diff --git a/README.md b/README.md new file mode 100644 index 0000000..c7b39ae --- /dev/null +++ b/README.md @@ -0,0 +1,102 @@ +=== Hesabix for WooCommerce === +Contributors: Mohammad Rezai +Tags: accounting, hesabix, woocommerce, jalali, invoice, integration, persian +Requires at least: 5.2 +Tested up to: 6.6.1 +Requires PHP: 7.4 +Stable tag: 1.0.0 +License: GPLv3 or later +License URI: https://www.gnu.org/licenses/gpl-3.0.html + +Modern, localized, and secure WooCommerce integration with Hesabix Cloud Accounting. Featuring full Jalali calendar support, real-time data sync, and advanced customization for Persian e-commerce. + +== 🧩 Overview == + +**Hesabix for WooCommerce** connects your online store with [Hesabix](https://hesabix.com), the powerful cloud-based accounting system built for Persian businesses. + +From real-time product, order, and customer sync to full Persian date support, this plugin is everything a modern Iranian online store needs to automate its bookkeeping. + +== ✨ Features == + +### 🔗 Seamless Integration +- Automatically syncs products, orders, and customers with your Hesabix account +- One-click synchronization for bulk data +- AJAX-powered UI for responsive operations + +### 📅 Persian Calendar Support +- Native Jalali calendar UI +- Gregorian ↔ Jalali date conversion +- Custom date filters and ranges + +### 💼 Smart Customer Handling +- Auto-create customers in Hesabix from WooCommerce orders +- National ID, economic code, and business info fields +- Custom checkout fields with flexible validation + +### 🧾 Invoice & Finance Management +- Instant invoice generation on new orders +- Freight and shipping cost handling +- Payment method mapping + +### ⚙️ Developer Tools +- Clean, modular code with hooks and filters +- Extendable data mappers for products and customers +- Debug logs and status monitoring + +### 🌐 Localization & UI +- Fully RTL and Persian language ready +- Modern, tabbed admin interface +- Responsive and mobile-friendly + +== 🛠️ Installation & Setup == + +1. Upload the plugin to `/wp-content/plugins/hesabix-woocommerce/` +2. Activate via **Plugins > Hesabix for WooCommerce** +3. Go to **WooCommerce > Hesabix Settings** +4. Enter your API Key (get it from your [Hesabix account](https://app.hesabix.com)) +5. Test connection and start syncing! + +== ❓ Frequently Asked Questions == + +**How do I get an API key?** +Log in to your Hesabix account and navigate to *Settings > API*. Copy the key and paste it into the plugin settings. + +**Is it compatible with Persian WooCommerce stores?** +Yes — fully RTL compatible, Persian translations included, and Jalali calendar support is native. + +**Can I control what data gets synced?** +Absolutely — toggle options for each data type and use filters to customize. + +**Does it work with subscription products?** +Currently designed for standard WooCommerce orders. + +**Is my data safe?** +Yes — we follow WordPress best practices including nonce verification, secure API connections, and local data handling. + +== 🖼️ Screenshots == + +1. Plugin Dashboard with sync status +2. Customer field customization +3. Jalali date picker for filtering +4. Invoice configuration +5. Product linking interface + +== 🌐 Resources == + +- [Official Website](https://hesabix.com) +- [User Guide](https://hesabix.com/school) +- [Support](https://hesabix.com/support) + +== 👨‍💻 Credits == + +**Developer**: Mohammad Rezai +**Website**: [pirouz.xyz](https://pirouz.xyz) + +== 🔐 License == + +This plugin is licensed under the GPLv3. You are free to modify, distribute, and use it under the terms of the license. + +== 🛡️ Privacy == + +No personal data is collected by this plugin. All communications are strictly between your WordPress site and Hesabix servers. + diff --git a/README.txt b/README.txt deleted file mode 100644 index 920f16c..0000000 --- a/README.txt +++ /dev/null @@ -1,35 +0,0 @@ -=== Hesabix Accounting === -Contributors: saeedsb, hamidprime, sepehr-najafi, Babak alizadeh -Tags: accounting cloud Hesabix -Requires at least: 5.2 -Tested up to: 6.6.1 -Requires PHP: 5.6 -Stable tag: 2.1.1 -License: GPLv2 or later -License URI: https://www.gnu.org/licenses/gpl-2.0.html - -Connect Hesabix Online Accounting to WooCommerce. - -== Description == -This plugin helps connect your (online) store to Hesabix online accounting software. By using this plugin, saving products, contacts, and orders in your store will also save them automatically in your Hesabix account. Besides that, just after a client pays a bill, the receipt document will be stored in Hesabix as well. Of course, you have to register your account in Hesabix first. To do so, visit Hesabix at the link here hesabix.com and sign up for free. After you signed up and entered your account, choose your business, then in the settings menu/API, you can find the API keys for the business and import them to the plugin settings. Now your module is ready to use. - -For more information and a full guide to how to use Hesabix and WooCommerce Plugin, visit Hesabix’s website and go to the “Accounting School” menu. - -== Installation == -1. Upload the plugin files to the `/wp-content/plugins/hesabixWCplugin` directory, or install the Hesabix plugin through the WordPress plugins screen directly. -2. Activate the plugin through the \'Plugins\' screen in WordPress -3. Use the Settings->Hesabix screen to configure the plugin - -== Screenshots == -1. API setting page -2. Catalog setting page -3. Customers setting page -4. Invoice setting page -5. Payment Methods setting page -6. Import and export setting page -7. Sync setting page -8. Log file - -== Changelog == -= 1.0.0 - 07.03.2024 = -* Initial stable release. \ No newline at end of file diff --git a/admin/class-hesabix-admin.php b/admin/class-hesabix-admin.php new file mode 100644 index 0000000..a170ab5 --- /dev/null +++ b/admin/class-hesabix-admin.php @@ -0,0 +1,2076 @@ +plugin_name = $plugin_name; + $this->version = $version; + $this->load_dependencies(); + add_action('wp_ajax_hesabix_get_sync_stats_ajax', array($this, 'hesabix_get_sync_stats_ajax')); + add_action('wp_ajax_hesabix_load_tab_content', array($this, 'hesabix_load_tab_content')); + add_action('wp_ajax_hesabix_save_customers_fields_ajax', array($this, 'hesabix_save_customers_fields_ajax')); + } + + public function hesabix_update_db_check() + { + $current_db_ver = get_site_option('hesabix_db_version'); + if ($current_db_ver === false || $current_db_ver < 1.1) { + global $wpdb; + $table_name = $wpdb->prefix . "hesabix"; + + $sql = "ALTER TABLE $table_name + ADD `id_ps_attribute` INT(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `id_ps`;"; + + if (!$wpdb->query($sql)) { + HesabixLogService::log(array("Cannot alter table $table_name. Current DB Version: $current_db_ver")); + } else { + update_option('hesabix_db_version', 1.1); + HesabixLogService::log(array("Alter table $table_name. Current DB Version: $current_db_ver")); + } + } + } + + public function enqueue_styles() + { + + if (isset($_GET['page']) && str_contains($_GET['page'], "hesabix")) { + ?> + + plugin_name, plugin_dir_url(__FILE__) . '../assets/css/hesabix-admin.css', array(), $this->version, 'all'); + wp_enqueue_style('bootstrap_css', plugin_dir_url(__FILE__) . '../assets/css/bootstrap.css', array(), $this->version, 'all'); + } + } + + public function enqueue_scripts() + { + + wp_enqueue_script($this->plugin_name, plugin_dir_url(__FILE__) . '../assets/js/hesabix.js', array('jquery'), $this->version, false); + + wp_localize_script($this->plugin_name, 'hesabix_ajax', array( + 'ajaxurl' => admin_url('admin-ajax.php'), + 'nonce' => wp_create_nonce('hesabix_ajax_nonce') + )); + + if (isset($_GET['page']) && str_contains($_GET['page'], "hesabix")) { + wp_enqueue_script('bootstrap_js', plugin_dir_url(__FILE__) . '../assets/js/bootstrap.bundle.min.js', array('jquery'), $this->version, false); + + } + } + + private function load_dependencies() + { + require_once plugin_dir_path(dirname(__FILE__)) . '/admin/partials/hesabix-admin-display.php'; + + require_once plugin_dir_path(dirname(__FILE__)) . '/admin/partials/hesabix-html-output.php'; + + require_once plugin_dir_path(dirname(__FILE__)) . '/admin/partials/hesabix-admin-setting.php'; + + require_once plugin_dir_path(dirname(__FILE__)) . '/admin/partials/hesabix-admin-functions.php'; + } + + public function hesabix_missing_notice() + { + echo '

' . sprintf(__('Hesabix Plugin requires the %s to work!', 'hesabix'), '' . __('WooCommerce', 'hesabix') . '') . '

'; + } + + public function hesabix_live_mode_notice() + { + echo '

' . __('Hesabix Plugin need to connect to Hesabix Accounting, Please check the API credential!', 'hesabix') . '

'; + } + + public function hesabix_business_expired_notice() + { + echo '

' . __('Cannot connect to Hesabix. Business expired.', 'hesabix') . '

'; + } + + public function hesabix_currency_notice() + { + echo '

' . __('Hesabix Plugin cannot works! because WooCommerce currency in not match with Hesabix.', 'hesabix') . '

'; + } + + public function hesabix_general_notices() + { + if (!empty($_REQUEST['submit_selected_orders_invoice_in_hesabix'])) { + if (!empty($_REQUEST['error_msg']) && $_REQUEST['error_msg'] == "select_max_10_items") { + printf( + '

%s

', + __('Error: Select maximum 10 orders. Due to some limitations in Hesabix API, sending too many requests in one minute is not possible.', 'hesabix') + ); + } else { + $success_count = intval($_REQUEST['success_count']); + printf('

%s %d

', __('Selected orders invoices have been saved. Number of saved invoices: ', 'hesabix'), $success_count); + } + } + } + + public function adminExportProductsCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + + $batch = wc_clean($_POST['batch']); + $totalBatch = wc_clean($_POST['totalBatch']); + $total = wc_clean($_POST['total']); + $updateCount = wc_clean($_POST['updateCount']); + + $func = new Hesabix_Admin_Functions(); + $result = $func->exportProducts($batch, $totalBatch, $total, $updateCount); + + if ($result['error']) { + if ($updateCount === -1) { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=export&productExportResult=false&error=-1'); + } else { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=export&productExportResult=false'); + } + } else { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=export&productExportResult=true&processed=' . $result['updateCount']); + } + + echo json_encode($result); + die(); + } + } + + public function adminImportProductsCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + + $batch = wc_clean($_POST['batch']); + $totalBatch = wc_clean($_POST['totalBatch']); + $total = wc_clean($_POST['total']); + $updateCount = wc_clean($_POST['updateCount']); + + $func = new Hesabix_Admin_Functions(); + $result = $func->importProducts($batch, $totalBatch, $total, $updateCount); + $import_count = $result['updateCount']; + + if ($result['error']) { + if ($import_count === -1) { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=export&productImportResult=false&error=-1'); + } else { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=export&productImportResult=false'); + } + } else { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=export&productImportResult=true&processed=' . $import_count); + } + + echo json_encode($result); + die(); + } + } + + public function adminExportProductsOpeningQuantityCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + + $batch = wc_clean($_POST['batch']); + $totalBatch = wc_clean($_POST['totalBatch']); + $total = wc_clean($_POST['total']); + + $func = new Hesabix_Admin_Functions(); + $result = $func->exportOpeningQuantity($batch, $totalBatch, $total); + if ($result['error']) { + if ($result['errorType'] == 'shareholderError') { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=export&productOpeningQuantityExportResult=false&shareholderError=true'); + } else if ($result['errorType'] == 'noProduct') { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=export&productOpeningQuantityExportResult=false&noProduct=true'); + } else { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=export&productOpeningQuantityExportResult=false'); + } + } else { + if ($result["done"] == true) + update_option('hesabix_use_export_product_opening_quantity', true); + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=export&productOpeningQuantityExportResult=true'); + } + + echo json_encode($result); + die(); + } + } + + public function adminExportCustomersCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + + $batch = wc_clean($_POST['batch']); + $totalBatch = wc_clean($_POST['totalBatch']); + $total = wc_clean($_POST['total']); + $updateCount = wc_clean($_POST['updateCount']); + + $func = new Hesabix_Admin_Functions(); + $result = $func->exportCustomers($batch, $totalBatch, $total, $updateCount); + + if ($result["error"]) { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=export&customerExportResult=false'); + } else { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=export&customerExportResult=true&processed=' . $result["updateCount"]); + } + echo json_encode($result); + + die(); + } + } + + public function adminSyncChangesCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + include(dirname(__FILE__) . '/../includes/class-hesabix-webhook.php'); + new Hesabix_Webhook(); + wp_send_json(array( + 'success' => true, + 'message' => __('changes synced successfully', 'hesabix') + )); + } + } + + public function admin_sync_products_callback() + { + if (!wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error('Security check failed'); + } + + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + $batch = wc_clean($_POST['batch']); + $totalBatch = wc_clean($_POST['totalBatch']); + $total = wc_clean($_POST['total']); + $func = new Hesabix_Admin_Functions(); + $result = $func->syncProducts($batch, $totalBatch, $total); + if ($result['error']) { + wp_send_json(array( + 'success' => false, + 'message' => __('Error syncing prices and inventory. Please check the logs.', 'hesabix') + )); + } else { + wp_send_json(array( + 'success' => true, + 'message' => __('Prices and inventory synced successfully', 'hesabix') + )); + } + } + } + + public function admin_sync_orders_callback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + $batch = wc_clean($_POST['batch']); + $totalBatch = wc_clean($_POST['totalBatch']); + $total = wc_clean($_POST['total']); + $updateCount = wc_clean($_POST['updateCount']); + $from_date = wc_clean($_POST['date']); + $end_date = wc_clean($_POST['endDate']); + $func = new Hesabix_Admin_Functions(); + $result = $func->syncOrders($from_date, $end_date, $batch, $totalBatch, $total, $updateCount); + if (!$result['error']) { + wp_send_json(array( + 'success' => true, + 'message' => __('Orders synchronized successfully.', 'hesabix') + )); + } else { + wp_send_json(array( + 'success' => false, + 'message' => $result['error'] + )); + } + } + } + + public function admin_update_products_callback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + $batch = wc_clean($_POST['batch']); + $totalBatch = wc_clean($_POST['totalBatch']); + $total = wc_clean($_POST['total']); + + $func = new Hesabix_Admin_Functions(); + $result = $func->updateProductsInHesabixBasedOnStore($batch, $totalBatch, $total); + + if ($result['error']) { + wp_send_json(array( + 'success' => false, + 'message' => __('Error updating products. Please check the logs.', 'hesabix') + )); + } else { + wp_send_json(array( + 'success' => true, + 'message' => __('Products updated successfully', 'hesabix') + )); + } + } + } + + public function admin_update_wc_products_callback() + { + if (!wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error('Security check failed'); + } + + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + $batch = wc_clean($_POST['batch']); + $totalBatch = wc_clean($_POST['totalBatch']); + $total = wc_clean($_POST['total']); + + $func = new Hesabix_Admin_Functions(); + $result = $func->updateWooCommerceProductsBasedOnHesabix($batch, $totalBatch, $total); + + if ($result['error']) { + wp_send_json(array( + 'success' => false, + 'message' => __('Error updating products. Please check the logs.', 'hesabix') + )); + } else { + wp_send_json(array( + 'success' => true, + 'message' => __('Products updated successfully', 'hesabix') + )); + } + } + } + + public function adminUpdateProductsWithFilterCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + + $offset = wc_clean($_POST['offset']); + $rpp = wc_clean($_POST['rpp']); + if (abs($rpp - $offset) <= 200) { + $func = new Hesabix_Admin_Functions(); + $result = $func->updateProductsInHesabixBasedOnStoreWithFilter($offset, $rpp); + + if ($result['error']) { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=sync&$productUpdateWithFilterResult=false'); + } else { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=sync&$productUpdateWithFilterResult=true'); + } + echo json_encode($result); + die(); + } else { + $result["redirectUrl"] = admin_url('admin.php?page=hesabix-option&tab=sync&$productUpdateWithFilterResult=false'); + echo json_encode($result); + die(); + } + } + } + + public function adminSubmitInvoiceCallback() + { + HesabixLogService::writeLogStr('Submit Invoice Manually'); + + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + $orderId = wc_clean($_POST['orderId']); + + $func = new Hesabix_Admin_Functions(); + $result = $func->setOrder($orderId); + if ($result) + $func->setOrderPayment($orderId); + + echo json_encode($result); + die(); + } + } + + public function adminClearPluginDataCallback() + { + + HesabixLogService::writeLogStr('Clear Plugin Data'); + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + + $hesabixApi = new Hesabix_Api(); + $result = $hesabixApi->fixClearTags(); + if (!$result->Success) { + + HesabixLogService::log(array("hesabix-Cannot clear tags. Error Message: " . (string) $result->ErrorMessage . ". Error Code: " . (string) $result->ErrorCode)); + } + + global $wpdb; + $options = $wpdb->get_results("SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%hesabix%'"); + foreach ($options as $option) { + delete_option($option->option_name); + } + + $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}hesabix"); + + die(); + } + } + + public function adminInstallPluginDataCallback() + { + + HesabixLogService::writeLogStr('Install Plugin Data'); + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + + require_once dirname(__FILE__) . '/includes/class-hesabix-activator.php'; + Hesabix_Activator::activate(); + + die(); + } + } + + public function admin_product_add_column($columns) + { + $hesabixArray = array("hesabix_code" => "کد در حسابیکس"); + $columns = $hesabixArray + $columns; + return $columns; + } + + public function admin_product_export_rows($rows, $products) + { + $rowsArray = explode("\n", $rows); + $exportRows = []; + + $reflection = new ReflectionClass($products); + $property = $reflection->getProperty('row_data'); + $property->setAccessible(true); + $productsArray = $property->getValue($products); + $matchingArray = []; + + if (!empty($productsArray)) { + foreach ($productsArray as $product) { + if (is_array($product) && isset($product['id'])) { + $wpFaService = new HesabixWpFaService(); + + if ($product["type"] == "variation") { + if (array_key_exists('parent_id', $product)) { + $parentId = $product['parent_id']; + $productParentId = explode(':', $parentId)[1]; + $wpFa = $wpFaService->getWpFaSearch($productParentId, $product['id'], '', "product"); + } + } elseif ($product["type"] == "simple" || $product["type"] == "variable") { + $wpFa = $wpFaService->getWpFaSearch($product['id'], 0, '', "product"); + } + + if (is_array($wpFa)) { + foreach ($wpFa as $item) { + if ($item->idWpAttribute != 0) { + $matchingArray[$item->idWpAttribute] = $item->idHesabix; + } else { + $matchingArray[$item->idWp] = $item->idHesabix; + } + } + } + } + } + } + + foreach ($rowsArray as $row) { + if (empty(trim($row))) { + continue; + } + $columns = str_getcsv($row); + $inserted = false; + + if (isset($columns[1])) { + foreach ($matchingArray as $wpId => $hesabixId) { + if ($columns[1] == $wpId && !$inserted) { + $columns[0] = $hesabixId; + $inserted = true; + break; + } + } + } + + if (!$inserted) { + $columns[0] = "کد ندارد"; + } + + $exportRows[] = implode(",", $columns); + } + + return implode("\n", $exportRows); + } + + public function hesabix_init_internal() + { + add_rewrite_rule('hesabix-webhook.php$', 'index.php?hesabix_webhook=1', 'top'); + } + + private function checkForSyncChanges() + { + $syncChangesLastDate = get_option('hesabix_sync_changes_last_date'); + if (!isset($syncChangesLastDate) || $syncChangesLastDate == false) { + add_option('hesabix_sync_changes_last_date', new DateTime()); + $syncChangesLastDate = new DateTime(); + } + + $nowDateTime = new DateTime(); + $diff = $nowDateTime->diff($syncChangesLastDate); + + if ($diff->i >= 4) { + HesabixLogService::writeLogStr('Sync Changes Automatically'); + update_option('hesabix_sync_changes_last_date', new DateTime()); + require_once plugin_dir_path(dirname(__FILE__)) . '/includes/class-hesabix-webhook.php'; + new Hesabix_Webhook(); + } + } + + public function hesabix_query_vars($query_vars) + { + $query_vars[] = 'hesabix_webhook'; + return $query_vars; + } + + public function custom_hesabix_column_order_list($columns) + { + $reordered_columns = array(); + + foreach ($columns as $key => $column) { + $reordered_columns[$key] = $column; + if ($key == 'order_status') { + + $reordered_columns['hesabix-column-invoice-number'] = __('Invoice in Hesabix', 'hesabix'); + $reordered_columns['hesabix-column-submit-invoice'] = __('Submit Invoice', 'hesabix'); + } + } + return $reordered_columns; + } + + public function custom_orders_list_column_content($column, $post_id) + { + + global $wpdb; + + if (get_option('woocommerce_custom_orders_table_enabled') == 'yes') { + switch ($column) { + case 'hesabix-column-invoice-number': + $product_id = $post_id->ID; + + $table_name = $wpdb->prefix . 'hesabix'; + $row = $wpdb->get_row( + $wpdb->prepare( + "SELECT id_hesabix FROM $table_name WHERE id_ps = %d AND obj_type = 'order'", + $product_id + ) + ); + + if (!empty($row)) { + echo '' . $row->id_hesabix . ''; + } else { + echo ''; + } + break; + + case 'hesabix-column-submit-invoice': + + $product_id = $post_id->ID; + echo ''; + echo __('Submit Invoice', 'hesabix'); + echo ''; + break; + } + } else { + switch ($column) { + case 'hesabix-column-invoice-number': + + $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "hesabix` WHERE `id_ps` = $post_id AND `obj_type` = 'order'"); + + + if (!empty($row)) + echo '' . $row->id_hesabix . ''; + else + echo ''; + break; + + case 'hesabix-column-submit-invoice': + echo '"; + echo __('Submit Invoice', 'hesabix'); + echo ''; + break; + } + } + } + + public function hesabix_parse_request(&$wp) + { + if (array_key_exists('hesabix_webhook', $wp->query_vars)) { + include(dirname(__FILE__) . '/includes/hesabix-webhook.php'); + exit(); + } + } + + public function custom_orders_list_bulk_action($actions) + { + $actions['submit_invoice_in_hesabix'] = __('Submit Invoice in Hesabix', 'hesabix'); + return $actions; + } + + public function custom_orders_list_bulk_action_run($redirect_to, $action, $post_ids) + { + if ($action !== 'submit_invoice_in_hesabix') + return $redirect_to; + + + HesabixLogService::writeLogStr("Submit selected orders invoice"); + + if (count($post_ids) > 10) + return $redirect_to = add_query_arg(array( + 'submit_selected_orders_invoice_in_hesabix' => '1', + 'error_msg' => 'select_max_10_items' + ), $redirect_to); + + $success_count = 0; + $func = new Hesabix_Admin_Functions(); + foreach ($post_ids as $orderId) { + $result = $func->setOrder($orderId); + if ($result) { + $success_count++; + $func->setOrderPayment($orderId); + } + } + + return $redirect_to = add_query_arg(array( + 'submit_selected_orders_invoice_in_hesabix' => '1', + 'success_count' => $success_count, + 'error_msg' => '0' + ), $redirect_to); + } + + public function hesabix_hook_edit_user(WP_User $user) + { + $wpFaService = new HesabixWpFaService(); + $code = isset($user) ? $wpFaService->getCustomerCodeByWpId($user->ID) : ''; + ?> +
+ + + + + +
+ +
+
+ +
+
+
+ getWpFaByHesabixId('customer', $user_hesabix_code); + $wpFa = $wpFaService->getWpFa('customer', $id_customer); + + if (!$wpFaOld || !$wpFa || $wpFaOld->id !== $wpFa->id) { + if ($wpFaOld) + $wpFaService->delete($wpFaOld); + + if ($wpFa) { + $wpFa->idHesabix = $user_hesabix_code; + $wpFaService->update($wpFa); + } else { + $wpFa = new WpFa(); + $wpFa->objType = 'customer'; + $wpFa->idWp = $id_customer; + $wpFa->idHesabix = intval($user_hesabix_code); + $wpFaService->save($wpFa); + } + } + } + + $function = new Hesabix_Admin_Functions(); + + if (get_option('hesabix_contact_automatically_save_in_hesabix') == 'yes') + $function->setContact($id_customer); + } + + public function hesabix_hook_delete_user($id_customer) + { + $wpFaService = new HesabixWpFaService(); + $id_obj = $wpFaService->getWpFaId('customer', $id_customer); + if ($id_obj != false) { + global $wpdb; + $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "hesabix` WHERE `id` = $id_obj AND `obj_type` = 'customer'"); + + if (is_object($row)) { + $hesabixApi = new Hesabix_Api(); + $hesabixApi->contactDelete($row->id_hesabix); + } + + global $wpdb; + $wpdb->delete($wpdb->prefix . 'hesabix', array('id_ps' => $id_customer)); + + + HesabixLogService::log(array("Customer deleted. Customer ID: $id_customer")); + } + } + + public function hesabix_hook_order_status_change($id_order, $from, $to) + { + HesabixLogService::writeLogStr("Order Status Hook"); + $function = new Hesabix_Admin_Functions(); + + $invoice_statuses = get_option('hesabix_invoice_status', array()); + if (!is_array($invoice_statuses)) { + if (is_string($invoice_statuses) && !empty($invoice_statuses)) { + $invoice_statuses = array_map('trim', explode(',', $invoice_statuses)); + } else { + $invoice_statuses = array(); + } + } + + foreach ($invoice_statuses as $status) { + + HesabixLogService::writeLogStr("status: $status"); + + if ($status == $to) { + $orderResult = $function->setOrder($id_order); + if ($orderResult) { + + $payment_statuses = get_option('hesabix_payment_status', array()); + if (!is_array($payment_statuses)) { + if (is_string($payment_statuses) && !empty($payment_statuses)) { + $payment_statuses = array_map('trim', explode(',', $payment_statuses)); + } else { + $payment_statuses = array(); + } + } + foreach ($payment_statuses as $statusPayment) { + if ($statusPayment == $to) + $function->setOrderPayment($id_order); + } + } + } + } + + $values = get_option('hesabix_invoice_return_status'); + if (is_array($values) || is_object($values)) { + foreach ($values as $status) { + if ($status == $to) + $function->setOrder($id_order, 2, $function->getInvoiceCodeByOrderId($id_order)); + } + } + } + + public function hesabix_hook_new_order($id_order, $order) + { + HesabixLogService::writeLogStr("New Order Hook"); + $function = new Hesabix_Admin_Functions(); + $orderStatus = wc_get_order($id_order)->get_status(); + $orderItems = $order->get_items(); + + $invoice_statuses = get_option('hesabix_invoice_status', array()); + if (!is_array($invoice_statuses)) { + if (is_string($invoice_statuses) && !empty($invoice_statuses)) { + $invoice_statuses = array_map('trim', explode(',', $invoice_statuses)); + } else { + $invoice_statuses = array(); + } + } + + foreach ($invoice_statuses as $status) { + + HesabixLogService::writeLogStr("status: $status"); + + if ($status == $orderStatus) { + $orderResult = $function->setOrder($id_order, 0, null, $orderItems); + if ($orderResult) { + + $payment_statuses = get_option('hesabix_payment_status', array()); + if (!is_array($payment_statuses)) { + if (is_string($payment_statuses) && !empty($payment_statuses)) { + $payment_statuses = array_map('trim', explode(',', $payment_statuses)); + } else { + $payment_statuses = array(); + } + } + foreach ($payment_statuses as $statusPayment) { + if ($statusPayment == $orderStatus) + $function->setOrderPayment($id_order); + } + } + } + } + + HesabixLogService::log(array($orderStatus)); + + $values = get_option('hesabix_invoice_return_status'); + if (is_array($values) || is_object($values)) { + foreach ($values as $status) { + if ($status == $orderStatus) + $function->setOrder($id_order, 2, $function->getInvoiceCodeByOrderId($id_order), $orderItems); + } + } + } + + public function hesabix_hook_payment_confirmation($id_order, $from, $to) + { + $payment_statuses = get_option('hesabix_payment_status', array()); + if (!is_array($payment_statuses)) { + if (is_string($payment_statuses) && !empty($payment_statuses)) { + $payment_statuses = array_map('trim', explode(',', $payment_statuses)); + } else { + $payment_statuses = array(); + } + } + + foreach ($payment_statuses as $status) { + if ($status == $to) { + $function = new Hesabix_Admin_Functions(); + $function->setOrderPayment($id_order); + } + } + } + + private $call_time = 1; + + public function hesabix_hook_new_product($id_product) + { + + if ($this->call_time === 1) { + $this->call_time++; + return; + } else { + $this->call_time = 1; + } + + if (get_option("hesabix_do_not_submit_product_automatically", "no") === "yes") + return; + $function = new Hesabix_Admin_Functions(); + $function->setItems(array($id_product)); + } + + public function hesabix_hook_save_product_variation($id_attribute) + { + + HesabixLogService::writeLogStr("hesabix_hook_save_product_variation"); + + if (get_option("hesabix_do_not_submit_product_automatically", "no") === "yes" || get_option("hesabix_do_not_submit_product_automatically", "no") == "1") { + + $variable_field_id = "hesabix_hesabix_item_code_" . $id_attribute; + $code = $_POST[$variable_field_id]; + $id_product = $_POST['product_id']; + + if ($code === "") + return; + + if (isset($code)) { + global $wpdb; + $row = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "hesabix` WHERE `id_hesabix` = " . $code . " AND `obj_type` = 'product'"); + + if (is_object($row)) { + if ($row->id_ps == $id_product && $row->id_ps_attribute == $id_attribute) { + return false; + } + + echo '

' . __('The new Item code already used for another Item', 'hesabix') . '

'; + + HesabixLogService::log(array("The new Item code already used for another Item. Product ID: $id_product")); + } else { + $row2 = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "hesabix` WHERE `id_ps` = $id_product AND `obj_type` = 'product' AND `id_ps_attribute` = $id_attribute"); + + if (is_object($row2)) { + $wpdb->update($wpdb->prefix . 'hesabix', array( + 'id_hesabix' => (int) $code, + ), array( + 'id_ps' => $id_product, + 'id_ps_attribute' => $id_attribute, + 'obj_type' => 'product', + )); + } else if ((int) $code !== 0) { + $wpdb->insert($wpdb->prefix . 'hesabix', array( + 'id_hesabix' => (int) $code, + 'id_ps' => (int) $id_product, + 'id_ps_attribute' => $id_attribute, + 'obj_type' => 'product', + )); + } + } + } + + + $func = new Hesabix_Admin_Functions(); + $wpFaService = new HesabixWpFaService(); + $code = $wpFaService->getProductCodeByWpId($id_product, $id_attribute); + if ($code == null) { + $func->setItems(array($id_product)); + } + } + } + + public function hesabix_hook_delete_product($id_product) + { + + HesabixLogService::writeLogStr("Product Delete Hook"); + + $func = new Hesabix_Admin_Functions(); + $wpFaService = new HesabixWpFaService(); + + $hesabixApi = new Hesabix_Api(); + global $wpdb; + + $variations = $func->getProductVariations($id_product); + if ($variations != false) { + foreach ($variations as $variation) { + $id_attribute = $variation->get_id(); + $code = $wpFaService->getProductCodeByWpId($id_product, $id_attribute); + if ($code != false) { + $hesabixApi->itemDelete($code); + $wpdb->delete($wpdb->prefix . 'hesabix', array('id_hesabix' => $code, 'obj_type' => 'product')); + + HesabixLogService::log(array("Product variation deleted. Product ID: $id_product-$id_attribute")); + } + } + } + + $code = $wpFaService->getProductCodeByWpId($id_product); + + if ($code != false) { + $hesabixApi->itemDelete($code); + $wpdb->delete($wpdb->prefix . 'hesabix', array('id_hesabix' => $code, 'obj_type' => 'product')); + + HesabixLogService::log(array("Product deleted. Product ID: $id_product")); + } + } + + public function hesabix_hook_delete_product_variation($id_attribute) + { + $hesabixApi = new Hesabix_Api(); + global $wpdb; + $row = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "hesabix` WHERE `id_ps_attribute` = $id_attribute AND `obj_type` = 'product'"); + + if (is_object($row)) { + $hesabixApi->itemDelete($row->id_hesabix); + + $wpdb->delete($wpdb->prefix . 'hesabix', array('id' => $row->id)); + + HesabixLogService::log(array("Product variation deleted. Product ID: $row->id_ps-$id_attribute")); + } + } + + public function hesabix_hook_product_options_general_product_data() + { + $wpFaService = new HesabixWpFaService(); + $value = isset($_GET['post']) ? $wpFaService->getProductCodeByWpId($_GET['post']) : ''; + $args = array( + 'id' => 'hesabix_hesabix_item_code_0', + 'label' => __('Hesabix base item code', 'hesabix'), + 'desc_tip' => true, + 'description' => __('The base Item code of this product in Hesabix, if you want to map this product to another item in Hesabix, enter the new Item code.', 'hesabix'), + 'value' => $value, + 'type' => 'number', + ); + woocommerce_wp_text_input($args); + } + + public function hesabix_hook_process_product_meta($post_id) + { + $itemCode = isset($_POST['hesabix_hesabix_item_code_0']) ? $_POST['hesabix_hesabix_item_code_0'] : ''; + + if ($itemCode === "") + return; + + if (isset($itemCode)) { + global $wpdb; + $row = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "hesabix` WHERE `id_hesabix` = " . $itemCode . " AND `obj_type` = 'product'"); + + if (is_object($row)) { + echo '

' . __('The new Item code already used for another Item', 'hesabix') . '

'; + + HesabixLogService::log(array("The new Item code already used for another Item. Product ID: $post_id")); + } else { + $row2 = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "hesabix` WHERE `id_ps` = $post_id AND `obj_type` = 'product' AND `id_ps_attribute` = 0"); + if (is_object($row2)) { + $wpdb->update($wpdb->prefix . 'hesabix', array( + 'id_hesabix' => (int) $itemCode, + ), array( + 'id_ps' => $post_id, + 'id_ps_attribute' => 0, + 'obj_type' => 'product', + )); + } else if ((int) $itemCode !== 0) { + $wpdb->insert($wpdb->prefix . 'hesabix', array( + 'id_hesabix' => (int) $itemCode, + 'id_ps' => (int) $post_id, + 'id_ps_attribute' => 0, + 'obj_type' => 'product', + )); + } + } + } + } + + public function hesabix_hook_product_after_variable_attributes($loop, $variation_data, $variation) + { + $wpFaService = new HesabixWpFaService(); + $value = isset($_POST['product_id']) ? $wpFaService->getProductCodeByWpId($_POST['product_id'], $variation->ID) : ''; + $args = array( + 'id' => 'hesabix_hesabix_item_code_' . $variation->ID, + 'label' => __('Hesabix variable item code', 'hesabix'), + 'desc_tip' => true, + 'description' => __('The variable Item code of this product variable in Hesabix, if you want to map this product to another item in Hesabix, enter the new Item code.', 'hesabix'), + 'value' => $value, + ); + woocommerce_wp_text_input($args); + } + + public function adminCleanLogFileCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + $func = new Hesabix_Admin_Functions(); + $result = $func->cleanLogFile(); + + if ($result) { + $redirect_url = admin_url('admin.php?page=hesabix-option&tab=log&cleanLogResult=true'); + } else { + $redirect_url = admin_url('admin.php?page=hesabix-option&tab=log&cleanLogResult=false'); + } + echo $redirect_url; + + die(); + } + } + + function add_hesabix_product_data_tab($product_data_tabs) + { + $product_data_tabs['hesabix'] = array( + 'label' => __('Hesabix', 'hesabix'), + 'target' => 'panel_product_data_hesabix', + ); + return $product_data_tabs; + } + + function add_hesabix_product_data_fields() + { + global $woocommerce, $post, $product; + + $funcs = new Hesabix_Admin_Functions(); + $items = array(); + $id_product = $post->ID; + $product = wc_get_product($id_product); + + if ($product->get_status() === "auto-draft") { + ?> +
+ هنوز محصول ذخیره نشده است. +
+ پس از ذخیره محصول، در این قسمت می توانید ارتباط محصول و متغیرهای آن با حسابیکس + را مدیریت کنید. +
+ get_stock_quantity(); + $items[0]["Id"] = $id_product; + $i = 1; + + $variations = $funcs->getProductVariations($id_product); + if ($variations) { + foreach ($variations as $variation) { + $items[] = HesabixItemService::mapProductVariation($product, $variation, $id_product, false); + $items[$i]["Quantity"] = $variation->get_stock_quantity(); + $items[$i]["Id"] = $variation->get_id(); + $i++; + } + } + + ?> +
+ + + + + + + + + + + + + + + + + + + + + +
نام کالاکد در حسابیکسذخیره کدحذف ارتباطبروزرسانی قیمت و موجودیقیمتموجودی
" id="hesabix-item-" + style="width: 75px;" class="hesabix-item-code" data-id="">" + class="button hesabix-item-save">" + class="button hesabix-item-delete-link">" + class="button button-primary hesabix-item-update">"> + + ">
+ + + + + +
+ + #hesabixID { + width: 5vw; + color: #2271b1; + } + #hesabixID a { + width: 100%; + } + '; + return array_slice($columns, 0, 3, true) + array('hesabixID' => 'کد حسابیکس') + array_slice($columns, 3, count($columns) - 3, true); + } + + function admin_products_hesabixId_column_content($column) + { + $funcs = new Hesabix_Admin_Functions(); + $items = array(); + $id_product = get_the_ID(); + $product = wc_get_product($id_product); + + $items[] = HesabixItemService::mapProduct($product, $id_product, false); + $i = 1; + + $variations = $funcs->getProductVariations($id_product); + if ($variations) { + foreach ($variations as $variation) { + $items[] = HesabixItemService::mapProductVariation($product, $variation, $id_product, false); + $i++; + } + } + + echo '
'; + foreach ($items as $item) { + if ($column == 'hesabixID') { + $hesabixId = $item["code"]; + echo "" . $hesabixId . " " . ""; + } + } + echo '
'; + } + + function adminChangeProductCodeCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + + $productId = (int) wc_clean($_POST['productId']); + $attributeId = (int) wc_clean($_POST['attributeId']); + if ($productId == $attributeId) + $attributeId = 0; + $code = (int) wc_clean($_POST['code']); + $result = array(); + + if (!$code) { + $result["error"] = true; + $result["message"] = "کد کالا وارد نشده است."; + echo json_encode($result); + die(); + return; + } + + $wpFaService = new HesabixWpFaService(); + $wpFa = $wpFaService->getWpFaByHesabixId('product', $code); + if ($wpFa) { + $result["error"] = true; + $result["message"] = "این کد به کالای دیگری متصل است. \n" . $wpFa->idWp . "-" . $wpFa->idWpAttribute; + echo json_encode($result); + die(); + return; + } + + $api = new Hesabix_Api(); + $response = $api->itemGet($code); + if (!$response->Success) { + $result["error"] = true; + $result["message"] = "کالایی با کد وارد شده در حسابیکس پیدا نشد."; + echo json_encode($result); + die(); + return; + } + + $wpFa = $wpFaService->getWpFa('product', $productId, $attributeId); + if ($wpFa) { + $wpFa->idHesabix = $code; + $wpFaService->update($wpFa); + } else { + $wpFa = new WpFa(); + $wpFa->idHesabix = $code; + $wpFa->idWp = $productId; + $wpFa->idWpAttribute = $attributeId; + $wpFa->objType = 'product'; + $wpFaService->save($wpFa); + } + $result["error"] = false; + echo json_encode($result); + die(); + } + } + + function adminDeleteProductLinkCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + $productId = wc_clean($_POST['productId']); + $attributeId = wc_clean($_POST['attributeId']); + if ($productId == $attributeId) + $attributeId = 0; + $result = array(); + + $wpFaService = new HesabixWpFaService(); + $wpFa = $wpFaService->getWpFa('product', $productId, $attributeId); + if ($wpFa) { + $wpFaService->delete($wpFa); + HesabixLogService::writeLogStr("حذف ارتباط کالا. کد کالا: " . $productId . "-" . "کد متغیر:" . $attributeId); + } + + $result["error"] = false; + echo json_encode($result); + die(); + } + } + + function adminUpdateProductCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + + if ( + get_option('hesabix_item_update_price', 'no') == 'no' && + get_option('hesabix_item_update_quantity', 'no') == 'no' + ) { + $result["error"] = true; + $result["message"] = "خطا: در تنظیمات افزونه، گزینه های بروزرسانی قیمت و موجودی محصول بر اساس حسابیکس فعال نیستند."; + echo json_encode($result); + die(); + } + + $productId = wc_clean($_POST['productId']); + $attributeId = wc_clean($_POST['attributeId']); + + if (get_option('hesabix_item_update_quantity', 'no') == 'yes') + update_post_meta($attributeId, '_manage_stock', 'yes'); + + if ($productId == $attributeId) + $attributeId = 0; + $result = array(); + + $wpFaService = new HesabixWpFaService(); + $wpFa = $wpFaService->getWpFa('product', $productId, $attributeId); + if ($wpFa) { + + $api = new Hesabix_Api(); + // $warehouse = get_option('hesabix_item_update_quantity_based_on', "-1"); + // if ($warehouse == "-1") + // $response = $api->itemGet($wpFa->idHesabix); + // else { + // $response = $api->itemGetQuantity($warehouse, array($wpFa->idHesabix)); + // } + + $response = $api->itemGet($wpFa->idHesabix); + + if ($response->Success) { + // $item = $warehouse == "-1" ? $response->Result : $response->Result[0]; + $item = $response->Result; + $newProps = Hesabix_Admin_Functions::setItemChanges($item); + $result["error"] = false; + $result["newPrice"] = $newProps["newPrice"]; + $result["newQuantity"] = $newProps["newQuantity"]; + } else { + $result["error"] = true; + $result["message"] = "کالا در حسابیکس پیدا نشد."; + } + } + + echo json_encode($result); + die(); + } + } + + function adminChangeProductsCodeCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + $wpFaService = new HesabixWpFaService(); + + $productId = (int) wc_clean($_POST['productId']); + $itemsData = wc_clean($_POST['itemsData'], true); + $result = array(); + $codes = []; + + foreach ($itemsData as $itemData) { + $attributeId = (int) $itemData["attributeId"]; + $code = (int) $itemData["code"]; + if ($productId == $attributeId) + $attributeId = 0; + $codes[] = str_pad($code, 6, "0", STR_PAD_LEFT); + + if (!$code) { + $result["error"] = true; + $result["message"] = "کد کالا وارد نشده است."; + echo json_encode($result); + die(); + return; + } + + $wpFa = $wpFaService->getWpFaByHesabixId('product', $code); + $wpFa2 = $wpFaService->getWpFa('product', $productId, $attributeId); + if ($wpFa && $wpFa2 && $wpFa->id != $wpFa2->id) { + $result["error"] = true; + $result["message"] = "این کد ($code) به کالای دیگری متصل است. \n" . $wpFa->idWp . "-" . $wpFa->idWpAttribute; + echo json_encode($result); + die(); + return; + } + } + + $api = new Hesabix_Api(); + $response = $api->itemGetItemsByCodes(array('values' => $codes)); + if ($response->Success) { + $items = $response->result; + foreach ($codes as $code) { + $found = false; + foreach ($items as $item) { + if ($item->code == $code) + $found = true; + } + if (!$found) { + $result["error"] = true; + $result["message"] = "کالایی با کد $code در حسابیکس پیدا نشد."; + echo json_encode($result); + die(); + return; + } + } + } else { + $result["error"] = true; + $result["message"] = "کالایی با کد وارد شده در حسابیکس پیدا نشد."; + echo json_encode($result); + die(); + return; + } + + + foreach ($itemsData as $itemData) { + $attributeId = (int) $itemData["attributeId"]; + $code = (int) $itemData["code"]; + if ($productId == $attributeId) + $attributeId = 0; + + $wpFa = $wpFaService->getWpFa('product', $productId, $attributeId); + if ($wpFa) { + $wpFa->idHesabix = $code; + $wpFaService->update($wpFa); + } else { + $wpFa = new WpFa(); + $wpFa->idHesabix = $code; + $wpFa->idWp = $productId; + $wpFa->idWpAttribute = $attributeId; + $wpFa->objType = 'product'; + $wpFaService->save($wpFa); + } + } + + $result["error"] = false; + echo json_encode($result); + die(); + } + } + + function adminDeleteProductsLinkCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + + $productId = wc_clean($_POST['productId']); + $result = array(); + + $wpFaService = new HesabixWpFaService(); + $wpFaService->deleteAll($productId); + HesabixLogService::writeLogStr("حذف ارتباط کالاها. کد کالا: " . $productId); + + $result["error"] = false; + echo json_encode($result); + die(); + } + } + + function adminUpdateProductAndVariationsCallback() + { + if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { + + if ( + get_option('hesabix_item_update_price', 'no') == 'no' && + get_option('hesabix_item_update_quantity', 'no') == 'no' + ) { + $result["error"] = true; + $result["message"] = "خطا: در تنظیمات افزونه، گزینه های بروزرسانی قیمت و موجودی محصول بر اساس حسابیکس فعال نیستند."; + echo json_encode($result); + die(); + } + + + $api = new Hesabix_Api(); + $wpFaService = new HesabixWpFaService(); + + $productId = wc_clean($_POST['productId']); + $productAndCombinations = $wpFaService->getProductAndCombinations($productId); + $result = array(); + if (count($productAndCombinations) == 0) { + $result["error"] = true; + $result["message"] = "هیچ ارتباطی پیدا نشد."; + echo json_encode($result); + die(); + } + $codes = []; + $hesabix_item_update_quantity = get_option('hesabix_item_update_quantity', 'no'); + foreach ($productAndCombinations as $p) { + $codes[] = str_pad($p->idHesabix, 6, "0", STR_PAD_LEFT); + + if ($hesabix_item_update_quantity == 'yes') + update_post_meta($p->idWpAttribute == 0 ? $p->idWp : $p->idWpAttribute, '_manage_stock', 'yes'); + } + + // $warehouse = get_option('hesabix_item_update_quantity_based_on', "-1"); + // if ($warehouse == "-1") + // $response = $api->itemGetItemsByCodes($codes); + // else { + // $response = $api->itemGetQuantity($warehouse, $codes); + // } + + $response = $api->itemGetItemsByCodes($codes); + + if ($response->Success) { + // $items = $warehouse == "-1" ? $response->Result->List : $response->Result; + $items = $response->Result->List; + $newData = []; + $result["error"] = false; + foreach ($items as $item) { + $newProps = Hesabix_Admin_Functions::setItemChanges($item); + $wpFa = $wpFaService->getWpFaByHesabixId('product', $item->Code); + $newData[] = array( + "newPrice" => $newProps["newPrice"], + "newQuantity" => $newProps["newQuantity"], + "attributeId" => $wpFa->idWpAttribute > 0 ? $wpFa->idWpAttribute : $wpFa->idWp + ); + } + $result["newData"] = $newData; + } else { + $result["error"] = true; + $result["message"] = "کالایی با کد وارد شده در حسابیکس پیدا نشد."; + echo json_encode($result); + die(); + return; + } + + echo json_encode($result); + die(); + } + } + + function add_additional_fields_to_checkout($fields) + { + $add_fields_option = get_option('hesabix_contact_add_fields'); + + if ($add_fields_option !== '1') { + return $fields; + } + + $NationalCode_isActive = get_option('hesabix_contact_NationalCode_checkbox_hesabix'); + $EconomicCode_isActive = get_option('hesabix_contact_EconomicCode_checkbox_hesabix'); + $RegistrationNumber_isActive = get_option('hesabix_contact_RegistrationNumber_checkbox_hesabix'); + $Website_isActive = get_option('hesabix_contact_Website_checkbox_hesabix'); + + $NationalCode_isRequired = get_option('hesabix_contact_NationalCode_isRequired_hesabix') === 'yes'; + $EconomicCode_isRequired = get_option('hesabix_contact_EconomicCode_isRequired_hesabix') === 'yes'; + $RegistrationNumber_isRequired = get_option('hesabix_contact_RegistrationNumber_isRequired_hesabix') === 'yes'; + $Website_isRequired = get_option('hesabix_contact_Website_isRequired_hesabix') === 'yes'; + + + if ($NationalCode_isActive == 'yes') { + $fields['billing']['billing_hesabix_nationalcode'] = array( + 'label' => __('National code', 'hesabix'), + 'placeholder' => __('please enter your National code', 'hesabix'), + 'priority' => 30, + 'required' => $NationalCode_isRequired, + 'clear' => true, + 'maxlength' => 10, + ); + } + + if ($EconomicCode_isActive == 'yes') { + $fields['billing']['billing_hesabix_economiccode'] = array( + 'label' => __('Economic code', 'hesabix'), + 'placeholder' => __('please enter your Economic code', 'hesabix'), + 'priority' => 31, + 'required' => $EconomicCode_isRequired, + 'clear' => true + ); + } + + if ($RegistrationNumber_isActive == 'yes') { + $fields['billing']['billing_hesabix_registerationnumber'] = array( + 'label' => __('Registration number', 'hesabix'), + 'placeholder' => __('please enter your Registration number', 'hesabix'), + 'priority' => 32, + 'required' => $RegistrationNumber_isRequired, + 'clear' => true + ); + } + + if ($Website_isActive == 'yes') { + $fields['billing']['billing_hesabix_website'] = array( + 'type' => 'url', + 'label' => __('Website', 'hesabix'), + 'placeholder' => __('please enter your Website address', 'hesabix'), + 'priority' => 33, + 'required' => $Website_isRequired, + 'clear' => true, + ); + } + return $fields; + } + + function show_additional_fields_in_order_detail($order) + { + + $add_fields_option = get_option('hesabix_contact_add_fields'); + if ($add_fields_option !== '1') { + return; + } + + + $orderId = $order->get_id(); + $NationalCode = '_billing_hesabix_nationalcode'; + $EconomicCode = '_billing_hesabix_economiccode'; + $RegistrationNumber = '_billing_hesabix_registerationnumber'; + $Website = '_billing_hesabix_website'; + + $NationalCode_isActive = get_option('hesabix_contact_NationalCode_checkbox_hesabix'); + $EconomicCode_isActive = get_option('hesabix_contact_EconomicCode_checkbox_hesabix'); + $RegistrationNumber_isActive = get_option('hesabix_contact_RegistrationNumber_checkbox_hesabix'); + $Website_isActive = get_option('hesabix_contact_Website_checkbox_hesabix'); + + if ($NationalCode_isActive == 'yes') { + echo '

' . __('National code', 'hesabix') . ': ' . '
' . '' . get_post_meta($orderId, $NationalCode, true) . '

'; + } + + if ($EconomicCode_isActive == 'yes') + echo '

' . __('Economic code', 'hesabix') . ': ' . '
' . '' . get_post_meta($orderId, $EconomicCode, true) . '

'; + + if ($RegistrationNumber_isActive == 'yes') + echo '

' . __('Registration number', 'hesabix') . ': ' . '
' . '' . get_post_meta($orderId, $RegistrationNumber, true) . '

'; + + if ($Website_isActive == 'yes') + echo '

' . __('Website', 'hesabix') . ': ' . '
' . '' . get_post_meta($orderId, $Website, true) . '

'; + } + + public function admin_get_home_stats_callback() + { + + if (!wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_die('Security check failed'); + } + + + $products_data = Hesabix_Setting::getProductsCount(); + $products_count = $products_data['storeProductsCount']; + $customers_count = Hesabix_Setting::getCustomersCount(); + $orders_count = Hesabix_Setting::getOrdersCount(); + + + $is_connected = $this->quickCheckHesabixConnection(); + + + $response = array( + 'success' => true, + 'data' => array( + 'products_count' => number_format($products_count), + 'customers_count' => number_format($customers_count), + 'orders_count' => number_format($orders_count), + 'is_connected' => $is_connected, + 'connected_text' => $is_connected ? __('Connected', 'hesabix') : __('Not Connected', 'hesabix'), + 'products_label' => __('Total Products', 'hesabix'), + 'customers_label' => __('Total Customers', 'hesabix'), + 'orders_label' => __('Total Orders', 'hesabix'), + 'status_label' => __('Hesabix Status', 'hesabix') + ) + ); + + wp_send_json($response); + } + + private function checkHesabixConnection() + { + + $api_key = get_option('hesabix_account_api'); + if (!$api_key) { + return false; + } + + try { + + $hesabix_api = new Hesabix_Api(); + $currency_response = $hesabix_api->settingGetCurrency(); + + if ($currency_response && is_object($currency_response) && $currency_response->Success) { + return true; + } + + return false; + } catch (Exception $e) { + return false; + } + } + + private function silentCheckHesabixConnection() + { + + $api_key = get_option('hesabix_account_api'); + if (!$api_key) { + return false; + } + + try { + + $hesabix_api = new Hesabix_Api(); + $currency_response = $hesabix_api->settingGetCurrency(); + + if ($currency_response && is_object($currency_response) && $currency_response->Success) { + return true; + } + + return false; + } catch (Exception $e) { + return false; + } + } + + private function quickCheckHesabixConnection() + { + + $api_key = get_option('hesabix_account_api'); + $live_mode = get_option('hesabix_live_mode', 0); + + return !empty($api_key) && $live_mode == 1; + } + + public function admin_check_for_updates_callback() + { + + if (!wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_die('Security check failed'); + } + + try { + $plugin_stats = wp_remote_get('https://hesabix.dragonizzer.ir/api/wordpress/plugin/stats'); + + if ($plugin_stats && !is_wp_error($plugin_stats) && $plugin_stats['response']['code'] == 200) { + + $json_data = json_decode($plugin_stats['body']); + + if ($json_data && isset($json_data->Success) && $json_data->Success) { + $current_version = HESABIX_VERSION; + $latest_version = $json_data->Result->version; + + $is_update_available = version_compare($current_version, $latest_version, '<'); + + $response = array( + 'success' => true, + 'data' => array( + 'current_version' => $current_version, + 'latest_version' => $latest_version, + 'is_update_available' => $is_update_available, + 'download_url' => $json_data->Result->download_url, + 'changelog' => $json_data->Result->changelog, + 'statistics' => $json_data->Result->statistics + ) + ); + } else { + $response = array( + 'success' => false, + 'message' => __('Failed to check for updates', 'hesabix') + ); + } + } else { + $response = array( + 'success' => false, + 'message' => __('Failed to check for updates', 'hesabix') + ); + } + } catch (Exception $e) { + $response = array( + 'success' => false, + 'message' => __('Error checking for updates', 'hesabix') + ); + } + + wp_send_json($response); + } + + public function adminSaveApiSettingsCallback() + { + check_ajax_referer('hesabix_ajax_nonce', 'nonce'); + + try { + $api_key = sanitize_text_field($_POST['api_key'] ?? ''); + $api_address = sanitize_text_field($_POST['api_address'] ?? '0'); + $custom_api_address = sanitize_text_field($_POST['custom_api_address'] ?? ''); + + update_option('hesabix_account_api', $api_key); + update_option('hesabix_api_address', $api_address); + update_option('hesabix_custom_api_address', $custom_api_address); + + + Hesabix_Setting::hesabix_set_webhook(false); + + wp_send_json_success(array( + 'message' => __('Settings saved successfully', 'hesabix') + )); + + } catch (Exception $e) { + wp_send_json_error(array('message' => $e->getMessage())); + } + } + + public function adminTestApiConnectionCallback() + { + check_ajax_referer('hesabix_ajax_nonce', 'nonce'); + + try { + $api_key = get_option('hesabix_account_api'); + $api_address = get_option('hesabix_api_address', 0); + + if (!$api_key) { + wp_send_json_error(array('message' => __('API key not configured', 'hesabix'))); + return; + } + + $is_connected = $this->quickCheckHesabixConnection(); + + if (!$is_connected) { + wp_send_json_error(array('message' => __('Connection failed. Please check your API key and try again.', 'hesabix'))); + return; + } + + wp_send_json_success(array( + 'message' => __('Connection successful!', 'hesabix'), + 'business_info' => $data['data'] ?? array() + )); + + } catch (Exception $e) { + wp_send_json_error(array('message' => $e->getMessage())); + } + } + + public function hesabix_get_sync_stats_ajax() + { + + if (!wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error('Security check failed'); + } + + $storeProductsCount = Hesabix_Setting::getProductCountsInStore(); + $hesabixProductsCount = Hesabix_Setting::getProductCountsInHesabix(); + $linkedProductsCount = Hesabix_Setting::getLinkedProductsCount(); + + wp_send_json_success(array( + 'storeProductsCount' => $storeProductsCount, + 'hesabixProductsCount' => $hesabixProductsCount, + 'linkedProductsCount' => $linkedProductsCount + )); + } + + public function hesabix_load_tab_content() + { + + if (!wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error('Security check failed'); + } + + $tab = sanitize_text_field($_POST['tab']); + + + $api_required_tabs = array('catalog', 'customers', 'invoice', 'sync'); + + + if (in_array($tab, $api_required_tabs)) { + $is_connected = $this->quickCheckHesabixConnection(); + + if (!$is_connected) { + + $error_message = '
+
+ +
+

' . __('API Connection Required', 'hesabix') . '

+

' . __('This tab requires a valid API connection. Please configure your API settings from the API tab first.', 'hesabix') . '

+
+ +
+
'; + + wp_send_json_success(array('content' => $error_message)); + return; + } + } + + + ob_start(); + + + switch ($tab) { + case 'home': + do_action('hesabix_home_setting_save_field'); + do_action('hesabix_home_setting'); + break; + case 'extra': + + do_action('hesabix_extra_setting'); + break; + case 'catalog': + do_action('hesabix_catalog_setting'); + break; + case 'customers': + do_action('hesabix_customers_setting'); + break; + case 'invoice': + do_action('hesabix_invoice_setting'); + break; + case 'api': + do_action('hesabix_api_setting_save_field'); + do_action('hesabix_api_setting'); + break; + case 'export': + do_action('hesabix_export_setting'); + break; + case 'sync': + do_action('hesabix_sync_setting'); + break; + case 'log': + do_action('hesabix_log_setting'); + break; + default: + wp_send_json_error('Invalid tab'); + break; + } + + $content = ob_get_clean(); + + wp_send_json_success(array('content' => $content)); + } + + public function hesabix_update_customers_ajax() + { + + if (!wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error('Security check failed'); + } + + try { + $function = new Hesabix_Admin_Functions(); + + + $customers = get_users(array( + 'role' => 'customer', + 'number' => -1, + 'fields' => 'ID' + )); + + $success_count = 0; + $error_count = 0; + $errors = array(); + + foreach ($customers as $customer_id) { + $result = $function->setContact($customer_id); + if ($result) { + $success_count++; + } else { + $error_count++; + $errors[] = "Customer ID: $customer_id"; + } + } + + $response = array( + 'success' => true, + 'message' => __('Customers successfully updated in Hesabix.', 'hesabix'), + 'data' => array( + 'success_count' => $success_count, + 'error_count' => $error_count, + 'errors' => $errors + ) + ); + + wp_send_json_success($response); + + } catch (Exception $e) { + wp_send_json_error(array( + 'message' => __('Error updating customers: ', 'hesabix') . $e->getMessage() + )); + } + } + + public function hesabix_save_customers_fields_ajax() + { + + if (!wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error('Security check failed'); + } + + try { + + $fields_to_save = array( + 'hesabix_contact_add_fields' => isset($_POST['addFieldsRadio']) ? sanitize_text_field($_POST['addFieldsRadio']) : '', + 'hesabix_contact_NationalCode_checkbox_hesabix' => isset($_POST['nationalCodeCheck']) ? sanitize_text_field($_POST['nationalCodeCheck']) : 'no', + 'hesabix_contact_NationalCode_isRequired_hesabix' => isset($_POST['nationalCodeRequired']) ? sanitize_text_field($_POST['nationalCodeRequired']) : 'no', + 'hesabix_contact_NationalCode_text_hesabix' => isset($_POST['nationalCode']) ? sanitize_text_field($_POST['nationalCode']) : '', + 'hesabix_contact_EconomicCode_checkbox_hesabix' => isset($_POST['economicCodeCheck']) ? sanitize_text_field($_POST['economicCodeCheck']) : 'no', + 'hesabix_contact_EconomicCode_isRequired_hesabix' => isset($_POST['economicCodeRequired']) ? sanitize_text_field($_POST['economicCodeRequired']) : 'no', + 'hesabix_contact_EconomicCode_text_hesabix' => isset($_POST['economicCode']) ? sanitize_text_field($_POST['economicCode']) : '', + 'hesabix_contact_RegistrationNumber_checkbox_hesabix' => isset($_POST['registrationNumberCheck']) ? sanitize_text_field($_POST['registrationNumberCheck']) : 'no', + 'hesabix_contact_RegistrationNumber_isRequired_hesabix' => isset($_POST['registrationNumberRequired']) ? sanitize_text_field($_POST['registrationNumberRequired']) : 'no', + 'hesabix_contact_RegistrationNumber_text_hesabix' => isset($_POST['registrationNumber']) ? sanitize_text_field($_POST['registrationNumber']) : '', + 'hesabix_contact_Website_checkbox_hesabix' => isset($_POST['websiteCheck']) ? sanitize_text_field($_POST['websiteCheck']) : 'no', + 'hesabix_contact_Website_isRequired_hesabix' => isset($_POST['websiteRequired']) ? sanitize_text_field($_POST['websiteRequired']) : 'no', + 'hesabix_contact_Website_text_hesabix' => isset($_POST['website']) ? sanitize_text_field($_POST['website']) : '', + ); + + $success = true; + foreach ($fields_to_save as $option_name => $option_value) { + $result = update_option($option_name, $option_value); + if (!$result && get_option($option_name) !== $option_value) { + $success = false; + } + } + + if ($success) { + wp_send_json_success(array('message' => __('Customer fields saved successfully', 'hesabix'))); + } else { + wp_send_json_error(array('message' => __('Failed to save customer fields', 'hesabix'))); + } + } catch (Exception $e) { + wp_send_json_error(array( + 'message' => __('Error saving customer fields: ', 'hesabix') . $e->getMessage() + )); + } + } + +} diff --git a/admin/class-ssbhesabix-admin.php b/admin/class-ssbhesabix-admin.php deleted file mode 100644 index 5b80987..0000000 --- a/admin/class-ssbhesabix-admin.php +++ /dev/null @@ -1,1658 +0,0 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - */ -class Ssbhesabix_Admin -{ - - /** - * The ID of this plugin. - * - * @since 1.0.0 - * @access private - * @var string $plugin_name The ID of this plugin. - */ - private $plugin_name; - - /** - * The version of this plugin. - * - * @since 1.0.0 - * @access private - * @var string $version The current version of this plugin. - */ - private $version; -//========================================================================================================================= - /** - * Initialize the class and set its properties. - * - * @param string $plugin_name The name of this plugin. - * @param string $version The version of this plugin. - * @since 1.0.0 - */ - public function __construct($plugin_name, $version) - { - $this->plugin_name = $plugin_name; - $this->version = $version; - $this->load_dependencies(); - } - - /** - * Check DB ver on plugin update and do necessary actions - * - * @since 1.0.7 - */ -//========================================================================================================================= - public function ssbhesabix_update_db_check() - { - $current_db_ver = get_site_option('ssbhesabix_db_version'); - if ($current_db_ver === false || $current_db_ver < 1.1) { - global $wpdb; - $table_name = $wpdb->prefix . "ssbhesabix"; - - $sql = "ALTER TABLE $table_name - ADD `id_ps_attribute` INT(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `id_ps`;"; - - if (!$wpdb->query($sql)) { - HesabixLogService::log(array("Cannot alter table $table_name. Current DB Version: $current_db_ver")); - } else { - update_option('ssbhesabix_db_version', 1.1); - HesabixLogService::log(array("Alter table $table_name. Current DB Version: $current_db_ver")); - } - } - } -//========================================================================================================================= - /** - * Register the stylesheets for the admin area. - * - * @since 1.0.0 - */ - public function enqueue_styles() - { - /** - * This function is provided for demonstration purposes only. - * - * An instance of this class should be passed to the run() function - * defined in Ssbhesabix_Loader as all of the hooks are defined - * in that particular class. - * - * The Ssbhesabix_Loader will then create the relationship - * between the defined hooks and the functions defined in this - * class. - */ - if( isset($_GET['page']) && str_contains($_GET['page'], "hesabix") ){ - wp_enqueue_style($this->plugin_name, plugin_dir_url(__FILE__) . 'css/ssbhesabix-admin.css?v=1', array(), $this->version, 'all'); - wp_enqueue_style('bootstrap_css', plugin_dir_url(__FILE__) . 'css/bootstrap.css', array(), $this->version, 'all'); - } - } -//========================================================================================================================= - /** - * Register the JavaScript for the admin area. - * - * @since 1.0.0 - */ - public function enqueue_scripts() - { - /** - * This function is provided for demonstration purposes only. - * - * An instance of this class should be passed to the run() function - * defined in Ssbhesabix_Loader as all of the hooks are defined - * in that particular class. - * - * The Ssbhesabix_Loader will then create the relationship - * between the defined hooks and the functions defined in this - * class. - */ - - wp_enqueue_script($this->plugin_name, plugin_dir_url(__FILE__) . 'js/ssbhesabix-admin.js', array('jquery'), $this->version, false); - if( isset($_GET['page']) && str_contains($_GET['page'], "hesabix") ) - wp_enqueue_script('bootstrap_js', plugin_dir_url(__FILE__) . 'js/bootstrap.bundle.min.js', array('jquery'), $this->version, false); - } -//========================================================================================================================= - private function load_dependencies() - { - /** - * The class responsible for defining all actions that occur in the Dashboard - */ - require_once plugin_dir_path(dirname(__FILE__)) . 'admin/partials/ssbhesabix-admin-display.php'; - - /** - * The class responsible for defining function for display Html element - */ - require_once plugin_dir_path(dirname(__FILE__)) . 'admin/partials/ssbhesabix-html-output.php'; - - /** - * The class responsible for defining function for display general setting tab - */ - require_once plugin_dir_path(dirname(__FILE__)) . 'admin/partials/ssbhesabix-admin-setting.php'; - - /** - * The class responsible for defining function for admin area - */ - require_once plugin_dir_path(dirname(__FILE__)) . 'admin/partials/ssbhesabix-admin-functions.php'; - } - - /** - * WC missing notice for the admin area. - * - * @since 1.0.0 - */ -//========================================================================================================================= - public function ssbhesabix_missing_notice() - { - echo '

' . sprintf(__('Hesabix Plugin requires the %s to work!', 'ssbhesabix'), '' . __('WooCommerce', 'ssbhesabix') . '') . '

'; - } - - /** - * Hesabix Plugin Live mode notice for the admin area. - * - * @since 1.0.0 - */ -//========================================================================================================================= - public function ssbhesabix_live_mode_notice() - { - echo '

' . __('Hesabix Plugin need to connect to Hesabix Accounting, Please check the API credential!', 'ssbhesabix') . '

'; - } -//========================================================================================================================= - public function ssbhesabix_business_expired_notice() - { - echo '

' . __('Cannot connect to Hesabix. Business expired.', 'ssbhesabix') . '

'; - } - - /** - * Missing hesabix default currency notice for the admin area. - * - * @since 1.0.0 - */ -//========================================================================================================================= - public function ssbhesabix_currency_notice() - { - echo '

' . __('Hesabix Plugin cannot works! because WooCommerce currency in not match with Hesabix.', 'ssbhesabix') . '

'; - } -//========================================================================================================================= - public function ssbhesabix_general_notices() { - if (!empty( $_REQUEST['submit_selected_orders_invoice_in_hesabix'])) { - if(!empty($_REQUEST['error_msg']) && $_REQUEST['error_msg'] == "select_max_10_items") { - printf( '

%s

', - __('Error: Select maximum 10 orders. Due to some limitations in Hesabix API, sending too many requests in one minute is not possible.', 'ssbhesabix')); - } else { - $success_count = intval( $_REQUEST['success_count'] ); - printf( '

%s %d

', __('Selected orders invoices have been saved. Number of saved invoices: ', 'ssbhesabix'), $success_count); - } - } - } - -//========================================================================================================================= - /* - * Action - Ajax 'export products' from Hesabix/Export tab - * @since 1.0.0 - */ - public function adminExportProductsCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - $batch = wc_clean($_POST['batch']); - $totalBatch = wc_clean($_POST['totalBatch']); - $total = wc_clean($_POST['total']); - $updateCount = wc_clean($_POST['updateCount']); - - $func = new Ssbhesabix_Admin_Functions(); - $result = $func->exportProducts($batch, $totalBatch, $total, $updateCount); - - if ($result['error']) { - if ($updateCount === -1) { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=export&productExportResult=false&error=-1'); - } else { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=export&productExportResult=false'); - } - } else { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=export&productExportResult=true&processed=' . $result['updateCount']); - } - - echo json_encode($result); - die(); - } - } -//========================================================================================================================= - public function adminImportProductsCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - $batch = wc_clean($_POST['batch']); - $totalBatch = wc_clean($_POST['totalBatch']); - $total = wc_clean($_POST['total']); - $updateCount = wc_clean($_POST['updateCount']); - - $func = new Ssbhesabix_Admin_Functions(); - $result = $func->importProducts($batch, $totalBatch, $total, $updateCount); - $import_count = $result['updateCount']; - - if ($result['error']) { - if ($import_count === -1) { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=export&productImportResult=false&error=-1'); - } else { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=export&productImportResult=false'); - } - } else { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=export&productImportResult=true&processed=' . $import_count); - } - - echo json_encode($result); - die(); - } - } -//========================================================================================================================= - /* - * Action - Ajax 'export products Opening Quantity' from Hesabix/Export tab - * @since 1.0.6 - */ - public function adminExportProductsOpeningQuantityCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - $batch = wc_clean($_POST['batch']); - $totalBatch = wc_clean($_POST['totalBatch']); - $total = wc_clean($_POST['total']); - - $func = new Ssbhesabix_Admin_Functions(); - $result = $func->exportOpeningQuantity($batch, $totalBatch, $total); - if ($result['error']) { - if ($result['errorType'] == 'shareholderError') { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=export&productOpeningQuantityExportResult=false&shareholderError=true'); - } else if ($result['errorType'] == 'noProduct') { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=export&productOpeningQuantityExportResult=false&noProduct=true'); - } else { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=export&productOpeningQuantityExportResult=false'); - } - } else { - if ($result["done"] == true) - update_option('ssbhesabix_use_export_product_opening_quantity', true); - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=export&productOpeningQuantityExportResult=true'); - } - - echo json_encode($result); - die(); - } - } -//========================================================================================================================= - /* - * Action - Ajax 'export customers' from Hesabix/Export tab - * @since 1.0.0 - */ - public function adminExportCustomersCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - $batch = wc_clean($_POST['batch']); - $totalBatch = wc_clean($_POST['totalBatch']); - $total = wc_clean($_POST['total']); - $updateCount = wc_clean($_POST['updateCount']); - - $func = new Ssbhesabix_Admin_Functions(); - $result = $func->exportCustomers($batch, $totalBatch, $total, $updateCount); - - if ($result["error"]) { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=export&customerExportResult=false'); - } else { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=export&customerExportResult=true&processed=' . $result["updateCount"]); - } - echo json_encode($result); - - die(); - } - } -//========================================================================================================================= - /* - * Action - Ajax 'Sync Changes' from Hesabix/Sync tab - * @since 1.0.0 - */ - public function adminSyncChangesCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - include(plugin_dir_path(__DIR__) . 'includes/class-ssbhesabix-webhook.php'); - new Ssbhesabix_Webhook(); - - $redirect_url = admin_url('admin.php?page=ssbhesabix-option&tab=sync&changesSyncResult=true'); - echo $redirect_url; - - die(); - } - } -//========================================================================================================================= - /* - * Action - Ajax 'Sync Products' from Hesabix/Sync tab - * @since 1.0.0 - */ - public function adminSyncProductsCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - $batch = wc_clean($_POST['batch']); - $totalBatch = wc_clean($_POST['totalBatch']); - $total = wc_clean($_POST['total']); - - $func = new Ssbhesabix_Admin_Functions(); - $result = $func->syncProducts($batch, $totalBatch, $total); - if ($result['error']) { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=sync&productSyncResult=false'); - echo json_encode($result); - } else { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=sync&productSyncResult=true'); - echo json_encode($result); - } - die(); - } - } -//========================================================================================================================= - /* - * Action - Ajax 'Sync Orders from Hesabix/Sync tab - * @since 1.0.0 - */ - public function adminSyncOrdersCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - $batch = wc_clean($_POST['batch']); - $totalBatch = wc_clean($_POST['totalBatch']); - $total = wc_clean($_POST['total']); - $updateCount = wc_clean($_POST['updateCount']); - $from_date = wc_clean($_POST['date']); - $end_date = wc_clean($_POST['endDate']); - - $func = new Ssbhesabix_Admin_Functions(); - $result = $func->syncOrders($from_date, $end_date, $batch, $totalBatch, $total, $updateCount); - - if (!$result['error']) - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=sync&orderSyncResult=true&processed=' . $result["updateCount"]); - else { - switch ($result['error']) { - case 'fiscalYearError': - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=sync&orderSyncResult=false&fiscal=true'); - break; - case 'inputDateError': - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=sync&orderSyncResult=false'); - break; - default: - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=sync&orderSyncResult=true&processed=' . $updateCount); - } - } - - echo json_encode($result); - die(); - } - } -//========================================================================================================================= - /* - * Action - Ajax 'Update Products' from Hesabix/Sync tab - * @since 1.0.0 - */ - public function adminUpdateProductsCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - $batch = wc_clean($_POST['batch']); - $totalBatch = wc_clean($_POST['totalBatch']); - $total = wc_clean($_POST['total']); - - $func = new Ssbhesabix_Admin_Functions(); - $result = $func->updateProductsInHesabixBasedOnStore($batch, $totalBatch, $total); - - if ($result['error']) { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=sync&$productUpdateResult=false'); - } else { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=sync&$productUpdateResult=true'); - } - echo json_encode($result); - die(); - } - } - -//========================================================================================================================= - public function adminUpdateProductsWithFilterCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - $offset = wc_clean($_POST['offset']); - $rpp = wc_clean($_POST['rpp']); - if(abs($rpp-$offset) <= 200) { - $func = new Ssbhesabix_Admin_Functions(); - $result = $func->updateProductsInHesabixBasedOnStoreWithFilter($offset, $rpp); - - if ($result['error']) { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=sync&$productUpdateWithFilterResult=false'); - } else { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=sync&$productUpdateWithFilterResult=true'); - } - echo json_encode($result); - die(); - } else { - $result["redirectUrl"] = admin_url('admin.php?page=ssbhesabix-option&tab=sync&$productUpdateWithFilterResult=false'); - echo json_encode($result); - die(); - } - } - } -//========================================================================================================================== - public function adminSubmitInvoiceCallback() - { - HesabixLogService::writeLogStr('Submit Invoice Manually'); - - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - $orderId = wc_clean($_POST['orderId']); - - $func = new Ssbhesabix_Admin_Functions(); - $result = $func->setOrder($orderId); - if ($result) - $func->setOrderPayment($orderId); - - echo json_encode($result); - die(); - } - } -//========================================================================================================================= - public function adminSyncProductsManuallyCallback() - { - HesabixLogService::writeLogStr('Sync Products Manually'); - - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - $page = wc_clean($_POST["page"]); - $rpp = wc_clean($_POST["rpp"]); - if (!$page) $page = 1; - if (!$rpp) $rpp = 10; - - if (isset($_POST["data"])) { - $data = wc_clean($_POST['data']); - $data = str_replace('\\', '', $data); - $data = json_decode($data, true); - } else { - $errors = true; - } - - $func = new Ssbhesabix_Admin_Functions(); - $res = $func->syncProductsManually($data); - if ($res["result"] == true) { - $redirect_url = admin_url("admin.php?page=hesabix-sync-products-manually&p=$page&rpp=$rpp&result=true"); - } else { - $data = implode(",", $res["data"]); - $redirect_url = admin_url("admin.php?page=hesabix-sync-products-manually&p=$page&rpp=$rpp&result=false&data=$data"); - } - echo $redirect_url; - - die(); - } - } -//========================================================================================================================= - public function adminClearPluginDataCallback() - { - - HesabixLogService::writeLogStr('Clear Plugin Data'); - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - //Call API - $hesabixApi = new Ssbhesabix_Api(); - $result = $hesabixApi->fixClearTags(); - if (!$result->Success) { - - HesabixLogService::log(array("ssbhesabix - Cannot clear tags. Error Message: " . (string)$result->ErrorMessage . ". Error Code: " . (string)$result->ErrorCode)); - } - - global $wpdb; - $options = $wpdb->get_results("SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%ssbhesabix%'"); - foreach ($options as $option) { - delete_option($option->option_name); - } - - $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}ssbhesabix"); - - die(); - } - } -//========================================================================================================================= - public function adminInstallPluginDataCallback() - { - - HesabixLogService::writeLogStr('Install Plugin Data'); - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - // create table and settings - require_once plugin_dir_path(__DIR__) . 'includes/class-ssbhesabix-activator.php'; - Ssbhesabix_Activator::activate(); - - die(); - } - } -//========================================================================================================================= - public function admin_product_add_column( $columns ) { - $hesabixArray = array("hesabix_code" => "کد در حسابیکس"); - $columns = $hesabixArray + $columns; - return $columns; - } -//========================================================================================================================= - public function admin_product_export_rows($rows, $products) { - $rowsArray = explode("\n", $rows); - $exportRows = []; - - $reflection = new ReflectionClass($products); - $property = $reflection->getProperty('row_data'); - $property->setAccessible(true); - $productsArray = $property->getValue($products); - $matchingArray = []; - - if (!empty($productsArray)) { - foreach ($productsArray as $product) { - if (is_array($product) && isset($product['id'])) { - $wpFaService = new HesabixWpFaService(); - - if ($product["type"] == "variation") { - if(array_key_exists('parent_id', $product)) { - $parentId = $product['parent_id']; - $productParentId = explode(':', $parentId)[1]; - $wpFa = $wpFaService->getWpFaSearch($productParentId, $product['id'], '', "product"); - } - } elseif ($product["type"] == "simple" || $product["type"] == "variable") { - $wpFa = $wpFaService->getWpFaSearch($product['id'], 0, '', "product"); - } - - if (is_array($wpFa)) { - foreach ($wpFa as $item) { - if ($item->idWpAttribute != 0) { - $matchingArray[$item->idWpAttribute] = $item->idHesabix; - } else { - $matchingArray[$item->idWp] = $item->idHesabix; - } - } - } - } - } - } - - foreach ($rowsArray as $row) { - if (empty(trim($row))) { - continue; - } - $columns = str_getcsv($row); - $inserted = false; - - if (isset($columns[1])) { - foreach ($matchingArray as $wpId => $hesabixId) { - if ($columns[1] == $wpId && !$inserted) { - $columns[0] = $hesabixId; - $inserted = true; - break; - } - } - } - - if (!$inserted) { - $columns[0] = "کد ندارد"; - } - - $exportRows[] = implode(",", $columns); - } - - return implode("\n", $exportRows); - } -//========================================================================================================================= - public function ssbhesabix_init_internal() - { - add_rewrite_rule('ssbhesabix-webhook.php$', 'index.php?ssbhesabix_webhook=1', 'top'); - //$this->checkForSyncChanges(); - } -//========================================================================================================================= - private function checkForSyncChanges() - { - $syncChangesLastDate = get_option('ssbhesabix_sync_changes_last_date'); - if (!isset($syncChangesLastDate) || $syncChangesLastDate == false) { - add_option('ssbhesabix_sync_changes_last_date', new DateTime()); - $syncChangesLastDate = new DateTime(); - } - - $nowDateTime = new DateTime(); - $diff = $nowDateTime->diff($syncChangesLastDate); - - if ($diff->i >= 4) { - HesabixLogService::writeLogStr('Sync Changes Automatically'); - update_option('ssbhesabix_sync_changes_last_date', new DateTime()); - require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-ssbhesabix-webhook.php'; - new Ssbhesabix_Webhook(); - } - } -//========================================================================================================================= - public function ssbhesabix_query_vars($query_vars) - { - $query_vars[] = 'ssbhesabix_webhook'; - return $query_vars; - } -//========================================================================================================================= - public function custom_hesabix_column_order_list($columns) - { - $reordered_columns = array(); - - foreach ($columns as $key => $column) { - $reordered_columns[$key] = $column; - if ($key == 'order_status') { - // Inserting after "Status" column - $reordered_columns['hesabix-column-invoice-number'] = __('Invoice in Hesabix', 'ssbhesabix'); - $reordered_columns['hesabix-column-submit-invoice'] = __('Submit Invoice', 'ssbhesabix'); - } - } - return $reordered_columns; - } -//========================================================================================================================= - public function custom_orders_list_column_content($column, $post_id) - { - - global $wpdb; - - if (get_option('woocommerce_custom_orders_table_enabled') == 'yes') { - switch ($column) { - case 'hesabix-column-invoice-number': - $product_id = $post_id->ID; // Extract product ID from the object - // $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id_ps` = $post_id AND `obj_type` = 'order'"); - $table_name = $wpdb->prefix . 'ssbhesabix'; - $row = $wpdb->get_row( - $wpdb->prepare( - "SELECT id_hesabix FROM $table_name WHERE id_ps = %d AND obj_type = 'order'", - $product_id - ) - ); - - if (!empty($row)) { - echo '' . $row->id_hesabix . ''; - } else { - echo ''; - } - break; - - case 'hesabix-column-submit-invoice': - // Use the product ID for the data attribute value - $product_id = $post_id->ID; - echo ''; - echo __('Submit Invoice', 'ssbhesabix'); - echo ''; - break; - } - } else { - switch ($column) { - case 'hesabix-column-invoice-number' : - // Get custom post meta data - $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id_ps` = $post_id AND `obj_type` = 'order'"); - - //$my_var_one = get_post_meta( $post_id, '_the_meta_key1', true ); - if (!empty($row)) - echo '' . $row->id_hesabix . ''; - else - echo ''; - break; - - case 'hesabix-column-submit-invoice' : - echo '"; - echo __('Submit Invoice', 'ssbhesabix'); - echo ''; - break; - } - } - } -//========================================================================================================================= - public function ssbhesabix_parse_request(&$wp) - { - if (array_key_exists('ssbhesabix_webhook', $wp->query_vars)) { - include(plugin_dir_path(__DIR__) . 'includes/ssbhesabix-webhook.php'); - exit(); - } - } -//========================================================================================================================= - public function custom_orders_list_bulk_action($actions) { - $actions['submit_invoice_in_hesabix'] = __('Submit Invoice in Hesabix', 'ssbhesabix'); - return $actions; - } -//========================================================================================================================= - public function custom_orders_list_bulk_action_run($redirect_to, $action, $post_ids) { - if ( $action !== 'submit_invoice_in_hesabix' ) - return $redirect_to; // Exit - - - HesabixLogService::writeLogStr("Submit selected orders invoice"); - - if(count($post_ids) > 10) - return $redirect_to = add_query_arg( array( - 'submit_selected_orders_invoice_in_hesabix' => '1', - 'error_msg' => 'select_max_10_items' - ), $redirect_to ); - - $success_count = 0; - $func = new Ssbhesabix_Admin_Functions(); - foreach ($post_ids as $orderId) { - $result = $func->setOrder($orderId); - if ($result) { - $success_count++; - $func->setOrderPayment($orderId); - } - } - - return $redirect_to = add_query_arg( array( - 'submit_selected_orders_invoice_in_hesabix' => '1', - 'success_count' => $success_count, - 'error_msg' => '0' - ), $redirect_to ); - } -//========================================================================================================================= - //Hooks - //Contact - public function ssbhesabix_hook_edit_user(WP_User $user) - { - $wpFaService = new HesabixWpFaService(); - $code = isset($user) ? $wpFaService->getCustomerCodeByWpId($user->ID) : ''; - ?> -
- - - - - -
- -
-
- -
-
-
- getWpFaByHesabixId('customer', $user_hesabix_code); - $wpFa = $wpFaService->getWpFa('customer', $id_customer); - - if (!$wpFaOld || !$wpFa || $wpFaOld->id !== $wpFa->id) { - if ($wpFaOld) - $wpFaService->delete($wpFaOld); - - if ($wpFa) { - $wpFa->idHesabix = $user_hesabix_code; - $wpFaService->update($wpFa); - } else { - $wpFa = new WpFa(); - $wpFa->objType = 'customer'; - $wpFa->idWp = $id_customer; - $wpFa->idHesabix = intval($user_hesabix_code); - $wpFaService->save($wpFa); - } - } - } - - $function = new Ssbhesabix_Admin_Functions(); - - if(get_option('ssbhesabix_contact_automatically_save_in_hesabix') == 'yes') - $function->setContact($id_customer); - } -//========================================================================================================================= - public function ssbhesabix_hook_delete_user($id_customer) - { - $wpFaService = new HesabixWpFaService(); - $id_obj = $wpFaService->getWpFaId('customer', $id_customer); - if ($id_obj != false) { - global $wpdb; - $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id` = $id_obj AND `obj_type` = 'customer'"); - - if (is_object($row)) { - $hesabixApi = new Ssbhesabix_Api(); - $hesabixApi->contactDelete($row->id_hesabix); - } - - global $wpdb; - $wpdb->delete($wpdb->prefix . 'ssbhesabix', array('id_ps' => $id_customer)); - - - HesabixLogService::log(array("Customer deleted. Customer ID: $id_customer")); - } - } -//========================================================================================================================= - //Invoice - public function ssbhesabix_hook_order_status_change($id_order, $from, $to) - { - HesabixLogService::writeLogStr("Order Status Hook"); - $function = new Ssbhesabix_Admin_Functions(); - - foreach (get_option('ssbhesabix_invoice_status') as $status) { - - HesabixLogService::writeLogStr("status: $status"); - - if ($status == $to) { - $orderResult = $function->setOrder($id_order); - if ($orderResult) { - // set payment - foreach (get_option('ssbhesabix_payment_status') as $statusPayment) { - if ($statusPayment == $to) - $function->setOrderPayment($id_order); - } - } - } - } - - $values = get_option('ssbhesabix_invoice_return_status'); - if(is_array($values) || is_object($values)) { - foreach ($values as $status) { - if ($status == $to) - $function->setOrder($id_order, 2, $function->getInvoiceCodeByOrderId($id_order)); - } - } - } -//========================================================================================================================= - public function ssbhesabix_hook_new_order($id_order, $order) - { - HesabixLogService::writeLogStr("New Order Hook"); - $function = new Ssbhesabix_Admin_Functions(); - $orderStatus = wc_get_order($id_order)->get_status(); - $orderItems = $order->get_items(); - - foreach (get_option('ssbhesabix_invoice_status') as $status) { - - HesabixLogService::writeLogStr("status: $status"); - - if ($status == $orderStatus) { - $orderResult = $function->setOrder($id_order, 0, null, $orderItems); - if ($orderResult) { - // set payment - foreach (get_option('ssbhesabix_payment_status') as $statusPayment) { - if ($statusPayment == $orderStatus) - $function->setOrderPayment($id_order); - } - } - } - } - - HesabixLogService::log(array($orderStatus)); - - $values = get_option('ssbhesabix_invoice_return_status'); - if(is_array($values) || is_object($values)) { - foreach ($values as $status) { - if ($status == $orderStatus) - $function->setOrder($id_order, 2, $function->getInvoiceCodeByOrderId($id_order), $orderItems); - } - } - } -//========================================================================================================================= - public function ssbhesabix_hook_payment_confirmation($id_order, $from, $to) - { - foreach (get_option('ssbhesabix_payment_status') as $status) { - if ($status == $to) { - $function = new Ssbhesabix_Admin_Functions(); - $function->setOrderPayment($id_order); - } - } - } - - //Item - private $call_time = 1; -//========================================================================================================================= - public function ssbhesabix_hook_new_product($id_product) - { -// if (get_option("ssbhesabix_inside_product_edit", 0) === 1) -// return; - - if ($this->call_time === 1) { - $this->call_time++; - return; - } else { - $this->call_time = 1; - } - - if (get_option("ssbhesabix_do_not_submit_product_automatically", "no") === "yes") return; - $function = new Ssbhesabix_Admin_Functions(); - $function->setItems(array($id_product)); - } -//========================================================================================================================= - public function ssbhesabix_hook_save_product_variation($id_attribute) - { - - HesabixLogService::writeLogStr("ssbhesabix_hook_save_product_variation"); - - if (get_option("ssbhesabix_do_not_submit_product_automatically", "no") === "yes" || get_option("ssbhesabix_do_not_submit_product_automatically", "no") == "1") { - //change hesabix item code - $variable_field_id = "ssbhesabix_hesabix_item_code_" . $id_attribute; - $code = $_POST[$variable_field_id]; - $id_product = $_POST['product_id']; - - if ($code === "") - return; - - if (isset($code)) { - global $wpdb; - $row = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id_hesabix` = " . $code . " AND `obj_type` = 'product'"); - - if (is_object($row)) { - if ($row->id_ps == $id_product && $row->id_ps_attribute == $id_attribute) { - return false; - } - - echo '

' . __('The new Item code already used for another Item', 'ssbhesabix') . '

'; - - HesabixLogService::log(array("The new Item code already used for another Item. Product ID: $id_product")); - } else { - $row2 = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id_ps` = $id_product AND `obj_type` = 'product' AND `id_ps_attribute` = $id_attribute"); - - if (is_object($row2)) { - $wpdb->update($wpdb->prefix . 'ssbhesabix', array( - 'id_hesabix' => (int)$code, - ), array( - 'id_ps' => $id_product, - 'id_ps_attribute' => $id_attribute, - 'obj_type' => 'product', - )); - } else if ((int)$code !== 0) { - $wpdb->insert($wpdb->prefix . 'ssbhesabix', array( - 'id_hesabix' => (int)$code, - 'id_ps' => (int)$id_product, - 'id_ps_attribute' => $id_attribute, - 'obj_type' => 'product', - )); - } - } - } - - //add attribute if not exists - $func = new Ssbhesabix_Admin_Functions(); - $wpFaService = new HesabixWpFaService(); - $code = $wpFaService->getProductCodeByWpId($id_product, $id_attribute); - if ($code == null) { - $func->setItems(array($id_product)); - } - } - } -//========================================================================================================================= - //ToDo: check why base product is not deleted - public function ssbhesabix_hook_delete_product($id_product) - { - - HesabixLogService::writeLogStr("Product Delete Hook"); - - $func = new Ssbhesabix_Admin_Functions(); - $wpFaService = new HesabixWpFaService(); - - $hesabixApi = new Ssbhesabix_Api(); - global $wpdb; - - $variations = $func->getProductVariations($id_product); - if ($variations != false) { - foreach ($variations as $variation) { - $id_attribute = $variation->get_id(); - $code = $wpFaService->getProductCodeByWpId($id_product, $id_attribute); - if ($code != false) { - $hesabixApi->itemDelete($code); - $wpdb->delete($wpdb->prefix . 'ssbhesabix', array('id_hesabix' => $code, 'obj_type' => 'product')); - - HesabixLogService::log(array("Product variation deleted. Product ID: $id_product-$id_attribute")); - } - } - } - - $code = $wpFaService->getProductCodeByWpId($id_product); - - if ($code != false) { - $hesabixApi->itemDelete($code); - $wpdb->delete($wpdb->prefix . 'ssbhesabix', array('id_hesabix' => $code, 'obj_type' => 'product')); - - HesabixLogService::log(array("Product deleted. Product ID: $id_product")); - } - } -//========================================================================================================================= - public function ssbhesabix_hook_delete_product_variation($id_attribute) - { -// $func = new Ssbhesabix_Admin_Functions(); - - $hesabixApi = new Ssbhesabix_Api(); - global $wpdb; - $row = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id_ps_attribute` = $id_attribute AND `obj_type` = 'product'"); - - if (is_object($row)) { - $hesabixApi->itemDelete($row->id_hesabix); - - $wpdb->delete($wpdb->prefix . 'ssbhesabix', array('id' => $row->id)); - - HesabixLogService::log(array("Product variation deleted. Product ID: $row->id_ps-$id_attribute")); - } - } -//========================================================================================================================= - public function ssbhesabix_hook_product_options_general_product_data() - { - $wpFaService = new HesabixWpFaService(); - $value = isset($_GET['post']) ? $wpFaService->getProductCodeByWpId($_GET['post']) : ''; - $args = array( - 'id' => 'ssbhesabix_hesabix_item_code_0', - 'label' => __('Hesabix base item code', 'ssbhesabix'), - 'desc_tip' => true, - 'description' => __('The base Item code of this product in Hesabix, if you want to map this product to another item in Hesabix, enter the new Item code.', 'ssbhesabix'), - 'value' => $value, - 'type' => 'number', - ); - woocommerce_wp_text_input($args); - } -//========================================================================================================================= - public function ssbhesabix_hook_process_product_meta($post_id) - { - $itemCode = isset($_POST['ssbhesabix_hesabix_item_code_0']) ? $_POST['ssbhesabix_hesabix_item_code_0'] : ''; - - if ($itemCode === "") - return; - - if (isset($itemCode)) { - global $wpdb; - $row = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id_hesabix` = " . $itemCode . " AND `obj_type` = 'product'"); - - if (is_object($row)) { - //ToDo: show error to customer in BO - echo '

' . __('The new Item code already used for another Item', 'ssbhesabix') . '

'; - - HesabixLogService::log(array("The new Item code already used for another Item. Product ID: $post_id")); - } else { - $row2 = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id_ps` = $post_id AND `obj_type` = 'product' AND `id_ps_attribute` = 0"); - if (is_object($row2)) { - $wpdb->update($wpdb->prefix . 'ssbhesabix', array( - 'id_hesabix' => (int)$itemCode, - ), array( - 'id_ps' => $post_id, - 'id_ps_attribute' => 0, - 'obj_type' => 'product', - )); - } else if ((int)$itemCode !== 0) { - $wpdb->insert($wpdb->prefix . 'ssbhesabix', array( - 'id_hesabix' => (int)$itemCode, - 'id_ps' => (int)$post_id, - 'id_ps_attribute' => 0, - 'obj_type' => 'product', - )); - } - } - } - } -//========================================================================================================================= - public function ssbhesabix_hook_product_after_variable_attributes($loop, $variation_data, $variation) - { - $wpFaService = new HesabixWpFaService(); - $value = isset($_POST['product_id']) ? $wpFaService->getProductCodeByWpId($_POST['product_id'], $variation->ID) : ''; - $args = array( - 'id' => 'ssbhesabix_hesabix_item_code_' . $variation->ID, - 'label' => __('Hesabix variable item code', 'ssbhesabix'), - 'desc_tip' => true, - 'description' => __('The variable Item code of this product variable in Hesabix, if you want to map this product to another item in Hesabix, enter the new Item code.', 'ssbhesabix'), - 'value' => $value, - ); - woocommerce_wp_text_input($args); - } -//========================================================================================================================= - /* - * Action - Ajax 'clean log file' from Hesabix/Log tab - * @since 1.0.0 - */ - public function adminCleanLogFileCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - $func = new Ssbhesabix_Admin_Functions(); - $result = $func->cleanLogFile(); - - if ($result) { - $redirect_url = admin_url('admin.php?page=ssbhesabix-option&tab=log&cleanLogResult=true'); - } else { - $redirect_url = admin_url('admin.php?page=ssbhesabix-option&tab=log&cleanLogResult=false'); - } - echo $redirect_url; - - die(); - } - } -//========================================================================================================================= - // custom data tab in edit product page in admin panel - function add_hesabix_product_data_tab($product_data_tabs) - { - $product_data_tabs['hesabix'] = array( - 'label' => __('Hesabix', 'ssbhesabix'), - 'target' => 'panel_product_data_hesabix', - ); - return $product_data_tabs; - } -//========================================================================================================================= - function add_hesabix_product_data_fields() - { - global $woocommerce, $post, $product; - - $funcs = new Ssbhesabix_Admin_Functions(); - $items = array(); - $id_product = $post->ID; -// $product = new WC_Product($id_product); - $product = wc_get_product($id_product); - - if ($product->get_status() === "auto-draft") { - ?> -
- هنوز محصول ذخیره نشده است. -
- پس از ذخیره محصول، در این قسمت می توانید ارتباط محصول و متغیرهای آن با حسابیکس - را مدیریت کنید. -
- get_stock_quantity(); - $items[0]["Id"] = $id_product; - $i = 1; - - $variations = $funcs->getProductVariations($id_product); - if ($variations) { - foreach ($variations as $variation) { - $items[] = ssbhesabixItemService::mapProductVariation($product, $variation, $id_product, false); - $items[$i]["Quantity"] = $variation->get_stock_quantity(); - $items[$i]["Id"] = $variation->get_id(); - $i++; - } - } - - ?> -
- - - - - - - - - - - - - - - - - - - - - -
نام کالاکد در حسابیکسذخیره کدحذف ارتباطبروزرسانی قیمت و موجودیقیمتموجودی
" - id="hesabix-item-" style="width: 75px;" - class="hesabix-item-code" data-id="">" - class="button hesabix-item-save">" - class="button hesabix-item-delete-link">" - class="button button-primary hesabix-item-update">">">
- - - - - -
- - #hesabixID { - width: 5vw; - color: #2271b1; - } - '; - return array_slice($columns, 0, 3, true) + array('hesabixID' => 'کد حسابیکس') + array_slice($columns, 3, count($columns) - 3, true); - } -//====== - function admin_products_hesabixId_column_content( $column ){ - $funcs = new Ssbhesabix_Admin_Functions(); - $items = array(); - $id_product = get_the_ID(); -// $product = new WC_Product($id_product); - $product = wc_get_product($id_product); - - $items[] = ssbhesabixItemService::mapProduct($product, $id_product, false); - $i = 1; - - $variations = $funcs->getProductVariations($id_product); - if ($variations) { - foreach ($variations as $variation) { - $items[] = ssbhesabixItemService::mapProductVariation($product, $variation, $id_product, false); - $i++; - } - } - - echo '
'; - foreach ($items as $item) { - if ( $column == 'hesabixID' ) { - $hesabixId = $item["Code"]; - echo "" . $hesabixId . " " . ""; - } - } - echo '
'; - } -//========================================================================================================================= - function adminChangeProductCodeCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - $productId = (int)wc_clean($_POST['productId']); - $attributeId = (int)wc_clean($_POST['attributeId']); - if ($productId == $attributeId) $attributeId = 0; - $code = (int)wc_clean($_POST['code']); - $result = array(); - - if (!$code) { - $result["error"] = true; - $result["message"] = "کد کالا وارد نشده است."; - echo json_encode($result); - die(); - return; - } - - $wpFaService = new HesabixWpFaService(); - $wpFa = $wpFaService->getWpFaByHesabixId('product', $code); - if ($wpFa) { - $result["error"] = true; - $result["message"] = "این کد به کالای دیگری متصل است. \n" . $wpFa->idWp . " - " . $wpFa->idWpAttribute; - echo json_encode($result); - die(); - return; - } - - $api = new Ssbhesabix_Api(); - $response = $api->itemGet($code); - if (!$response->Success) { - $result["error"] = true; - $result["message"] = "کالایی با کد وارد شده در حسابیکس پیدا نشد."; - echo json_encode($result); - die(); - return; - } - - $wpFa = $wpFaService->getWpFa('product', $productId, $attributeId); - if ($wpFa) { - $wpFa->idHesabix = $code; - $wpFaService->update($wpFa); - } else { - $wpFa = new WpFa(); - $wpFa->idHesabix = $code; - $wpFa->idWp = $productId; - $wpFa->idWpAttribute = $attributeId; - $wpFa->objType = 'product'; - $wpFaService->save($wpFa); - } - $result["error"] = false; - echo json_encode($result); - die(); - } - } -//========================================================================================================================= - function adminDeleteProductLinkCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - $productId = wc_clean($_POST['productId']); - $attributeId = wc_clean($_POST['attributeId']); - if ($productId == $attributeId) $attributeId = 0; - $result = array(); - - $wpFaService = new HesabixWpFaService(); - $wpFa = $wpFaService->getWpFa('product', $productId, $attributeId); - if ($wpFa) { - $wpFaService->delete($wpFa); - HesabixLogService::writeLogStr("حذف ارتباط کالا. کد کالا: " . $productId . " - ". "کد متغیر:". $attributeId); - } - - $result["error"] = false; - echo json_encode($result); - die(); - } - } -//========================================================================================================================= - function adminUpdateProductCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - if (get_option('ssbhesabix_item_update_price', 'no') == 'no' && - get_option('ssbhesabix_item_update_quantity', 'no') == 'no') { - $result["error"] = true; - $result["message"] = "خطا: در تنظیمات افزونه، گزینه های بروزرسانی قیمت و موجودی محصول بر اساس حسابیکس فعال نیستند."; - echo json_encode($result); - die(); - } - - $productId = wc_clean($_POST['productId']); - $attributeId = wc_clean($_POST['attributeId']); - - if (get_option('ssbhesabix_item_update_quantity', 'no') == 'yes') - update_post_meta($attributeId, '_manage_stock', 'yes'); - - if ($productId == $attributeId) $attributeId = 0; - $result = array(); - - $wpFaService = new HesabixWpFaService(); - $wpFa = $wpFaService->getWpFa('product', $productId, $attributeId); - if ($wpFa) { - - $api = new Ssbhesabix_Api(); - $warehouse = get_option('ssbhesabix_item_update_quantity_based_on', "-1"); - if ($warehouse == "-1") - $response = $api->itemGet($wpFa->idHesabix); - else { - $response = $api->itemGetQuantity($warehouse, array($wpFa->idHesabix)); - } - - if ($response->Success) { - $item = $warehouse == "-1" ? $response->Result : $response->Result[0]; - $newProps = Ssbhesabix_Admin_Functions::setItemChanges($item); - $result["error"] = false; - $result["newPrice"] = $newProps["newPrice"]; - $result["newQuantity"] = $newProps["newQuantity"]; - } else { - $result["error"] = true; - $result["message"] = "کالا در حسابیکس پیدا نشد."; - } - } - - echo json_encode($result); - die(); - } - } -//========================================================================================================================= - function adminChangeProductsCodeCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - $wpFaService = new HesabixWpFaService(); - - $productId = (int)wc_clean($_POST['productId']); - $itemsData = wc_clean($_POST['itemsData'], true); - $result = array(); - $codes = []; - - foreach ($itemsData as $itemData) { - $attributeId = (int)$itemData["attributeId"]; - $code = (int)$itemData["code"]; - if ($productId == $attributeId) $attributeId = 0; - $codes[] = str_pad($code, 6, "0", STR_PAD_LEFT); - - if (!$code) { - $result["error"] = true; - $result["message"] = "کد کالا وارد نشده است."; - echo json_encode($result); - die(); - return; - } - - $wpFa = $wpFaService->getWpFaByHesabixId('product', $code); - $wpFa2 = $wpFaService->getWpFa('product', $productId, $attributeId); - if ($wpFa && $wpFa2 && $wpFa->id != $wpFa2->id) { - $result["error"] = true; - $result["message"] = "این کد ($code) به کالای دیگری متصل است. \n" . $wpFa->idWp . " - " . $wpFa->idWpAttribute; - echo json_encode($result); - die(); - return; - } - } - - $api = new Ssbhesabix_Api(); - $response = $api->itemGetItemsByCodes(array('values' => $codes)); - if ($response->Success) { - $items = $response->result; - foreach ($codes as $code) { - $found = false; - foreach ($items as $item) { - if ($item->code == $code) - $found = true; - } - if (!$found) { - $result["error"] = true; - $result["message"] = "کالایی با کد $code در حسابیکس پیدا نشد."; - echo json_encode($result); - die(); - return; - } - } - } else { - $result["error"] = true; - $result["message"] = "کالایی با کد وارد شده در حسابیکس پیدا نشد."; - echo json_encode($result); - die(); - return; - } - - - foreach ($itemsData as $itemData) { - $attributeId = (int)$itemData["attributeId"]; - $code = (int)$itemData["code"]; - if ($productId == $attributeId) $attributeId = 0; - - $wpFa = $wpFaService->getWpFa('product', $productId, $attributeId); - if ($wpFa) { - $wpFa->idHesabix = $code; - $wpFaService->update($wpFa); - } else { - $wpFa = new WpFa(); - $wpFa->idHesabix = $code; - $wpFa->idWp = $productId; - $wpFa->idWpAttribute = $attributeId; - $wpFa->objType = 'product'; - $wpFaService->save($wpFa); - } - } - - $result["error"] = false; - echo json_encode($result); - die(); - } - } -//========================================================================================================================= - function adminDeleteProductsLinkCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - $productId = wc_clean($_POST['productId']); - $result = array(); - - $wpFaService = new HesabixWpFaService(); - $wpFaService->deleteAll($productId); - HesabixLogService::writeLogStr("حذف ارتباط کالاها. کد کالا: " . $productId); - - $result["error"] = false; - echo json_encode($result); - die(); - } - } -//========================================================================================================================= - function adminUpdateProductAndVariationsCallback() - { - if (is_admin() && (defined('DOING_AJAX') || DOING_AJAX)) { - - if (get_option('ssbhesabix_item_update_price', 'no') == 'no' && - get_option('ssbhesabix_item_update_quantity', 'no') == 'no') { - $result["error"] = true; - $result["message"] = "خطا: در تنظیمات افزونه، گزینه های بروزرسانی قیمت و موجودی محصول بر اساس حسابیکس فعال نیستند."; - echo json_encode($result); - die(); - } - - //Call API - $api = new Ssbhesabix_Api(); - $wpFaService = new HesabixWpFaService(); - - $productId = wc_clean($_POST['productId']); - $productAndCombinations = $wpFaService->getProductAndCombinations($productId); - $result = array(); - if (count($productAndCombinations) == 0) { - $result["error"] = true; - $result["message"] = "هیچ ارتباطی پیدا نشد."; - echo json_encode($result); - die(); - } - $codes = []; - $ssbhesabix_item_update_quantity = get_option('ssbhesabix_item_update_quantity', 'no'); - foreach ($productAndCombinations as $p) { - $codes[] = str_pad($p->idHesabix, 6, "0", STR_PAD_LEFT); - - if ($ssbhesabix_item_update_quantity == 'yes') - update_post_meta($p->idWpAttribute == 0 ? $p->idWp : $p->idWpAttribute, '_manage_stock', 'yes'); - } - - $warehouse = get_option('ssbhesabix_item_update_quantity_based_on', "-1"); - if ($warehouse == "-1") - $response = $api->itemGetItemsByCodes($codes); - else { - $response = $api->itemGetQuantity($warehouse, $codes); - } - - if ($response->Success) { - $items = $warehouse == "-1" ? $response->Result->List : $response->Result; - $newData = []; - $result["error"] = false; - foreach ($items as $item) { - $newProps = Ssbhesabix_Admin_Functions::setItemChanges($item); - $wpFa = $wpFaService->getWpFaByHesabixId('product', $item->Code); - $newData[] = array("newPrice" => $newProps["newPrice"], - "newQuantity" => $newProps["newQuantity"], - "attributeId" => $wpFa->idWpAttribute > 0 ? $wpFa->idWpAttribute : $wpFa->idWp); - } - $result["newData"] = $newData; - } else { - $result["error"] = true; - $result["message"] = "کالایی با کد وارد شده در حسابیکس پیدا نشد."; - echo json_encode($result); - die(); - return; - } - - echo json_encode($result); - die(); - } - } -//========================================================================================================================= - function add_additional_fields_to_checkout( $fields ) { - $NationalCode_isActive = get_option('ssbhesabix_contact_NationalCode_checkbox_hesabix'); - $EconomicCode_isActive = get_option('ssbhesabix_contact_EconomicCode_checkbox_hesabix'); - $RegistrationNumber_isActive = get_option('ssbhesabix_contact_RegistrationNumber_checkbox_hesabix'); - $Website_isActive = get_option('ssbhesabix_contact_Website_checkbox_hesabix'); - - $NationalCode_isRequired = get_option('ssbhesabix_contact_NationalCode_isRequired_hesabix'); - $EconomicCode_isRequired = get_option('ssbhesabix_contact_EconomicCode_isRequired_hesabix'); - $RegistrationNumber_isRequired = get_option('ssbhesabix_contact_RegistrationNumber_isRequired_hesabix'); - $Website_isRequired = get_option('ssbhesabix_contact_Website_isRequired_hesabix'); - - //NationalCode - if($NationalCode_isActive == 'yes'){ - $fields['billing']['billing_hesabix_nationalcode'] = array( - 'label' => __('National code', 'ssbhesabix'), - 'placeholder' => __('please enter your National code', 'ssbhesabix'), - 'priority' => 30, - 'required' => (bool) $NationalCode_isRequired, - 'clear' => true, - 'maxlength' => 10, - ); - } - //Economic code - if($EconomicCode_isActive == 'yes'){ - $fields['billing']['billing_hesabix_economiccode'] = array( - 'label' => __('Economic code', 'ssbhesabix'), - 'placeholder' => __('please enter your Economic code', 'ssbhesabix'), - 'priority' => 31, - 'required' => (bool) $EconomicCode_isRequired, - 'clear' => true - ); - } - //Registration Number - if($RegistrationNumber_isActive == 'yes'){ - $fields['billing']['billing_hesabix_registerationnumber'] = array( - 'label' => __('Registration number', 'ssbhesabix'), - 'placeholder' => __('please enter your Registration number', 'ssbhesabix'), - 'priority' => 32, - 'required' => (bool) $RegistrationNumber_isRequired, - 'clear' => true - ); - } - //Website - if($Website_isActive == 'yes'){ - $fields['billing']['billing_hesabix_website'] = array( - 'type' => 'url', - 'label' => __('Website', 'ssbhesabix'), - 'placeholder' => __('please enter your Website address', 'ssbhesabix'), - 'priority' => 33, - 'required' => (bool) $Website_isRequired, - 'clear' => true, - ); - } - if(isset($_POST['billing_hesabix_nationalcode']) || isset($_POST['billing_hesabix_website'])) { - $func = new Ssbhesabix_Admin_Functions(); - $NationalCode = $_POST['billing_hesabix_nationalcode']; - $Website = $_POST['billing_hesabix_website']; - if($NationalCode_isRequired) { - $func->checkNationalCode($NationalCode); - } - - if($Website_isRequired) { - $func->checkWebsite($Website); - } - } - return $fields; - } -//========================================================================================================================= - function show_additional_fields_in_order_detail($order) { - //this function is used to show codes and website in woocommerce orders detail - $orderId = $order->get_id(); - $NationalCode = '_billing_hesabix_nationalcode'; - $EconomicCode = '_billing_hesabix_economiccode'; - $RegistrationNumber = '_billing_hesabix_registerationnumber'; - $Website = '_billing_hesabix_website'; - - $NationalCode_isActive = get_option('ssbhesabix_contact_NationalCode_checkbox_hesabix'); - $EconomicCode_isActive = get_option('ssbhesabix_contact_EconomicCode_checkbox_hesabix'); - $RegistrationNumber_isActive = get_option('ssbhesabix_contact_RegistrationNumber_checkbox_hesabix'); - $Website_isActive = get_option('ssbhesabix_contact_Website_checkbox_hesabix'); - - if($NationalCode_isActive == 'yes') { - echo '

' . __('National code', 'ssbhesabix') . ': ' .'
'. '' . get_post_meta( $orderId, $NationalCode, true ) . '

'; - } - - if($EconomicCode_isActive == 'yes') - echo '

' . __('Economic code', 'ssbhesabix') . ': ' .'
'. '' . get_post_meta( $orderId, $EconomicCode, true ) . '

'; - - if($RegistrationNumber_isActive == 'yes') - echo '

' . __('Registration number', 'ssbhesabix') . ': ' .'
'. '' . get_post_meta( $orderId, $RegistrationNumber, true ) . '

'; - - if($Website_isActive == 'yes') - echo '

' . __('Website', 'ssbhesabix') . ': ' .'
'. '' . get_post_meta( $orderId, $Website, true ) . '

'; - } -//========================================================================================================================= -} diff --git a/admin/css/fontiran.css b/admin/css/fontiran.css deleted file mode 100644 index 14c003c..0000000 --- a/admin/css/fontiran.css +++ /dev/null @@ -1,105 +0,0 @@ -/** -* -* Name: IRANYekan Font -* Version: 3.3 -* Author: Moslem Ebrahimi (moslemebrahimi.com) -* Created on: Sep 17, 2020 -* Updated on: Sep 17, 2020 -* Website: http://fontiran.com -* Copyright: Commercial/Proprietary Software --------------------------------------------------------------------------------------- -فونت ایران یکان یک نرم افزار مالکیتی محسوب می شود. جهت آگاهی از قوانین استفاده از این فونت ها لطفا به وب سایت (فونت ایران دات کام) مراجعه نمایید --------------------------------------------------------------------------------------- -IRANYekan fonts are considered a proprietary software. To gain information about the laws regarding the use of these fonts, please visit www.fontiran.com --------------------------------------------------------------------------------------- -This set of fonts are used in this project under the license: (.....) --------------------------------------------------------------------------------------- -* -**/ -@font-face { - font-family: iranyekan; - font-style: normal; - font-weight: bold; - src: url('../fonts/eot/iranyekanwebbold.eot'); - src: url('../fonts/eot/iranyekanwebbold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ - url('../fonts/woff/iranyekanwebbold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/ - url('../fonts/woff2/iranyekanwebbold.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/ - url('../fonts/ttf/iranyekanwebbold.ttf') format('truetype'); -} - -@font-face { - font-family: iranyekan; - font-style: normal; - font-weight: 100; - src: url('../fonts/eot/iranyekanwebthin.eot'); - src: url('../fonts/eot/iranyekanwebthin.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ - url('../fonts/woff/iranyekanwebthin.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/ - url('../fonts/woff2/iranyekanwebthin.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/ - url('../fonts/ttf/iranyekanwebthin.ttf') format('truetype'); -} - -@font-face { - font-family: iranyekan; - font-style: normal; - font-weight: 300; - src: url('../fonts/eot/iranyekanweblight.eot'); - src: url('../fonts/eot/iranyekanweblight.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ - url('../fonts/woff/iranyekanweblight.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/ - url('../fonts/woff2/iranyekanweblight.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/ - url('../fonts/ttf/iranyekanweblight.ttf') format('truetype'); -} - -@font-face { - font-family: iranyekan; - font-style: normal; - font-weight: normal; - src: url('../fonts/eot/iranyekanwebregular.eot'); - src: url('../fonts/eot/iranyekanwebregular.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ - url('../fonts/woff/iranyekanwebregular.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/ - url('../fonts/woff2/iranyekanwebregular.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/ - url('../fonts/ttf/iranyekanwebregular.ttf') format('truetype'); -} - -@font-face { - font-family: iranyekan; - font-style: normal; - font-weight: 500; - src: url('../fonts/eot/iranyekanwebmedium.eot'); - src: url('../fonts/eot/iranyekanwebmedium.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ - url('../fonts/woff/iranyekanwebmedium.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/ - url('../fonts/woff2/iranyekanwebmedium.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/ - url('../fonts/ttf/iranyekanwebmedium.ttf') format('truetype'); -} - -@font-face { - font-family: iranyekan; - font-style: normal; - font-weight: 800; - src: url('../fonts/eot/iranyekanwebextrabold.eot'); - src: url('../fonts/eot/iranyekanwebextrabold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ - url('../fonts/woff/iranyekanwebextrabold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/ - url('../fonts/woff2/iranyekanwebextrabold.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/ - url('../fonts/ttf/iranyekanwebextrabold.ttf') format('truetype'); -} - -@font-face { - font-family: iranyekan; - font-style: normal; - font-weight: 850; - src: url('../fonts/eot/iranyekanwebblack.eot'); - src: url('../fonts/eot/iranyekanwebblack.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ - url('../fonts/woff/iranyekanwebblack.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/ - url('../fonts/woff2/iranyekanwebblack.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/ - url('../fonts/ttf/iranyekanwebblack.ttf') format('truetype'); -} - -@font-face { - font-family: iranyekan; - font-style: normal; - font-weight: 900; - src: url('../fonts/eot/iranyekanwebextrablack.eot'); - src: url('../fonts/eot/iranyekanwebextrablack.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ - url('../fonts/woff/iranyekanwebextrablack.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/ - url('../fonts/woff2/iranyekanwebextrablack.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/ - url('../fonts/ttf/iranyekanwebextrablack.ttf') format('truetype'); -} \ No newline at end of file diff --git a/admin/css/ssbhesabfa-admin.css b/admin/css/ssbhesabfa-admin.css deleted file mode 100644 index fe05fbe..0000000 --- a/admin/css/ssbhesabfa-admin.css +++ /dev/null @@ -1,67 +0,0 @@ -* { - font-family: "Tahoma", "Calibri", sans-serif; -} - -.hand { - cursor: pointer; -} - -.hesabix-tab-icon { - width: 16px; - height: 16px; - margin-left: 10px; -} - -a.nav-tab { - padding: 5px 10px; - font-weight: normal; - border-radius: 7px 7px 0px 0px; - -} - -.hesabix-tab-page-title { - color: dimgray; -} - -.hesabix-f-12 { - font-size: 12pt; -} - -.hesabix-f li { - font-size: 11pt; -} - -.hesabix-header { - background-color: #304967; - box-shadow: 5px 5px 5px #f3f3f3; - padding: 5px; - margin-right: -20px; -} - -.hesabix-header img { - height: 35px; -} - -.hesabix-card { - max-width: none !important; - margin-left: 20px; - background-color: whitesmoke !important; -} - -.hesabix-bold { - font-weight: bold; -} - -.hesabix-plugin-tutorial-chapter { - color: dimgray; - font-weight: bold; - border-bottom: 1px solid silver; - margin-bottom: 5px; - padding-bottom: 10px; - margin-top: 10px; -} - -.hesabix-plugin-tutorial-chapter:hover { - color: dodgerblue; - cursor: pointer; -} diff --git a/admin/index.php b/admin/index.php deleted file mode 100644 index e71af0e..0000000 --- a/admin/index.php +++ /dev/null @@ -1 +0,0 @@ - خروج محصولات...'); - $('#ssbhesabix-export-product-submit i.spinner').show(); - - $('#exportProductsProgress').show(); - $('#exp ortProductsProgressBar').css('width', 0 + '%').attr('aria-valuenow', 0); - - exportProducts(1, 1, 1, 0); - - return false; - }); - }); -//===================================================================================================================== - function exportProducts(batch, totalBatch, total, updateCount) { - const data = { - 'action': 'adminExportProducts', - 'batch': batch, - 'totalBatch': totalBatch, - 'total': total, - 'updateCount': updateCount - }; - $.post(ajaxurl, data, function (response) { - if (response !== 'failed') { - const res = JSON.parse(response); - res.batch = parseInt(res.batch); - if (res.batch < res.totalBatch) { - let progress = (res.batch * 100) / res.totalBatch; - progress = Math.round(progress); - $('#exportProductsProgressBar').css('width', progress + '%').attr('aria-valuenow', progress); - exportProducts(res.batch + 1, res.totalBatch, res.total, res.updateCount); - return false; - } else { - $('#exportProductsProgressBar').css('width', 100 + '%').attr('aria-valuenow', 100); - setTimeout(() => { - top.location.replace(res.redirectUrl); - }, 1000); - return false; - } - } else { - alert('خطا در استخراج محصولات'); - return false; - } - }); - } -//===================================================================================================================== - $(function () { - // AJAX - Import Products - $('#ssbhesabix_import_products').submit(function () { - // show processing status - $('#ssbhesabix-import-product-submit').attr('disabled', 'disabled'); - $('#ssbhesabix-import-product-submit').removeClass('button-primary'); - $('#ssbhesabix-import-product-submit').html(' در حال ورود کالاها از حسابیکس, لطفاً صبر کنید...'); - $('#ssbhesabix-import-product-submit i.spinner').show(); - - $('#importProductsProgress').show(); - $('#importProductsProgressBar').css('width', 0 + '%').attr('aria-valuenow', 0); - - importProducts(1, 1, 1, 0); - - return false; - }); - }); -//===================================================================================================================== - function importProducts(batch, totalBatch, total, updateCount) { - var data = { - 'action': 'adminImportProducts', - 'batch': batch, - 'totalBatch': totalBatch, - 'total': total, - 'updateCount': updateCount - }; - $.post(ajaxurl, data, function (response) { - if ('failed' !== response) { - const res = JSON.parse(response); - res.batch = parseInt(res.batch); - if (res.batch < res.totalBatch) { - let progress = (res.batch * 100) / res.totalBatch; - progress = Math.round(progress); - $('#importProductsProgressBar').css('width', progress + '%').attr('aria-valuenow', progress); - //alert('batch: ' + res.batch + ', totalBatch: ' + res.totalBatch + ', total: ' + res.total); - importProducts(res.batch + 1, res.totalBatch, res.total, res.updateCount); - return false; - } else { - $('#importProductsProgressBar').css('width', 100 + '%').attr('aria-valuenow', 100); - setTimeout(() => { - top.location.replace(res.redirectUrl); - }, 1000); - return false; - } - } else { - alert('خطا در وارد کردن محصولات'); - return false; - } - }); - } -//===================================================================================================================== - $(function () { - // AJAX - Export Products opening quantity - $('#ssbhesabix_export_products_opening_quantity').submit(function () { - // show processing status - $('#ssbhesabix-export-product-opening-quantity-submit').attr('disabled', 'disabled'); - $('#ssbhesabix-export-product-opening-quantity-submit').removeClass('button-primary'); - $('#ssbhesabix-export-product-opening-quantity-submit').html(' استخراج موجودی اول دوره...'); - $('#ssbhesabix-export-product-opening-quantity-submit i.spinner').show(); - - $('#exportProductsOpeningQuantityProgress').show(); - $('#exportProductsOpeningQuantityProgressBar').css('width', 0 + '%').attr('aria-valuenow', 0); - - exportProductsOpeningQuantity(1, 1, 1); - - return false; - }); - }); - - function exportProductsOpeningQuantity(batch, totalBatch, total) { - var data = { - 'action': 'adminExportProductsOpeningQuantity', - 'batch': batch, - 'totalBatch': totalBatch, - 'total': total - }; - $.post(ajaxurl, data, function (response) { - if ('failed' !== response) { - const res = JSON.parse(response); - res.batch = parseInt(res.batch); - if (res.batch < res.totalBatch) { - let progress = (res.batch * 100) / res.totalBatch; - progress = Math.round(progress); - $('#exportProductsOpeningQuantityProgressBar').css('width', progress + '%').attr('aria-valuenow', progress); - exportProductsOpeningQuantity(res.batch + 1, res.totalBatch, res.total); - return false; - } else { - $('#exportProductsOpeningQuantityProgressBar').css('width', 100 + '%').attr('aria-valuenow', 100); - setTimeout(() => { - top.location.replace(res.redirectUrl); - }, 1000); - return false; - } - } else { - alert('خطا در استخراج موجودی اول دوره'); - return false; - } - }); - } -//===================================================================================================================== - $(function () { - // AJAX - Export Customers - $('#ssbhesabix_export_customers').submit(function () { - // show processing status - $('#ssbhesabix-export-customer-submit').attr('disabled', 'disabled'); - $('#ssbhesabix-export-customer-submit').removeClass('button-primary'); - $('#ssbhesabix-export-customer-submit').html(' خروجی مشتریان، لطفاً صبر کنید...'); - $('#ssbhesabix-export-customer-submit i.spinner').show(); - - $('#exportCustomersProgress').show(); - $('#exportCustomersProgressBar').css('width', 0 + '%').attr('aria-valuenow', 0); - - exportCustomers(1, 1, 1, 0); - - return false; - }); - }); - - function exportCustomers(batch, totalBatch, total, updateCount) { - const data = { - 'action': 'adminExportCustomers', - 'batch': batch, - 'totalBatch': totalBatch, - 'total': total, - 'updateCount': updateCount - }; - $.post(ajaxurl, data, function (response) { - if (response !== 'failed') { - const res = JSON.parse(response); - res.batch = parseInt(res.batch); - if (res.batch < res.totalBatch) { - let progress = (res.batch * 100) / res.totalBatch; - progress = Math.round(progress); - $('#exportCustomersProgressBar').css('width', progress + '%').attr('aria-valuenow', progress); - exportCustomers(res.batch + 1, res.totalBatch, res.total, res.updateCount); - return false; - } else { - $('#exportCustomersProgressBar').css('width', 100 + '%').attr('aria-valuenow', 100); - setTimeout(() => { - top.location.replace(res.redirectUrl); - }, 1000); - return false; - } - } else { - alert('خطا در استخراج مشتریان'); - return false; - } - }); - } -//===================================================================================================================== - $(function () { - // AJAX - Sync Changes - $('#ssbhesabix_sync_changes').submit(function () { - // show processing status - $('#ssbhesabix-sync-changes-submit').attr('disabled', 'disabled'); - $('#ssbhesabix-sync-changes-submit').removeClass('button-primary'); - $('#ssbhesabix-sync-changes-submit').html(' همسان سازی تغییرات...'); - $('#ssbhesabix-sync-changes-submit i.spinner').show(); - - var data = { - 'action': 'adminSyncChanges' - }; - - // post it - $.post(ajaxurl, data, function (response) { - if ('failed' !== response) { - var redirectUrl = response; - - /** Debug **/ - // console.log(redirectUrl); - // return false; - - top.location.replace(redirectUrl); - return false; - } else { - alert('خطا در همگام سازی تغییرات'); - return false; - } - }); - /*End Post*/ - return false; - }); - }); -//===================================================================================================================== - $(function () { - // AJAX - Sync Products - $('#ssbhesabix_sync_products').submit(function () { - - // show processing status - $('#ssbhesabix-sync-products-submit').attr('disabled', 'disabled'); - $('#ssbhesabix-sync-products-submit').removeClass('button-primary'); - $('#ssbhesabix-sync-products-submit').html(' همسان سازی محصولات...'); - $('#ssbhesabix-sync-products-submit i.spinner').show(); - - $('#syncProductsProgress').show(); - $('#syncProductsProgressBar').css('width', 0 + '%').attr('aria-valuenow', 0); - - syncProducts(1, 1, 1); - - return false; - }); - }); -//===================================================================================================================== - function syncProducts(batch, totalBatch, total) { - const data = { - 'action': 'adminSyncProducts', - 'batch': batch, - 'totalBatch': totalBatch, - 'total': total - }; - //$.post(URL, DATA, CALLBACK) - $.post(ajaxurl, data, function (response) { - if (response !== 'failed') { - const res = JSON.parse(response); - res.batch = parseInt(res.batch); - if (res.batch < res.totalBatch) { - let progress = (res.batch * 100) / res.totalBatch; - progress = Math.round(progress); - $('#syncProductsProgressBar').css('width', progress + '%').attr('aria-valuenow', progress); - //alert('batch: ' + res.batch + ', totalBatch: ' + res.totalBatch + ', total: ' + res.total); - syncProducts(res.batch + 1, res.totalBatch, res.total); - return false; - } else { - $('#syncProductsProgressBar').css('width', 100 + '%').attr('aria-valuenow', 100); - setTimeout(() => { - top.location.replace(res.redirectUrl); - }, 1000); - return false; - } - } else { - alert('خطا در همگام سازی محصولات'); - return false; - } - }); - } -//===================================================================================================================== - $(function () { - // AJAX - Sync Orders - $('#ssbhesabix_sync_orders').submit(function () { - // show processing status - $('#ssbhesabix-sync-orders-submit').attr('disabled', 'disabled'); - $('#ssbhesabix-sync-orders-submit').removeClass('button-primary'); - $('#ssbhesabix-sync-orders-submit').html(' همسان سازی سفارشات...'); - $('#ssbhesabix-sync-orders-submit i.spinner').show(); - - $('#syncOrdersProgress').show(); - $('#syncOrdersProgressBar').css('width', 0 + '%').attr('aria-valuenow', 0); - - syncOrders(1, 1, 1, 0); - - return false; - }); - }); - - function syncOrders(batch, totalBatch, total, updateCount) { - var date = $('#ssbhesabix_sync_order_date').val(); - var endDate = $('#ssbhesabix_sync_order_end_date').val(); - - const data = { - 'action': 'adminSyncOrders', - 'date': date, - 'endDate': endDate, - 'batch': batch, - 'totalBatch': totalBatch, - 'total': total, - 'updateCount': updateCount, - }; - - $.post(ajaxurl, data, function (response) { - if (response !== 'failed') { - const res = JSON.parse(response); - res.batch = parseInt(res.batch); - if(res.batch) $('#syncOrdersStatistics').html(`
پارت: ${res.batch} از ${res.totalBatch} - تعداد کل: ${res.total}
`); - if (res.batch < res.totalBatch) { - let progress = (res.batch * 100) / res.totalBatch; - progress = Math.round(progress); - $('#syncOrdersProgressBar').css('width', progress + '%').attr('aria-valuenow', progress); - syncOrders(res.batch + 1, res.totalBatch, res.total, res.updateCount); - return false; - } else { - $('#syncOrdersProgressBar').css('width', 100 + '%').attr('aria-valuenow', 100); - setTimeout(() => { - top.location.replace(res.redirectUrl); - }, 1000); - return false; - } - } else { - alert('خطا در همگام سازی سفارشات'); - return false; - } - }); - } -//===================================================================================================================== - $(function () { - // AJAX - Sync Products - $('#ssbhesabix_update_products').submit(function () { - // show processing status - $('#ssbhesabix-update-products-submit').attr('disabled', 'disabled'); - $('#ssbhesabix-update-products-submit').removeClass('button-primary'); - $('#ssbhesabix-update-products-submit').html(' بروزرسانی محصولات...'); - $('#ssbhesabix-update-products-submit i.spinner').show(); - - $('#updateProductsProgress').show(); - $('#updateProductsProgressBar').css('width', 0 + '%').attr('aria-valuenow', 0); - - updateProducts(1, 1, 1); - - return false; - }); - }); -//===================================================================================================================== - function updateProducts(batch, totalBatch, total) { - var data = { - 'action': 'adminUpdateProducts', - 'batch': batch, - 'totalBatch': totalBatch, - 'total': total - }; - $.post(ajaxurl, data, function (response) { - if ('failed' !== response) { - const res = JSON.parse(response); - res.batch = parseInt(res.batch); - if (res.batch < res.totalBatch) { - let progress = (res.batch * 100) / res.totalBatch; - progress = Math.round(progress); - $('#updateProductsProgressBar').css('width', progress + '%').attr('aria-valuenow', progress); - updateProducts(res.batch + 1, res.totalBatch, res.total); - return false; - } else { - $('#updateProductsProgressBar').css('width', 100 + '%').attr('aria-valuenow', 100); - setTimeout(() => { - top.location.replace(res.redirectUrl); - }, 1000); - return false; - } - } else { - alert('خطا در بروزرسانی محصولات'); - return false; - } - }); - } - -//===================================================================================================================== - - // $(function () { - // // AJAX - Sync Products with ID filter - // $('#ssbhesabix_update_products_with_filter').submit(function (e) { - // - // // Show processing status - // var submitButton = $('#ssbhesabix-update-products-with-filter-submit'); - // submitButton.removeClass('button-primary'); - // submitButton.html(' بروزرسانی محصولات...'); - // }); - // }); - - - - $(function () { - // AJAX - Sync Products - $('#ssbhesabix_update_products_with_filter').submit(function () { - let submitButton = $('#ssbhesabix-update-products-with-filter-submit'); - let offset = document.getElementById("ssbhesabix-update-products-offset").value; - let rpp = document.getElementById("ssbhesabix-update-products-rpp").value; - submitButton.removeClass('button-primary'); - submitButton.html(' بروزرسانی محصولات لطفا صبر کنید...'); - $('#ssbhesabix-update-products-with-filter-submit').attr('disabled', 'disabled'); - - updateProductsWithFilter(offset, rpp); - - return false; - }); - }); -//===================================================================================================================== - function updateProductsWithFilter(offset, rpp) { - var data = { - 'action': 'adminUpdateProductsWithFilter', - 'offset': offset, - 'rpp': rpp, - }; - if(offset && rpp) { - $.post(ajaxurl, data, function (response) { - if ('failed' !== response) { - const res = JSON.parse(response); - if(!res.error) { - top.location.replace(res.redirectUrl); - } - } else { - alert('خطا در بروزرسانی محصولات'); - return false; - } - }); - } else { - alert('فیلد ها را به درستی وارد نمایید'); - submitButton.addClass('button-primary'); - submitButton.html('بروزرسانی محصولات در حسابیکس بر اساس فروشگاه در بازه ID مشخص شده'); - $('#ssbhesabix-update-products-with-filter-submit').removeAttr('disabled'); - return false; - } - } - -//===================================================================================================================== - $(function () { - // AJAX - Clean log - $('#ssbhesabix_clean_log').submit(function (e) { - // show processing status - $('#ssbhesabix-log-clean-submit').attr('disabled', 'disabled'); - $('#ssbhesabix-log-clean-submit').removeClass('button-primary'); - $('#ssbhesabix-log-clean-submit').html(' پاک کردن فایل لاگ، لطفاً صبر کنید...'); - $('#ssbhesabix-log-clean-submit i.spinner').show(); - - var data = { - 'action': 'adminCleanLogFile' - }; - - // post it - $.post(ajaxurl, data, function (response) { - if ('failed' !== response) { - var redirectUrl = response; - - /** Debug **/ - // console.log(redirectUrl); - // return false; - - top.location.replace(redirectUrl); - return false; - } else { - alert('خطا در پاکسازی فایل لاگ'); - return false; - } - }); - /*End Post*/ - return false; - }); - }); -//===================================================================================================================== - $(function () { - // AJAX - Sync Products Manually - $('#ssbhesabix_sync_products_manually').submit(function () { - // show processing status - $('#ssbhesabix_sync_products_manually-submit').attr('disabled', 'disabled'); - $('#ssbhesabix_sync_products_manually-submit').removeClass('button-primary'); - $('#ssbhesabix_sync_products_manually-submit').html(' ذخیره کردن اطلاعات...'); - $('#ssbhesabix_sync_products_manually i.spinner').show(); - - const inputArray = []; - const inputs = $('.code-input'); - console.log(inputs); - for (var n = 0; n < inputs.length; n++) { - var i = inputs[n]; - console.log(i); - const obj = { - id: $(i).attr('id'), - hesabix_id: $(i).val(), - parent_id: $(i).attr('data-parent-id') - } - inputArray.push(obj); - } - - const page = $('#pageNumber').val(); - const rpp = $('#goToPage').attr('data-rpp'); - - var data = { - 'action': 'adminSyncProductsManually', - 'data': JSON.stringify(inputArray), - 'page': page, - 'rpp': rpp - }; - - // post it - $.post(ajaxurl, data, function (response) { - if ('failed' !== response) { - var redirectUrl = response; - - /** Debug **/ - // console.log(redirectUrl); - // return false; - - top.location.replace(redirectUrl); - return false; - } else { - alert('خطا در ذخیره اطلاعات'); - return false; - } - }); - /*End Post*/ - return false; - }); - - $("#goToPage").click(function () { - const page = $('#pageNumber').val(); - const rpp = $('#goToPage').attr('data-rpp'); - window.location.href = "?page=hesabix-sync-products-manually&p=" + page + "&rpp=" + rpp; - }); - - $("#show-tips-btn").click(function () { - $('#tips-alert').removeClass('d-none'); - $('#tips-alert').addClass('d-block'); - }); - - $("#hide-tips-btn").click(function () { - $('#tips-alert').removeClass('d-block'); - $('#tips-alert').addClass('d-none'); - }); - }); - - $(".btn-submit-invoice").on( "click", function() { - var orderId = $(this).attr("data-order-id"); - - var btnEl = $('.btn-submit-invoice[data-order-id=' + orderId + ']'); - - btnEl.attr('aria-disabled', true); - btnEl.addClass('disabled'); - btnEl.html('ثبت فاکتور...'); - //btnEl.show(); - - submitInvoice(orderId); - }); -//===================================================================================================================== - function submitInvoice(orderId) { - var data = { - 'action': 'adminSubmitInvoice', - 'orderId': orderId - }; - $.post(ajaxurl, data, function (response) { - if ('failed' !== response) { - const res = JSON.parse(response); - // refresh page - location.reload(); - } else { - alert('خطا در ثبت فاکتور'); - return false; - } - }); - } - - // change business warning - var oldApiKey = ''; - $("#changeBusinessWarning").hide(); - - $("#ssbhesabix_account_api").focusin( function () { - oldApiKey = $("#ssbhesabix_account_api" ).val(); - }); - $("#ssbhesabix_account_api").focusout( function () { - var newApiKey = $("#ssbhesabix_account_api" ).val(); - if(oldApiKey != '' && oldApiKey != newApiKey) { - $("#changeBusinessWarning").show(); - } - }); -//===================================================================================================================== - $(function () { - // AJAX - clear all plugin data - $('#hesabix-clear-plugin-data').click(function () { - if (confirm('هشدار: با انجام این عملیات کلیه اطلاعات افزونه شامل روابط بین کالاها، مشتریان و فاکتور ها و همینطور تنظیمات افزونه حذف می گردد.' + - 'آیا از انجام این عملیات مطمئن هستید؟')) { - $('#hesabix-clear-plugin-data').addClass('disabled'); - $('#hesabix-clear-plugin-data').html('حذف دیتای افزونه...'); - var data = { - 'action': 'adminClearPluginData' - }; - $.post(ajaxurl, data, function (response) { - $('#hesabix-clear-plugin-data').removeClass('disabled'); - $('#hesabix-clear-plugin-data').html('حذف دیتای افزونه'); - if ('failed' !== response) { - alert('دیتای افزونه با موفقیت حذف شد.'); - return false; - } else { - alert('خطا در هنگام حذف دیتای افزونه.'); - return false; - } - }); - } else { - // Do nothing! - } - return false; - }); - - $('#hesabix-install-plugin-data').click(function () { - if (confirm('با انجام این عملیات جدول افزونه در دیتابیس وردپرس ایجاد' + - ' و تنظیمات پیش فرض افزونه تنظیم می گردد.' + - ' آیا از انجام این عملیات مطمئن هستید؟')) { - $('#hesabix-install-plugin-data').addClass('disabled'); - $('#hesabix-install-plugin-data').html('نصب دیتای افزونه...'); - var data = { - 'action': 'adminInstallPluginData' - }; - $.post(ajaxurl, data, function (response) { - $('#hesabix-install-plugin-data').removeClass('disabled'); - $('#hesabix-install-plugin-data').html('نصب دیتای افزونه'); - if ('failed' !== response) { - alert('دیتای افزونه با موفقیت نصب شد.'); - return false; - } else { - alert('خطا در هنگام نصب دیتای افزونه.'); - return false; - } - }); - } else { - // Do nothing! - } - return false; - }); - }); -//===================================================================================================================== - $(function () { - //SAVE - $(".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(); - var data = { - 'action': 'adminChangeProductCode', - 'productId': productId, - 'attributeId': attributeId, - 'code': code, - }; - $(this).prop('disabled', true); - const _this = this; - $.post(ajaxurl, data, function (response) { - $(_this).prop('disabled', false); - if ('failed' !== response) { - const res = JSON.parse(response); - alert(res.error ? res.message : 'کد کالای متصل با موفقیت تغییر کرد.'); - if(productId === attributeId) - $("#ssbhesabix_hesabix_item_code_0").val(code); - else - $("#ssbhesabix_hesabix_item_code_" + attributeId).val(code); - return false; - } else { - alert('خطا در هنگام تغییر کد کالای متصل.'); - return false; - } - }); - }); - //DELETE LINK - $(".hesabix-item-delete-link").on('click', function (){ - const productId = $("#panel_product_data_hesabix").data('product-id'); - const attributeId = $(this).data('id'); - var data = { - 'action': 'adminDeleteProductLink', - 'productId': productId, - 'attributeId': attributeId - }; - $(this).prop('disabled', true); - const _this = this; - $.post(ajaxurl, data, function (response) { - $(_this).prop('disabled', false); - if ('failed' !== response) { - const res = JSON.parse(response); - $("#hesabix-item-" + attributeId).val(''); - if(productId === attributeId) - $("#ssbhesabix_hesabix_item_code_0").val(''); - else - $("#ssbhesabix_hesabix_item_code_" + attributeId).val(''); - setTimeout(function (){ - alert(res.error ? res.message : 'ارتباط محصول با موفقیت حذف شد'); - }, 100); - return false; - } else { - alert('خطا در هنگام حذف ارتباط'); - return false; - } - }); - }); - //UPDATE - $(".hesabix-item-update").on('click', function (){ - const productId = $("#panel_product_data_hesabix").data('product-id'); - const attributeId = $(this).data('id'); - var data = { - 'action': 'adminUpdateProduct', - 'productId': productId, - 'attributeId': attributeId - }; - $(this).prop('disabled', true); - const _this = this; - $.post(ajaxurl, data, function (response) { - $(_this).prop('disabled', false); - if ('failed' !== response) { - 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); - return false; - } else { - alert('خطا در هنگام بروزرسانی محصول'); - return false; - } - }); - }); - //SAVE ALL - $("#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}); - } - - var data = { - 'action': 'adminChangeProductsCode', - 'productId': productId, - 'itemsData': itemsData - }; - $(this).prop('disabled', true); - const _this = this; - $.post(ajaxurl, data, function (response) { - $(_this).prop('disabled', false); - if ('failed' !== response) { - const res = JSON.parse(response); - alert(res.error ? res.message : 'کد کالاهای متصل با موفقیت تغییر کرد.'); - location.reload(); - return false; - } else { - alert('خطا در هنگام تغییر کد کالاهای متصل'); - return false; - } - }); - }); - //DELETE - $("#hesabix-item-delete-link-all").on('click', function (){ - const productId = $("#panel_product_data_hesabix").data('product-id'); - var data = { - 'action': 'adminDeleteProductsLink', - 'productId': productId - }; - $(this).prop('disabled', true); - const _this = this; - $.post(ajaxurl, data, function (response) { - $(_this).prop('disabled', false); - if ('failed' !== response) { - 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^="ssbhesabix_hesabix_item_code_"]').val(''); - setTimeout(function (){ - alert(res.error ? res.message : 'ارتباط محصولات با موفقیت حذف شد.'); - }, 100); - return false; - } else { - alert('خطا در هنگام حذف ارتباط'); - return false; - } - }); - }); - //UPDATE ALL - $("#hesabix-item-update-all").on('click', function (){ - const productId = $("#panel_product_data_hesabix").data('product-id'); - var data = { - 'action': 'adminUpdateProductAndVariations', - 'productId': productId - }; - $(this).prop('disabled', true); - const _this = this; - $.post(ajaxurl, data, function (response) { - $(_this).prop('disabled', false); - if ('failed' !== response) { - const res = JSON.parse(response); - if(res.error) - { - alert(res.message); - return false; - } - 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); - } - return false; - } else { - alert('خطا در هنگام بروزرسانی محصول'); - return false; - } - }); - }); - }); -//===================================================================================================================== - $(function (){ - let radio = $('input:radio[name="addFieldsRadio"]'); - let radioChecked = $('input:radio[name="addFieldsRadio"]:checked'); - let 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 ); - } - }); - - }); -}); -//===================================================================================================================== -function hesabixTutorialJumpTo(time) { - let vidEl = document.getElementById('hesabix-tutorial-video'); - vidEl.play(); - vidEl.pause(); - vidEl.currentTime = time; - vidEl.play(); -} diff --git a/admin/partials/hesabix-admin-display.php b/admin/partials/hesabix-admin-display.php new file mode 100644 index 0000000..fb26275 --- /dev/null +++ b/admin/partials/hesabix-admin-display.php @@ -0,0 +1,297 @@ +get_results( + "SELECT id_hesabix + FROM {$wpdb->prefix}hesabix + WHERE obj_type = 'product' + GROUP BY id_hesabix + HAVING COUNT(id_hesabix) > 1" + ); + + $ids = array(); + + foreach ($rows as $row) + $ids[] = $row->id_hesabix; + + $idsStr = implode(',', $ids); + + $rows = $wpdb->get_results( + $wpdb->prepare( + "SELECT * + FROM {$wpdb->prefix}hesabix + WHERE obj_type = 'product' + AND id_hesabix IN ($idsStr) + ORDER BY id_hesabix" + ) + ); + + $i = 0; + + self::hesabix_plugin_header(); + ?> +
+
+ +
+ + + + + + + + + + + + + + + + + + + +
#
id_hesabix; ?>id_ps; ?>id_ps_attribute; ?>
+
+ +
+
+ +
+ + +
+ +
+ get_results( + $wpdb->prepare( + "SELECT post.ID, post.post_title, post.post_parent, post.post_excerpt, wc.sku + FROM {$wpdb->posts} AS post + LEFT OUTER JOIN {$wpdb->prefix}wc_product_meta_lookup AS wc + ON post.ID = wc.product_id + WHERE post.post_type IN ('product', 'product_variation') + AND post.post_status IN ('publish', 'private') + ORDER BY post.post_title ASC + LIMIT %d, %d", + $offset, + $rpp + ) + ); + + $totalCount = $wpdb->get_var( + "SELECT COUNT(*) + FROM {$wpdb->posts} AS post + LEFT OUTER JOIN {$wpdb->prefix}wc_product_meta_lookup AS wc + ON post.ID = wc.product_id + WHERE post.post_type IN ('product', 'product_variation') + AND post.post_status IN ('publish', 'private')" + ); + + $links = $wpdb->get_results( + "SELECT * + FROM {$wpdb->prefix}hesabix + WHERE obj_type = 'product'" + ); + + foreach ($rows as $r) { + if ($r->post_excerpt) + $r->post_title = $r->post_title . ' [' . $r->post_excerpt . ']'; + } + + foreach ($links as $link) { + foreach ($rows as $r) { + if ($r->ID == $link->id_ps && $link->id_ps_attribute == 0) { + $r->id_hesabix = $link->id_hesabix; + } else if ($r->ID == $link->id_ps_attribute) { + $r->id_hesabix = $link->id_hesabix; + } + } + } + + return array("data" => $rows, "totalCount" => $totalCount); + } + + public static function hesabix_plugin_page() + { + $iconsArray = [ + 'home', + 'cog', + 'box-open', + 'users', + 'file-invoice-dollar', + 'sync-alt', + 'file-alt', + 'cog' + ]; + if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) { + $setting_tabs = apply_filters('hesabix_setting_tab', array( + 'home' => __('Home', 'hesabix'), + 'api' => __('API', 'hesabix'), + 'catalog' => __('Catalog', 'hesabix'), + 'customers' => __('Customers', 'hesabix'), + 'invoice' => __('Invoice', 'hesabix'), + 'sync' => __('Sync', 'hesabix'), + 'log' => __('Log', 'hesabix'), + 'extra' => __('Extra Settings', 'hesabix') + )); + $current_tab = (isset($_GET['tab'])) ? wc_clean($_GET['tab']) : 'home'; + ?> +
+
+ + +
+ $label) { + $iconUrl = HESABIX_PLUGIN_URL . "assets/img/icons/$iconsArray[$i].svg"; + $i++; + $active_class = ($current_tab == $name) ? 'active' : ''; + echo ''; + } + ?> +
+ +
+ $setting_tabvalue) { + switch ($setting_tabkey) { + case $current_tab: + do_action('hesabix_' . $setting_tabkey . '_setting_save_field'); + do_action('hesabix_' . $setting_tabkey . '_setting'); + break; + } + } + ?> +
+
+
+ +
+
+
+ + + +
+ +
+
+
+
+
+ +
+ +
+

+

+
+ + + + + + + + +
+
+
+ +
+ + + + + + + +
+
+
+ format($date); + return $this->convertPersianDigitsToEnglish($formatted); + } catch (Exception $e) { + return ''; + } + } + + public static function isDateInFiscalYear($date) + { + $hesabixApi = new Hesabix_Api(); + $fiscalYear = $hesabixApi->settingGetFiscalYear(); + if (is_object($fiscalYear)) { + + if ($fiscalYear->Success) { + $fiscalYearStartTimeStamp = strtotime($fiscalYear->Result->StartDate); + $fiscalYearEndTimeStamp = strtotime($fiscalYear->Result->EndDate); + $dateTimeStamp = strtotime($date); + + if ($dateTimeStamp >= $fiscalYearStartTimeStamp && $dateTimeStamp <= $fiscalYearEndTimeStamp) { + return 1; + } else { + return __('date is not in fiscal year', 'hesabix'); + } + } else { + HesabixLogService::log(array("Cannot get FiscalDate. Error Code: $fiscalYear->ErrroCode. Error Message: $fiscalYear->ErrorMessage")); + return __('Cannot connect to Hesabix for get FiscalDate.', 'hesabix'); + } + } else { + return __('Cannot connect to Hesabix for get FiscalDate.', 'hesabix'); + } + HesabixLogService::log(array("Cannot connect to Hesabix for get FiscalDate.")); + return __('Cannot connect to Hesabix for get FiscalDate.', 'hesabix'); + } + + public function getProductVariations($id_product) + { + if (!isset($id_product)) { + return false; + } + $product = wc_get_product($id_product); + + if (is_bool($product)) + return false; + if ($product->is_type('variable')) { + $children = $product->get_children($args = '', $output = OBJECT); + $variations = array(); + foreach ($children as $value) { + $product_variatons = new WC_Product_Variation($value); + if ($product_variatons->exists()) { + $variations[] = $product_variatons; + } + } + return $variations; + } + return false; + } + + public function setItems($id_product_array) + { + if (!isset($id_product_array) || $id_product_array[0] == null) + return false; + if (is_array($id_product_array) && empty($id_product_array)) + return true; + + $items = array(); + foreach ($id_product_array as $id_product) { + $product = new WC_Product($id_product); + if ($product->get_status() === "draft") + continue; + + $items[] = HesabixItemService::mapProduct($product, $id_product, false); + + $variations = $this->getProductVariations($id_product); + if ($variations) + foreach ($variations as $variation) + $items[] = HesabixItemService::mapProductVariation($product, $variation, $id_product, false); + } + + if (count($items) === 0) + return false; + if (!$this->saveItems($items)) + return false; + return true; + } + + public function saveItems($items) + { + $hesabix = new Hesabix_Api(); + $wpFaService = new HesabixWpFaService(); + + $response = $hesabix->itemBatchSave($items); + if ($response->Success) { + foreach ($response->createdItems as $item) + $wpFaService->saveProduct($item); + return true; + } else { + HesabixLogService::log(array("Cannot add/update Hesabix items. Error Code: " . (string) $response->ErrorCode . ". Error Message: $response->ErrorMessage.")); + return false; + } + } + + public function getContactCodeByCustomerId($id_customer) + { + if (!isset($id_customer)) { + return false; + } + + global $wpdb; + + + $row = $wpdb->get_row( + $wpdb->prepare( + "SELECT `id_hesabix` FROM {$wpdb->prefix}hesabix + WHERE `id_ps` = %d AND `obj_type` = 'customer'", + $id_customer + ) + ); + + if (is_object($row)) { + return $row->id_hesabix; + } else { + return null; + } + } + + public function setContact($id_customer, $type = 'first', $id_order = '') + { + if (!isset($id_customer)) + return false; + + $code = $this->getContactCodeByCustomerId($id_customer); + + $hesabixCustomer = HesabixCustomerService::mapCustomer($code, $id_customer, $type, $id_order); + + $hesabix = new Hesabix_Api(); + $response = $hesabix->contactSave($hesabixCustomer); + + if ($response->Success) { + $wpFaService = new HesabixWpFaService(); + $wpFaService->saveCustomer($response->person); + return $response->person->code; + } else { + HesabixLogService::log(array("Cannot add/update customer. Error Code: " . (string) $response->ErrroCode . ". Error Message: " . (string) $response->ErrorMessage . ". Customer ID: $id_customer")); + return false; + } + } + + public function setGuestCustomer($id_order) + { + if (!isset($id_order)) + return false; + + + $order = wc_get_order($id_order); + + $contactCode = $this->getContactCodeByPhoneOrEmail($order->get_billing_phone(), $order->get_billing_email()); + + $hesabixCustomer = HesabixCustomerService::mapGuestCustomer($contactCode, $id_order); + + $hesabix = new Hesabix_Api(); + $response = $hesabix->contactSave($hesabixCustomer); + + if ($response->Success) { + $wpFaService = new HesabixWpFaService(); + $wpFaService->saveCustomer($response->Result); + return (int) $response->Result->code; + } else { + HesabixLogService::log(array("Cannot add/update contact. Error Code: " . (string) $response->ErrroCode . ". Error Message: " . (string) $response->ErrorMessage . ". Customer ID: Guest Customer")); + return false; + } + } + + public function getContactCodeByPhoneOrEmail($phone, $email) + { + if (!$email && !$phone) + return null; + + $hesabix = new Hesabix_Api(); + $response = $hesabix->contactGetByPhoneOrEmail($phone, $email); + + if (is_object($response)) { + if ($response->Success && $response->Result->TotalCount > 0) { + $contact_obj = $response->Result->List; + + if (!$contact_obj[0]->code || $contact_obj[0]->code == '0' || $contact_obj[0]->code == '000000') + return null; + + foreach ($contact_obj as $contact) { + if (($contact->phone == $phone || $contact->mobile = $phone) && $contact->email == $email) + return (int) $contact->code; + } + foreach ($contact_obj as $contact) { + if ($phone && $contact->phone == $phone || $contact->mobile = $phone) + return (int) $contact->code; + } + foreach ($contact_obj as $contact) { + if ($email && $contact->email == $email) + return (int) $contact->code; + } + return null; + } + } else { + HesabixLogService::log(array("Cannot get Contact list. Error Message: (string)$response->ErrorMessage. Error Code: (string)$response->ErrorCode.")); + } + + return null; + } + + private function formatInvoiceItems($products) + { + $wpFaService = new HesabixWpFaService(); + $items = []; + foreach ($products as $product) { + $wcProduct = $product['variation_id'] + ? wc_get_product($product['variation_id']) + : wc_get_product($product['product_id']); + + $product_id = $product['product_id']; + $code = $wpFaService->getProductCodeByWpId($product_id, $product['variation_id']); + $uid = $wpFaService->getProductUidByCode($code); + if (!$code) + continue; + if (!$uid) + continue; + + + if ($wcProduct->is_on_sale() && get_option('hesabix_set_special_sale_as_discount') === 'yes') { + $unit_price = $this->getPriceInHesabixDefaultCurrency($wcProduct->get_regular_price()); + $discountAmount = $this->getPriceInHesabixDefaultCurrency($wcProduct->get_regular_price() - $wcProduct->get_sale_price()); + $discountAmount *= $product['quantity']; + $total = $this->getPriceInHesabixDefaultCurrency($product['total']); + } else { + $unit_price = $this->getPriceInHesabixDefaultCurrency($product['subtotal'] / $product['quantity']); + $total = $this->getPriceInHesabixDefaultCurrency($product['total']); + $discountAmount = $this->getPriceInHesabixDefaultCurrency($product['subtotal'] - $product['total']); + } + + $items[] = [ + 'name' => [ + 'id' => $uid, + 'name' => $product['name'], + 'code' => $code, + 'priceSell' => (float) $unit_price, + ], + 'count' => (int) $product['quantity'], + 'price' => (float) $unit_price, + 'discountType' => 'percent', + 'discountPercent' => 0, + 'discountAmount' => (float) $discountAmount, + 'description' => '', + 'showPercentDiscount' => true, + 'total' => (float) $total, + 'tax' => (float) $this->getPriceInHesabixDefaultCurrency($product['total_tax']) + ]; + } + return $items; + } + + public function setOrder($id_order, $orderType = 0, $reference = null) + { + if (!isset($id_order)) { + return false; + } + + $wpFaService = new HesabixWpFaService(); + + $number = $this->getInvoiceNumberByOrderId($id_order); + if (!$number) { + $number = null; + if ($orderType == 2) { + return false; + } + } + + $order = wc_get_order($id_order); + + $dokanOption = get_option("hesabix_invoice_dokan", 0); + + if ($dokanOption && is_plugin_active("dokan-lite/dokan.php")) { + $orderCreated = $order->get_created_via(); + if ($dokanOption == 1 && $orderCreated !== 'checkout') + return false; + else if ($dokanOption == 2 && $orderCreated === 'checkout') + return false; + } + + $id_customer = $order->get_customer_id(); + if ($id_customer !== 0) { + + $contactCode = $this->setContact($id_customer, 'first', $id_order); + + if ($contactCode == null) { + if (!$contactCode) { + return false; + } + } + HesabixLogService::writeLogStr("order ID " . $id_order); + if (get_option('hesabix_contact_address_status') == 2) { + $this->setContact($id_customer, 'billing', $id_order); + } elseif (get_option('hesabix_contact_address_status') == 3) { + $this->setContact($id_customer, 'shipping', $id_order); + } + } else { + $contactCode = $this->setGuestCustomer($id_order); + if (!$contactCode) { + return false; + } + } + + global $notDefinedProductID; + $notDefinedItems = array(); + $products = $order->get_items(); + foreach ($products as $product) { + if ($product['product_id'] == 0) + continue; + $itemCode = $wpFaService->getProductCodeByWpId($product['product_id'], $product['variation_id']); + if ($itemCode == null) { + $notDefinedItems[] = $product['product_id']; + } + } + + if (!empty($notDefinedItems)) { + if (!$this->setItems($notDefinedItems)) { + HesabixLogService::writeLogStr("Cannot add/update Invoice. Failed to set products. Order ID: $id_order"); + return false; + } + } + + $invoiceItems = array(); + $i = 0; + $failed = false; + + $invoiceItems = $this->formatInvoiceItems($products); + + + if (empty($invoiceItems)) { + HesabixLogService::writeLogStr("Cannot add/update Invoice. No valid items found. Order ID: $id_order"); + return false; + } + + if ($failed) { + HesabixLogService::writeLogStr("Cannot add/update Invoice. Item code is NULL. Check your invoice products and relations with Hesabix. Order ID: $id_order"); + return false; + } + + if (empty($invoiceItems)) { + HesabixLogService::log(array("Cannot add/update Invoice. At least one item required.")); + return false; + } + + $date_obj = $order->get_date_created(); + switch ($orderType) { + case 0: + $date = $date_obj->date('Y-m-d H:i:s'); + break; + case 2: + $date = date('Y-m-d H:i:s'); + break; + default: + $date = $date_obj->date('Y-m-d H:i:s'); + } + + if ($reference === null) + $reference = $id_order; + + global $freightOption, $freightItemCode; + $freightOption = get_option("hesabix_invoice_freight"); + + $order_shipping_method = ""; + foreach ($order->get_items('shipping') as $item) + $order_shipping_method = $item->get_name(); + + $note = $order->get_customer_note(); + if ($order_shipping_method && $freightOption == 0) + $note .= "\n" . __('Shipping method', 'hesabix') . ": " . $order_shipping_method; + + + $freightItems = []; + + if ($freightOption == 1) { + $freightItemCode = get_option('hesabix_invoice_freight_code'); + if (!isset($freightItemCode) || !$freightItemCode) + HesabixLogService::writeLogStr(__("Freight service code is not defined", 'hesabix') . "\n" . "Freight service code is not set"); + + $freightItemCode = $this->convertPersianDigitsToEnglish($freightItemCode); + + if ($this->getPriceInHesabixDefaultCurrency($order->get_shipping_total()) != 0) { + + $wpFaService = new HesabixWpFaService(); + $uid = $wpFaService->getProductUidByCode($freightItemCode); + + if ($uid) { + $freightItems[] = [ + 'name' => [ + 'id' => $uid, + 'name' => __('Freight Cost', 'hesabix'), + 'code' => $freightItemCode, + 'priceSell' => (float) $this->getPriceInHesabixDefaultCurrency($order->get_shipping_total()), + ], + 'count' => 1, + 'price' => (float) $this->getPriceInHesabixDefaultCurrency($order->get_shipping_total()), + 'discountType' => 'percent', + 'discountPercent' => 0, + 'discountAmount' => 0, + 'description' => __('Freight method', 'hesabix') . ": " . $order_shipping_method, + 'showPercentDiscount' => true, + 'total' => (float) $this->getPriceInHesabixDefaultCurrency($order->get_shipping_total()), + 'tax' => (float) $this->getPriceInHesabixDefaultCurrency($order->get_shipping_tax()) + ]; + } + } + } + + $contactId = $wpFaService->getCustomerUidByCode($contactCode); + + if (!isset($contactId)) { + return false; + } + + + $allItems = $this->formatInvoiceItems($products); + if (!empty($freightItems)) { + $allItems = array_merge($allItems, $freightItems); + } + + $data = [ + 'id' => '', + 'invoiceDate' => $this->convertToJalali($date), + 'customer' => (int) $contactId, + 'invoiceDescription' => $note, + 'totalInvoice' => $this->getPriceInHesabixDefaultCurrency($order->get_total()), + 'taxPercent' => 0, + 'discountType' => 'percent', + 'discountPercent' => 0, + 'totalDiscount' => 0, + + 'showTotalPercentDiscount' => true, + 'items' => $allItems, + 'sendSmsToCustomer' => false, + 'payments' => [] + ]; + + if ($freightOption == 0) { + $freight = $this->getPriceInHesabixDefaultCurrency($order->get_shipping_total() + $order->get_shipping_tax()); + $data['shippingCost'] = $freight; + } + + + + + + $invoice_project = get_option('hesabix_invoice_project', -1); + $invoice_salesman = get_option('hesabix_invoice_salesman', -1); + $invoice_salesman_percentage = get_option('hesabix_invoice_salesman_percentage', 0); + if ($invoice_project != -1) + $data['Project'] = $invoice_project; + if ($invoice_salesman != -1) + $data['SalesmanCode'] = $invoice_salesman; + if ($invoice_salesman_percentage) if ($invoice_salesman_percentage != 0) + $data['SalesmanPercent'] = $this->convertPersianDigitsToEnglish($invoice_salesman_percentage); + + $hesabix = new Hesabix_Api(); + $response = $hesabix->invoiceSave($data); + + if ($response->Success) { + global $wpdb; + + switch ($orderType) { + case 0: + $obj_type = 'order'; + break; + case 2: + $obj_type = 'returnOrder'; + break; + } + + if ($number === null) { + $wpdb->insert($wpdb->prefix . 'hesabix', array( + 'id_hesabix' => (int) $response->data->id, + 'obj_type' => $obj_type, + 'id_ps' => $id_order, + )); + HesabixLogService::log(array("Invoice successfully added. Invoice number: " . (string) $response->Result->Number . ". Order ID: $id_order")); + } else { + $wpFaId = $wpFaService->getWpFaId($obj_type, $id_order); + + $wpdb->update($wpdb->prefix . 'hesabix', array( + 'id_hesabix' => (int) $response->data->id, + 'obj_type' => $obj_type, + 'id_ps' => $id_order, + ), array('id' => $wpFaId)); + HesabixLogService::log(array("Invoice successfully updated. Invoice number: " . (string) $response->Result->Number . ". Order ID: $id_order")); + } + + // $warehouse = get_option('hesabix_item_update_quantity_based_on', "-1"); + // if ($warehouse != "-1" && $orderType === 0) + // $this->setWarehouseReceipt($invoiceItems, (int) $response->Result->Number, $warehouse, $date, $invoice_project); + + return true; + } else { + foreach ($invoiceItems as $item) { + HesabixLogService::log(array( + "Cannot add/update Invoice. Error Code: " . (string) $response->ErrorCode . ". Error Message: " . (string) $response->ErrorMessage . ". Order ID: $id_order" . "\n" + . "Hesabix Id:" . $item['ItemCode'] + )); + } + return false; + } + } + + public function setWarehouseReceipt($items, $invoiceNumber, $warehouseCode, $date, $project) + { + $invoiceOption = get_option('hesabix_invoice_freight'); + if ($invoiceOption == 1) { + $invoiceFreightCode = get_option('hesabix_invoice_freight_code'); + for ($i = 0; $i < count($items); $i++) { + if ($items[$i]["ItemCode"] == $invoiceFreightCode) { + unset($items[$i]); + } + } + } + + $data = array( + 'WarehouseCode' => $warehouseCode, + 'InvoiceNumber' => $invoiceNumber, + 'InvoiceType' => 0, + 'Date' => $date, + 'Items' => $items + ); + + if ($project != -1) + $data['Project'] = $project; + + $hesabix = new Hesabix_Api(); + $response = $hesabix->saveWarehouseReceipt($data); + + if ($response->Success) + HesabixLogService::log(array("Warehouse receipt successfully saved/updated. warehouse receipt number: " . (string) $response->Result->Number . ". Invoice number: $invoiceNumber")); + else + HesabixLogService::log(array("Cannot save/update Warehouse receipt. Error Code: " . (string) $response->ErrorCode . ". Error Message: " . (string) $response->ErrorMessage . ". Invoice number: $invoiceNumber")); + } + + public static function getPriceInHesabixDefaultCurrency($price) + { + if (!isset($price)) + return false; + + $woocommerce_currency = get_woocommerce_currency(); + $hesabix_currency = get_option('hesabix_hesabix_default_currency'); + + if (!is_numeric($price)) + $price = intval($price); + + if ($hesabix_currency == 'IRR' && $woocommerce_currency == 'IRT') + $price *= 10; + + if ($hesabix_currency == 'IRT' && $woocommerce_currency == 'IRR') + $price /= 10; + + return $price; + } + + public static function getPriceInWooCommerceDefaultCurrency($price) + { + if (!isset($price)) + return false; + + $woocommerce_currency = get_woocommerce_currency(); + $hesabix_currency = get_option('hesabix_hesabix_default_currency'); + + if (!is_numeric($price)) + $price = intval($price); + + if ($hesabix_currency == 'IRR' && $woocommerce_currency == 'IRT') + $price /= 10; + + if ($hesabix_currency == 'IRT' && $woocommerce_currency == 'IRR') + $price *= 10; + + return $price; + } + + public function setOrderPayment($id_order) + { + if (!isset($id_order)) { + return false; + } + + $hesabix = new Hesabix_Api(); + $number = $this->getInvoiceCodeByOrderId($id_order); + if (!$number) { + return false; + } + + + $order = wc_get_order($id_order); + + if ($order->get_total() <= 0) { + return true; + } + + + $transaction_id = $order->get_transaction_id(); + + if ($transaction_id == '') { + $transaction_id = '-'; + } + + global $financialData; + if (get_option('hesabix_payment_option') == 'no') { + $bank_code = $this->getBankCodeByPaymentMethod($order->get_payment_method()); + if ($bank_code != false) { + $payTempValue = substr($bank_code, 0, 4); + + switch ($payTempValue) { + case 'bank': + $payTempValue = substr($bank_code, 4); + $financialData = array('bankCode' => $payTempValue); + break; + case 'cash': + $payTempValue = substr($bank_code, 4); + $financialData = array('cashCode' => $payTempValue); + break; + } + } else { + HesabixLogService::log(array("Cannot add Hesabix Invoice payment - Bank Code not defined. Order ID: $id_order")); + return false; + } + } elseif (get_option('hesabix_payment_option') == 'yes') { + $defaultBankCode = $this->convertPersianDigitsToEnglish(get_option('hesabix_default_payment_method_code')); + if ($defaultBankCode != false) { + $financialData = array('bankCode' => $defaultBankCode); + } else { + HesabixLogService::writeLogStr("Default Bank Code is not Defined"); + return false; + } + } + + $date_obj = $order->get_date_paid(); + if ($date_obj == null) { + $date_obj = $order->get_date_modified(); + } + + global $accountPath; + + if (get_option("hesabix_cash_in_transit") == "1" || get_option("hesabix_cash_in_transit") == "yes") { + $func = new Hesabix_Admin_Functions(); + $cashInTransitFullPath = $func->getCashInTransitFullPath(); + if (!$cashInTransitFullPath) { + HesabixLogService::writeLogStr("Cash in Transit is not Defined in Hesabix ---- " . __('Cash in Transit not found in Hesabix', 'hesabix')); + return false; + } else { + $accountPath = array("accountPath" => $cashInTransitFullPath); + } + } + + $response = $hesabix->invoiceGet($number); + if ($response->Success) { + if ($response->Result->Paid > 0) { + + } else { + $paymentMethod = $order->get_payment_method(); + $transactionFee = 0; + if (isset($paymentMethod)) { + if (get_option("hesabix_payment_transaction_fee_$paymentMethod") > 0) + $transactionFee = $this->formatTransactionFee(get_option("hesabix_payment_transaction_fee_$paymentMethod"), $this->getPriceInHesabixDefaultCurrency($order->get_total())); + else + $transactionFee = $this->formatTransactionFee(get_option("hesabix_invoice_transaction_fee"), $this->getPriceInHesabixDefaultCurrency($order->get_total())); + } + + if (isset($transactionFee) && $transactionFee != null) + $response = $hesabix->invoiceSavePayment($number, $financialData, $accountPath, $date_obj->date('Y-m-d H:i:s'), $this->getPriceInHesabixDefaultCurrency($order->get_total()), $transaction_id, '', $transactionFee); + else + $response = $hesabix->invoiceSavePayment($number, $financialData, $accountPath, $date_obj->date('Y-m-d H:i:s'), $this->getPriceInHesabixDefaultCurrency($order->get_total()), $transaction_id, '', 0); + + if ($response->Success) { + HesabixLogService::log(array("Hesabix invoice payment added. Order ID: $id_order")); + return true; + } else { + HesabixLogService::log(array("Cannot add Hesabix Invoice payment. Order ID: $id_order. Error Code: " . (string) $response->ErrorCode . ". Error Message: " . (string) $response->ErrorMessage . ".")); + return false; + } + } + return true; + } else { + HesabixLogService::log(array("Error while trying to get invoice. Invoice Number: $number. Error Code: " . (string) $response->ErrorCode . ". Error Message: " . (string) $response->ErrorMessage . ".")); + return false; + } + } + + public function getCashInTransitFullPath() + { + $api = new Hesabix_Api(); + $accounts = $api->settingGetAccounts(); + foreach ($accounts->Result as $account) { + if ($account->Name == "وجوه در راه") { + return $account->FullPath; + } + } + return false; + } + + public function getInvoiceNumberByOrderId($id_order) + { + if (!isset($id_order)) + return false; + + global $wpdb; + $row = $wpdb->get_row("SELECT `id_hesabix` FROM " . $wpdb->prefix . "hesabix WHERE `id_ps` = $id_order AND `obj_type` = 'order'"); + + if (is_object($row)) { + return $row->id_hesabix; + } else { + return false; + } + } + + public function getBankCodeByPaymentMethod($payment_method) + { + $code = get_option('hesabix_payment_method_' . $payment_method); + + if (isset($code)) + return $code; + else + return false; + } + + public function getInvoiceCodeByOrderId($id_order) + { + if (!isset($id_order)) + return false; + + global $wpdb; + $row = $wpdb->get_row("SELECT `id_hesabix` FROM " . $wpdb->prefix . "hesabix WHERE `id_ps` = $id_order AND `obj_type` = 'order'"); + + if (is_object($row)) { + return $row->id_hesabix; + } else { + return false; + } + } + + public function exportProducts($batch, $totalBatch, $total, $updateCount) + { + HesabixLogService::writeLogStr("Exporting Products"); + try { + $wpFaService = new HesabixWpFaService(); + $extraSettingRPP = get_option("hesabix_set_rpp_for_export_products"); + $rpp = 500; + if ($extraSettingRPP) { + if ($extraSettingRPP != '-1' && $extraSettingRPP != '0') { + $rpp = $extraSettingRPP; + } + } + $result = array(); + $result["error"] = false; + global $wpdb; + + if ($batch == 1) { + + + + $total = $wpdb->get_var( + $wpdb->prepare( + "SELECT COUNT(*) FROM {$wpdb->posts} + WHERE post_type = 'product' AND post_status IN ('publish', 'private')" + ) + ); + + $totalBatch = ceil($total / $rpp); + } + + $offset = ($batch - 1) * $rpp; + + + + $products = $wpdb->get_results( + $wpdb->prepare( + "SELECT ID FROM {$wpdb->posts} + WHERE post_type = 'product' AND post_status IN ('publish', 'private') + ORDER BY ID ASC + LIMIT %d, %d", + $offset, + $rpp + ) + ); + + $items = array(); + + foreach ($products as $item) { + $id_product = $item->ID; + $product = new WC_Product($id_product); + + $id_obj = $wpFaService->getWpFaId('product', $id_product, 0); + + if (!$id_obj) { + $hesabixItem = HesabixItemService::mapProduct($product, $id_product); + array_push($items, $hesabixItem); + $updateCount++; + } + + $variations = $this->getProductVariations($id_product); + if ($variations) { + foreach ($variations as $variation) { + $id_attribute = $variation->get_id(); + $id_obj = $wpFaService->getWpFaId('product', $id_product, $id_attribute); + + if (!$id_obj) { + $hesabixItem = HesabixItemService::mapProductVariation($product, $variation, $id_product); + array_push($items, $hesabixItem); + $updateCount++; + } + } + } + } + + if (!empty($items)) { + $count = 0; + $hesabix = new Hesabix_Api(); + $response = $hesabix->itemBatchSave($items); + if ($response->Success) { + foreach ($response->Result as $item) { + $json = json_decode($item->Tag); + + global $wpdb; + $wpdb->insert($wpdb->prefix . 'hesabix', array( + 'id_hesabix' => (int) $item->code, + 'obj_type' => 'product', + 'id_ps' => (int) $json->id_product, + 'id_ps_attribute' => (int) $json->id_attribute, + )); + HesabixLogService::log(array("Item successfully added. Item Code: " . (string) $item->code . ". Product ID: $json->id_product - $json->id_attribute")); + } + $count += count($response->Result); + } else { + HesabixLogService::log(array("Cannot add bulk item. Error Message: " . (string) $response->ErrorMessage . ". Error Code: " . (string) $response->ErrorCode . ".")); + } + sleep(2); + } + + $result["batch"] = $batch; + $result["totalBatch"] = $totalBatch; + $result["total"] = $total; + $result["updateCount"] = $updateCount; + return $result; + } catch (Error $error) { + HesabixLogService::writeLogStr("Error in export products: " . $error->getMessage()); + } + } + + public function importProducts($batch, $totalBatch, $total, $updateCount) + { + HesabixLogService::writeLogStr("Import Products"); + try { + $wpFaService = new HesabixWpFaService(); + $extraSettingRPP = get_option("hesabix_set_rpp_for_import_products"); + + $rpp = 100; + if ($extraSettingRPP) { + if ($extraSettingRPP != '-1' && $extraSettingRPP != '0') { + $rpp = $extraSettingRPP; + } + } + + $result = array(); + $result["error"] = false; + global $wpdb; + $hesabix = new Hesabix_Api(); + $filters = array(array("Property" => "khadamat", "Operator" => "=", "Value" => 0)); + + if ($batch == 1) { + $total = 0; + $response = $hesabix->itemGetItems(array('Take' => 1, 'Filters' => $filters)); + if ($response->Success) { + $total = $response->Result->FilteredCount; + $totalBatch = ceil($total / $rpp); + } else { + HesabixLogService::log(array("Error while trying to get products for import. Error Message: $response->ErrorMessage. Error Code: $response->ErrorCode.")); + $result["error"] = true; + return $result; + } + ; + } + + $id_product_array = array(); + $offset = ($batch - 1) * $rpp; + + $response = $hesabix->itemGetItems(array('Skip' => $offset, 'Take' => $rpp, 'SortBy' => 'Id', 'Filters' => $filters)); + if ($response->Success) { + $items = $response->Result->List; + $from = $response->Result->From; + $to = $response->Result->To; + + foreach ($items as $item) { + $wpFa = $wpFaService->getWpFaByHesabixId('product', $item->code); + if ($wpFa) + continue; + + $clearedName = preg_replace("/\s+|\/|\\\|\(|\)/", '-', trim($item->Name)); + $clearedName = preg_replace("/\-+/", '-', $clearedName); + $clearedName = trim($clearedName, '-'); + $clearedName = preg_replace( + ["/۰/", "/۱/", "/۲/", "/۳/", "/۴/", "/۵/", "/۶/", "/۷/", "/۸/", "/۹/"], + ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], + $clearedName + ); + + + $wpdb->insert($wpdb->posts, array( + 'post_author' => get_current_user_id(), + 'post_date' => current_time('mysql'), + 'post_date_gmt' => current_time('mysql', 1), + 'post_content' => '', + 'post_title' => $item->Name, + 'post_excerpt' => '', + 'post_status' => 'private', + 'comment_status' => 'open', + 'ping_status' => 'closed', + 'post_password' => '', + 'post_name' => $clearedName, + 'to_ping' => '', + 'pinged' => '', + 'post_modified' => current_time('mysql'), + 'post_modified_gmt' => current_time('mysql', 1), + 'post_content_filtered' => '', + 'post_parent' => 0, + 'guid' => home_url('/product/' . $clearedName . '/'), + 'menu_order' => 0, + 'post_type' => 'product', + 'post_mime_type' => '', + 'comment_count' => 0, + )); + + $postId = $wpdb->insert_id; + $id_product_array[] = $postId; + $price = self::getPriceInWooCommerceDefaultCurrency($item->SellPrice); + + + $wpdb->insert($wpdb->prefix . 'hesabix', array( + 'obj_type' => 'product', + 'id_hesabix' => (int) $item->code, + 'id_ps' => $postId, + 'id_ps_attribute' => 0, + )); + + update_post_meta($postId, '_manage_stock', 'yes'); + update_post_meta($postId, '_sku', $item->Barcode); + update_post_meta($postId, '_regular_price', $price); + update_post_meta($postId, '_price', $price); + update_post_meta($postId, '_stock', $item->stock); + + $new_stock_status = ($item->stock > 0) ? "instock" : "outofstock"; + wc_update_product_stock_status($postId, $new_stock_status); + $updateCount++; + } + + } else { + HesabixLogService::log(array("Error while trying to get products for import. Error Message: (string)$response->ErrorMessage. Error Code: (string)$response->ErrorCode.")); + $result["error"] = true; + return $result; + } + sleep(2); + + $result["batch"] = $batch; + $result["totalBatch"] = $totalBatch; + $result["total"] = $total; + $result["updateCount"] = $updateCount; + return $result; + } catch (Error $error) { + HesabixLogService::writeLogStr("Error in importing products" . $error->getMessage()); + } + } + + public function exportOpeningQuantity($batch, $totalBatch, $total) + { + try { + $wpFaService = new HesabixWpFaService(); + + $result = array(); + $result["error"] = false; + $extraSettingRPP = get_option("hesabix_set_rpp_for_export_opening_products"); + + $rpp = 500; + if ($extraSettingRPP) { + if ($extraSettingRPP != '-1' && $extraSettingRPP != '0') { + $rpp = $extraSettingRPP; + } + } + + global $wpdb; + + if ($batch == 1) { + $total = $wpdb->get_var( + $wpdb->prepare( + "SELECT COUNT(*) FROM {$wpdb->posts} + WHERE post_type = 'product' AND post_status IN ('publish', 'private')" + ) + ); + $totalBatch = ceil($total / $rpp); + } + + $offset = ($batch - 1) * $rpp; + + $products = $wpdb->get_results( + $wpdb->prepare( + "SELECT ID FROM {$wpdb->posts} + WHERE post_type = 'product' AND post_status IN ('publish', 'private') + ORDER BY ID ASC + LIMIT %d, %d", + $offset, + $rpp + ) + ); + + $items = array(); + + foreach ($products as $item) { + $variations = $this->getProductVariations($item->ID); + if (!$variations) { + $id_obj = $wpFaService->getWpFaId('product', $item->ID, 0); + + if ($id_obj != false) { + $product = new WC_Product($item->ID); + $quantity = $product->get_stock_quantity(); + $price = $product->get_regular_price() ? $product->get_regular_price() : $product->get_price(); + + $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "hesabix` WHERE `id` = " . $id_obj . " AND `obj_type` = 'product'"); + + if (is_object($product) && is_object($row) && $quantity > 0 && $price > 0) { + array_push($items, array( + 'Code' => $row->id_hesabix, + 'Quantity' => $quantity, + 'UnitPrice' => $this->getPriceInHesabixDefaultCurrency($price), + )); + } + } + } else { + foreach ($variations as $variation) { + $id_attribute = $variation->get_id(); + $id_obj = $wpFaService->getWpFaId('product', $item->ID, $id_attribute); + if ($id_obj != false) { + $quantity = $variation->get_stock_quantity(); + $price = $variation->get_regular_price() ? $variation->get_regular_price() : $variation->get_price(); + + $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "hesabix` WHERE `id` = " . $id_obj . " AND `obj_type` = 'product'"); + + if (is_object($variation) && is_object($row) && $quantity > 0 && $price > 0) { + array_push($items, array( + 'Code' => $row->id_hesabix, + 'Quantity' => $quantity, + 'UnitPrice' => $this->getPriceInHesabixDefaultCurrency($price), + )); + } + } + } + } + } + + if (!empty($items)) { + $hesabix = new Hesabix_Api(); + $response = $hesabix->itemUpdateOpeningQuantity($items); + if ($response->Success) { + + } else { + HesabixLogService::log(array("hesabix - Cannot set Opening quantity. Error Code: ' . $response->ErrorCode . '. Error Message: ' . $response->ErrorMessage")); + $result['error'] = true; + if ($response->ErrorCode = 199 && $response->ErrorMessage == 'No-Shareholders-Exist') { + $result['errorType'] = 'shareholderError'; + return $result; + } + return $result; + } + } + sleep(2); + $result["batch"] = $batch; + $result["totalBatch"] = $totalBatch; + $result["total"] = $total; + $result["done"] = $batch == $totalBatch; + return $result; + } catch (Error $error) { + HesabixLogService::writeLogStr("Error in Exporting Opening Quantity" . $error->getMessage()); + } + } + + public function exportCustomers($batch, $totalBatch, $total, $updateCount) + { + HesabixLogService::writeLogStr("Export Customers"); + $wpFaService = new HesabixWpFaService(); + + $result = array(); + $result["error"] = false; + $rpp = 500; + global $wpdb; + + if ($batch == 1) { + $total = $wpdb->get_var("SELECT COUNT(*) FROM `" . $wpdb->prefix . "users`"); + $totalBatch = ceil($total / $rpp); + } + + $offset = ($batch - 1) * $rpp; + $customers = $wpdb->get_results("SELECT ID FROM `" . $wpdb->prefix . "users` ORDER BY ID ASC LIMIT $offset,$rpp"); + + $items = array(); + foreach ($customers as $item) { + $id_customer = $item->ID; + $id_obj = $wpFaService->getWpFaId('customer', $id_customer); + if (!$id_obj) { + $hesabixCustomer = HesabixCustomerService::mapCustomer(null, $id_customer); + array_push($items, $hesabixCustomer); + $updateCount++; + } + } + + if (!empty($items)) { + $hesabix = new Hesabix_Api(); + $response = $hesabix->contactBatchSave($items); + if ($response->Success) { + foreach ($response->Result as $item) { + $json = json_decode($item->Tag); + + $wpdb->insert($wpdb->prefix . 'hesabix', array( + 'id_hesabix' => (int) $item->code, + 'obj_type' => 'customer', + 'id_ps' => (int) $json->id_customer, + )); + + HesabixLogService::log(array("Contact successfully added. Contact Code: " . $item->code . ". Customer ID: " . (int) $json->id_customer)); + } + } else { + HesabixLogService::log(array("Cannot add bulk contacts. Error Message: $response->ErrorMessage. Error Code: $response->ErrorCode.")); + } + } + + $result["batch"] = $batch; + $result["totalBatch"] = $totalBatch; + $result["total"] = $total; + $result["updateCount"] = $updateCount; + + return $result; + } + + + private function getOrdersCount($from_date, $end_date) + { + global $wpdb; + if (get_option('woocommerce_custom_orders_table_enabled') === 'yes') { + $table = $wpdb->prefix . 'wc_orders'; + $sql = $wpdb->prepare( + "SELECT COUNT(*) FROM `$table` + WHERE type = %s AND date_created_gmt BETWEEN %s AND %s", + 'shop_order', + $from_date, + $end_date + ); + } else { + $table = $wpdb->prefix . 'posts'; + $sql = $wpdb->prepare( + "SELECT COUNT(*) FROM `$table` + WHERE post_type = %s AND post_date BETWEEN %s AND %s", + 'shop_order', + $from_date, + $end_date + ); + } + return (int) $wpdb->get_var($sql); + } + + private function getOrdersByBatch($from_date, $end_date, $batch, $rpp) + { + global $wpdb; + $offset = ($batch - 1) * $rpp; + + if (get_option('woocommerce_custom_orders_table_enabled') === 'yes') { + $table = $wpdb->prefix . 'wc_orders'; + $sql = $wpdb->prepare( + "SELECT ID FROM `$table` + WHERE type = %s AND date_created_gmt BETWEEN %s AND %s + ORDER BY ID ASC LIMIT %d, %d", + 'shop_order', + $from_date, + $end_date, + $offset, + $rpp + ); + } else { + $table = $wpdb->prefix . 'posts'; + $sql = $wpdb->prepare( + "SELECT ID FROM `$table` + WHERE post_type = %s AND post_date BETWEEN %s AND %s + ORDER BY ID ASC LIMIT %d, %d", + 'shop_order', + $from_date, + $end_date, + $offset, + $rpp + ); + } + + return $wpdb->get_results($sql); + } + + public function syncOrders($from_date, $end_date, $batch, $totalBatch, $total, $updateCount) + { + HesabixLogService::writeLogStr("Sync Orders"); + + $result = [ + "error" => false, + "batch" => $batch, + "totalBatch" => $totalBatch, + "total" => $total, + "updateCount" => $updateCount, + ]; + + $rpp = 10; + global $wpdb; + + if (empty($from_date) || empty($end_date)) { + $result['error'] = 'inputDateError'; + return $result; + } + + if (($fy1 = $this->isDateInFiscalYear($from_date)) !== 1) { + $result['error'] = $fy1; + return $result; + } + + if (($fy2 = $this->isDateInFiscalYear($end_date)) !== 1) { + $result['error'] = $fy2; + return $result; + } + + if ($batch == 1) { + $total = $this->getOrdersCount($from_date, $end_date); + $totalBatch = ceil($total / $rpp); + HesabixLogService::writeLogStr("Total Orders: $total, Total Batches: $totalBatch"); + } + + $orders = $this->getOrdersByBatch($from_date, $end_date, $batch, $rpp); + if (empty($orders)) { + $result['error'] = __('no orders found', 'hesabix'); + return $result; + } + HesabixLogService::writeLogStr("Orders count: " . count($orders)); + + $wpFaService = new HesabixWpFaService(); + $invoice_statuses = get_option('hesabix_invoice_status', array()); + if (!is_array($invoice_statuses)) { + if (is_string($invoice_statuses) && !empty($invoice_statuses)) { + $invoice_statuses = array_map('trim', explode(',', $invoice_statuses)); + } else { + $invoice_statuses = array(); + } + } + + $return_invoice_statuses = get_option('hesabix_invoice_return_status', array()); + if (!is_array($return_invoice_statuses)) { + if (is_string($return_invoice_statuses) && !empty($return_invoice_statuses)) { + $return_invoice_statuses = array_map('trim', explode(',', $return_invoice_statuses)); + } else { + $return_invoice_statuses = array(); + } + } + + $payment_statuses = get_option('hesabix_payment_status', array()); + if (!is_array($payment_statuses)) { + if (is_string($payment_statuses) && !empty($payment_statuses)) { + $payment_statuses = array_map('trim', explode(',', $payment_statuses)); + } else { + $payment_statuses = array(); + } + } + + $statusesToSubmitInvoice = $invoice_statuses; + $statusesToSubmitReturnInvoice = $return_invoice_statuses; + $statusesToSubmitPayment = $payment_statuses; + + $id_orders = []; + + + foreach ($orders as $order) { + $order = wc_get_order($order->ID); + if (!$order) + continue; + + $id_order = $order->get_id(); + $current_status = $order->get_status(); + $id_obj = $wpFaService->getWpFaId('order', $id_order); + + if (!$id_obj) { + if (in_array($current_status, $statusesToSubmitInvoice)) { + if ($this->setOrder($id_order)) { + $id_orders[] = $id_order; + $updateCount++; + + if (in_array($current_status, $statusesToSubmitPayment)) { + $this->setOrderPayment($id_order); + } + + if (in_array($current_status, $statusesToSubmitReturnInvoice)) { + $invoice_code = $this->getInvoiceCodeByOrderId($id_order); + $this->setOrder($id_order, 2, $invoice_code); + } + } + } + } else { + if (in_array($current_status, $statusesToSubmitPayment)) { + $this->setOrderPayment($id_order); + } + } + } + + $result["total"] = $total; + $result["totalBatch"] = $totalBatch; + $result["updateCount"] = $updateCount; + + return $result; + } + + + public function syncProducts($batch, $totalBatch, $total) + { + try { + HesabixLogService::writeLogStr("Sync products price and quantity from hesabix to store: part $batch"); + $result = array(); + $result["error"] = false; + $extraSettingRPP = get_option("hesabix_set_rpp_for_sync_products_into_woocommerce"); + + $rpp = 200; + if ($extraSettingRPP) { + if ($extraSettingRPP != '-1' && $extraSettingRPP != '0') { + $rpp = $extraSettingRPP; + } + } + + $hesabix = new Hesabix_Api(); + $filters = array(array("Property" => "khadamat", "Operator" => "=", "Value" => 0)); + + if ($batch == 1) { + $response = $hesabix->itemGetItems(array('Take' => 1, 'Filters' => $filters)); + if ($response->Success) { + $total = $response->data->FilteredCount; + $totalBatch = ceil($total / $rpp); + } else { + HesabixLogService::log(array("Error while trying to get products for sync. Error Message: $response->ErrorMessage. Error Code: $response->ErrorCode.")); + $result["error"] = true; + return $result; + } + } + + $offset = ($batch - 1) * $rpp; + $response = $hesabix->itemGetItems(array('Skip' => $offset, 'Take' => $rpp, 'SortBy' => 'Id', 'Filters' => $filters)); + + // $warehouse = get_option('hesabix_item_update_quantity_based_on', "-1"); + + // if ($warehouse != "-1") { + // $products = $response->data->List; + // $codes = []; + // foreach ($products as $product) + // $codes[] = $product->code; + // $response = $hesabix->itemGetQuantity($warehouse, $codes); + // error_log('warehouse: ' . $warehouse); + // error_log('codes: ' . print_r($codes, true)); + // error_log('response: ' . print_r($response, true)); + // } + + if ($response->Success) { + // $products = $warehouse == "-1" ? $response->data->List : $response->data; + $products = $response->data->List; + foreach ($products as $product) { + self::setItemChanges($product); + } + } else { + HesabixLogService::log(array("Error while trying to get products for sync. Error Message: $response->ErrorMessage. Error Code: $response->ErrorCode.")); + $result["error"] = true; + return $result; + } + + $result["batch"] = $batch; + $result["totalBatch"] = $totalBatch; + $result["total"] = $total; + return $result; + } catch (Error $error) { + HesabixLogService::writeLogStr("Error in sync products: " . $error->getMessage()); + } + } + + public function syncProductsManually($data) + { + HesabixLogService::writeLogStr('Sync Products Manually'); + + $hesabix_item_codes = array(); + foreach ($data as $d) { + if ($d["hesabix_id"]) { + $hesabix_item_codes[] = str_pad($d["hesabix_id"], 6, "0", STR_PAD_LEFT); + } + } + + $hesabix = new Hesabix_Api(); + + $filters = array(array("Property" => "Code", "Operator" => "in", "Value" => $hesabix_item_codes)); + $response = $hesabix->itemGetItems(array('Take' => 100, 'Filters' => $filters)); + + if ($response->Success) { + $products = $response->Result->List; + $products_codes = array(); + foreach ($products as $product) + $products_codes[] = $product->code; + $diff = array_diff($hesabix_item_codes, $products_codes); + if (is_array($diff) && count($diff) > 0) { + return array("result" => false, "data" => $diff); + } + } + + $id_product_array = array(); + global $wpdb; + + foreach ($data as $d) { + $row = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "hesabix` WHERE `id_ps_attribute` = " . $d["id"] . " AND `obj_type` = 'product'"); + + if (!is_object($row)) { + $row = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "hesabix` WHERE `id_ps` = " . $d["id"] . " AND `obj_type` = 'product'"); + } + if (is_object($row)) { + if (!$d["hesabix_id"]) + $wpdb->delete($wpdb->prefix . 'hesabix', array('id' => $row->id)); + else + $wpdb->update($wpdb->prefix . 'hesabix', array('id_hesabix' => $d["hesabix_id"]), array('id' => $row->id)); + } else { + if (!$d["hesabix_id"]) + continue; + if ($d["parent_id"]) + $wpdb->insert($wpdb->prefix . 'hesabix', array('obj_type' => 'product', 'id_hesabix' => $d["hesabix_id"], 'id_ps' => $d["parent_id"], 'id_ps_attribute' => $d["id"])); + else + $wpdb->insert($wpdb->prefix . 'hesabix', array('obj_type' => 'product', 'id_hesabix' => $d["hesabix_id"], 'id_ps' => $d["id"], 'id_ps_attribute' => '0')); + } + + if ($d["hesabix_id"]) { + if ($d["parent_id"]) { + if (!in_array($d["parent_id"], $id_product_array)) + $id_product_array[] = $d["parent_id"]; + } else { + if (!in_array($d["id"], $id_product_array)) + $id_product_array[] = $d["id"]; + } + } + } + + $this->setItems($id_product_array); + return array("result" => true, "data" => null); + } + + public function updateProductsInHesabixBasedOnStore($batch, $totalBatch, $total) + { + HesabixLogService::writeLogStr("Update Products In Hesabix Based On Store"); + $result = array(); + $result["error"] = false; + $extraSettingRPP = get_option('hesabix_set_rpp_for_sync_products_into_hesabix'); + + $rpp = 500; + if ($extraSettingRPP) { + if ($extraSettingRPP != '-1' && $extraSettingRPP != '0') { + $rpp = $extraSettingRPP; + } + } + + global $wpdb; + + if ($batch == 1) { + $total = $wpdb->get_var( + $wpdb->prepare( + "SELECT COUNT(*) FROM {$wpdb->posts} + WHERE post_type = 'product' AND post_status IN ('publish', 'private')" + ) + ); + $totalBatch = ceil($total / $rpp); + } + + $offset = ($batch - 1) * $rpp; + + $products = $wpdb->get_results( + $wpdb->prepare( + "SELECT ID FROM {$wpdb->posts} + WHERE post_type = 'product' AND post_status IN ('publish', 'private') + ORDER BY ID ASC + LIMIT %d, %d", + $offset, + $rpp + ) + ); + + $products_id_array = array(); + foreach ($products as $product) + $products_id_array[] = $product->ID; + $this->setItems($products_id_array); + sleep(2); + + $result["batch"] = $batch; + $result["totalBatch"] = $totalBatch; + $result["total"] = $total; + return $result; + } + + + public function updateWooCommerceProductsBasedOnHesabix($batch, $totalBatch, $total) + { + HesabixLogService::writeLogStr("Update WooCommerce Products Based On Hesabix"); + $result = array(); + $result["error"] = false; + $extraSettingRPP = get_option('hesabix_set_rpp_for_sync_products_into_hesabix'); + + $rpp = 500; + if ($extraSettingRPP) { + if ($extraSettingRPP != '-1' && $extraSettingRPP != '0') { + $rpp = $extraSettingRPP; + } + } + + $api = new Hesabix_Api(); + $wpFaService = new HesabixWpFaService(); + $filters = array(array("Property" => "khadamat", "Operator" => "=", "Value" => 0)); + $items = $api->itemGetItems(array('Filters' => $filters)); + + foreach ($items->data->List as $item) { + + $this->saveHesabixProductToDatabase($item, $wpFaService); + + + $existingWpFa = $wpFaService->getWpFaByHesabixCode('product', $item->code); + + if ($existingWpFa && $existingWpFa->idWp > 0) { + + $this->updateWooCommerceProductsFromHesabix(array($existingWpFa->idWp)); + } else { + + $this->createWooCommerceProductFromHesabix($item, $wpFaService); + } + } + + $result["batch"] = $batch; + $result["totalBatch"] = $totalBatch; + $result["total"] = $total; + return $result; + + } + + + private function saveHesabixProductToDatabase($item, $wpFaService) + { + $hesabix_code = 0; + $hesabix_uid = 0; + $id_product = 0; + $id_attribute = 0; + + if (isset($item->code)) + $hesabix_code = (int) $item->code; + if (isset($item->id)) + $hesabix_uid = (int) $item->id; + + + $existingWpFa = $wpFaService->getWpFaByHesabixCode('product', $hesabix_code); + + if (!$existingWpFa) { + + $wpFa = WpFa::newWpFa(0, 'product', $hesabix_code, $id_product, $id_attribute, $hesabix_uid); + $wpFaService->save($wpFa); + HesabixLogService::writeLogStr("Hesabix product added to database. Code: $hesabix_code, UID: $hesabix_uid"); + } else { + + $existingWpFa->idHesabix = $hesabix_code; + $existingWpFa->uidHesabix = $hesabix_uid; + $wpFaService->update($existingWpFa); + HesabixLogService::writeLogStr("Hesabix product updated in database. Code: $hesabix_code, UID: $hesabix_uid"); + } + } + + + private function createWooCommerceProductFromHesabix($item, $wpFaService) + { + HesabixLogService::writeLogStr("Creating WooCommerce product from Hesabix - Code: " . $item->code . ", Name: " . $item->name); + + try { + + $product = new WC_Product_Simple(); + + + if (!empty($item->name)) { + $product->set_name($item->name); + } + + + + + if (isset($item->priceSell) && $item->priceSell > 0) { + $price = $this->getPriceInWooCommerceDefaultCurrency($item->priceSell); + $product->set_regular_price($price); + $product->set_price($price); + HesabixLogService::writeLogStr("Price converted from Hesabix: " . $item->priceSell . " to WooCommerce: " . $price); + } + + + if (isset($item->priceSellDiscount) && $item->priceSellDiscount > 0) { + $sale_price = $this->getPriceInWooCommerceDefaultCurrency($item->priceSellDiscount); + $product->set_sale_price($sale_price); + HesabixLogService::writeLogStr("Sale price converted from Hesabix: " . $item->priceSellDiscount . " to WooCommerce: " . $sale_price); + } + + + if (isset($item->priceBuy) && $item->priceBuy > 0) { + $purchase_price = $this->getPriceInWooCommerceDefaultCurrency($item->priceBuy); + update_post_meta($product->get_id(), '_purchase_price', $purchase_price); + HesabixLogService::writeLogStr("Purchase price converted from Hesabix: " . $item->priceBuy . " to WooCommerce: " . $purchase_price); + } + + + if (!empty($item->des)) { + $product->set_description($item->des); + } + + + if (!empty($item->barcodes)) { + $product->set_sku($item->barcodes); + } + + + $product->set_status('publish'); + + + $product_id = $product->save(); + + if ($product_id) { + + $existingWpFa = $wpFaService->getWpFaByHesabixCode('product', $item->code); + if ($existingWpFa) { + $existingWpFa->idWp = $product_id; + $wpFaService->update($existingWpFa); + HesabixLogService::writeLogStr("Updated database record with WooCommerce product ID: " . $product_id . " for Hesabix code: " . $item->code); + } + + + update_post_meta($product_id, 'hesabix_product_code', $item->code); + + HesabixLogService::writeLogStr("Successfully created WooCommerce product ID: " . $product_id . " from Hesabix code: " . $item->code); + } + } catch (Exception $e) { + HesabixLogService::writeLogStr("Error creating WooCommerce product from Hesabix code: " . $item->code . " - " . $e->getMessage()); + } + } + + + private function updateWooCommerceProductsFromHesabix($products_id_array) + { + HesabixLogService::writeLogStr("Update WooCommerce Products From Hesabix - Products Count: " . count($products_id_array)); + + $hesabixApi = new Hesabix_Api(); + + foreach ($products_id_array as $product_id) { + $product = wc_get_product($product_id); + if (!$product) { + continue; + } + + + $hesabix_code = get_post_meta($product_id, 'hesabix_product_code', true); + if (empty($hesabix_code)) { + continue; + } + + try { + + $hesabixProduct = $hesabixApi->itemGetItemsByCodes(array('values' => [$hesabix_code])); + + if ($hesabixProduct && isset($hesabixProduct->Success) && $hesabixProduct->Success) { + $item = $hesabixProduct->result[0]; + + + if (get_option('hesabix_do_not_update_titles_in_hesabix') !== 'yes') { + if (!empty($item->name)) { + $product->set_name($item->name); + } + } + + + if (get_option('hesabix_do_not_update_product_price_in_hesabix') !== 'yes') { + if (isset($item->priceSell) && $item->priceSell > 0) { + $price = $this->getPriceInWooCommerceDefaultCurrency($item->priceSell); + $product->set_regular_price($price); + $product->set_price($price); + } + } + + + if (get_option('hesabix_do_not_update_product_barcode_in_hesabix') !== 'yes') { + if (!empty($item->barcodes)) { + update_post_meta($product_id, '_sku', $item->barcodes); + } + } + + + if (get_option('hesabix_do_not_update_product_category_in_hesabix') !== 'yes') { + if (!empty($item->cat)) { + + + $category_name = $item->cat; + $term = term_exists($category_name, 'product_cat'); + if (!$term) { + $term = wp_insert_term($category_name, 'product_cat'); + } + if (!is_wp_error($term)) { + wp_set_object_terms($product_id, $term['term_id'], 'product_cat'); + } + } + } + + + if (get_option('hesabix_do_not_update_product_product_code_in_hesabix') !== 'yes') { + if (!empty($item->code)) { + update_post_meta($product_id, 'hesabix_product_code', $item->code); + } + } + + $product->save(); + + HesabixLogService::writeLogStr("Updated WooCommerce product ID: " . $product_id . " with Hesabix data"); + } + } catch (Exception $e) { + HesabixLogService::writeLogStr("Error updating WooCommerce product ID: " . $product_id . " - " . $e->getMessage()); + } + } + } + + public static function updateProductsInHesabixBasedOnStoreWithFilter($offset = 0, $rpp = 0) + { + HesabixLogService::writeLogStr("Update Products With Filter In Hesabix Based On Store"); + $result = array(); + $result["error"] = false; + + global $wpdb; + if ($offset != 0 && $rpp != 0) { + if (abs($rpp - $offset) <= 200) { + if ($rpp > $offset) { + + + + $products = $wpdb->get_results( + $wpdb->prepare( + "SELECT * FROM {$wpdb->posts} + WHERE ID BETWEEN %d AND %d + AND post_type = 'product' + AND post_status IN ('publish', 'private') + ORDER BY ID ASC", + $offset, + $rpp + ) + ); + + $products_id_array = array(); + foreach ($products as $product) + $products_id_array[] = $product->ID; + $response = (new Hesabix_Admin_Functions)->setItems($products_id_array); + if (!$response) + $result['error'] = true; + } else { + + + + $products = $wpdb->get_results( + $wpdb->prepare( + "SELECT * FROM {$wpdb->posts} + WHERE ID BETWEEN %d AND %d + AND post_type = 'product' + AND post_status IN ('publish', 'private') + ORDER BY ID ASC", + $rpp, + $offset + ) + ); + + $products_id_array = array(); + foreach ($products as $product) + $products_id_array[] = $product->ID; + $response = (new Hesabix_Admin_Functions)->setItems($products_id_array); + if (!$response) + $result['error'] = true; + } + } else { + $result['error'] = true; + echo ''; + } + } else { + echo ''; + } + + return $result; + } + + public function cleanLogFile() + { + HesabixLogService::clearLog(); + return true; + } + + public static function setItemChanges($item) + { + + if (!is_object($item)) + return false; + + if ($item->count || !$item->stock) + $item->stock = $item->count; + + $wpFaService = new HesabixWpFaService(); + global $wpdb; + + $wpFa = $wpFaService->getWpFaByHesabixId('product', $item->code); + if (!$wpFa) + return false; + + $id_product = $wpFa->idWp; + $id_attribute = $wpFa->idWpAttribute; + + if ($id_product == 0) { + HesabixLogService::log(array("Item with code: $item->code is not defined in Online store")); + return false; + } + + $found = $wpdb->get_var( + $wpdb->prepare( + "SELECT COUNT(*) FROM {$wpdb->posts} + WHERE ID = %d", + $id_product + ) + ); + + if (!$found) { + HesabixLogService::writeLogStr("product not found in woocommerce.code: $item->code, product id: $id_product, variation id: $id_attribute"); + return false; + } + + $product = wc_get_product($id_product); + $variation = $id_attribute != 0 ? wc_get_product($id_attribute) : null; + + $result = array(); + $result["newPrice"] = null; + $result["newQuantity"] = null; + + $p = $variation ? $variation : $product; + + if (get_option('hesabix_item_update_price') == 'yes') + $result = self::setItemNewPrice($p, $item, $id_attribute, $id_product, $result); + + if (get_option('hesabix_item_update_quantity') == 'yes') + $result = self::setItemNewQuantity($p, $item, $id_product, $id_attribute, $result); + + return $result; + } + + private static function setItemNewPrice($product, $item, $id_attribute, $id_product, array $result) + { + try { + $option_sale_price = get_option('hesabix_item_update_sale_price', 0); + $woocommerce_currency = get_woocommerce_currency(); + $hesabix_currency = get_option('hesabix_hesabix_default_currency'); + + $old_price = $product->get_regular_price() ? $product->get_regular_price() : $product->get_price(); + $old_price = Hesabix_Admin_Functions::getPriceInHesabixDefaultCurrency($old_price); + + $post_id = $id_attribute && $id_attribute > 0 ? $id_attribute : $id_product; + + $new_price = Hesabix_Admin_Functions::getPriceInWooCommerceDefaultCurrency($item->priceSell); + update_post_meta($post_id, '_regular_price', $new_price); + update_post_meta($post_id, '_price', $new_price); + + $sale_price = $product->get_sale_price(); + if ($sale_price && is_numeric($sale_price)) { + $sale_price = Hesabix_Admin_Functions::getPriceInHesabixDefaultCurrency($sale_price); + if (+$option_sale_price === 1) { + update_post_meta($post_id, '_sale_price', null); + } elseif (+$option_sale_price === 2) { + update_post_meta($post_id, '_sale_price', round(($sale_price * $new_price) / $old_price)); + update_post_meta($post_id, '_price', round(($sale_price * $new_price) / $old_price)); + } else { + if ($woocommerce_currency == 'IRT' && $hesabix_currency == 'IRR') + update_post_meta($post_id, '_price', ($sale_price / 10)); + elseif ($woocommerce_currency == 'IRR' && $hesabix_currency == 'IRT') + update_post_meta($post_id, '_price', ($sale_price * 10)); + elseif ($woocommerce_currency == 'IRR' && $hesabix_currency == 'IRR') + update_post_meta($post_id, '_price', $sale_price); + elseif ($woocommerce_currency == 'IRT' && $hesabix_currency == 'IRT') + update_post_meta($post_id, '_price', $sale_price); + } + } + + HesabixLogService::log(array("product ID $id_product-$id_attribute Price changed. Old Price: $old_price. New Price: $new_price")); + $result["newPrice"] = $new_price; + + return $result; + } catch (Error $error) { + HesabixLogService::writeLogStr("Error in Set Item New Price -> $error"); + } + } + + private static function setItemNewQuantity($product, $item, $id_product, $id_attribute, array $result) + { + try { + $old_quantity = $product->get_stock_quantity(); + $new_quantity = $item->stock; + if (!$new_quantity) + $new_quantity = 0; + + + $new_stock_status = ($new_quantity > 0) ? "instock" : "outofstock"; + + $post_id = ($id_attribute && $id_attribute > 0) ? $id_attribute : $id_product; + + $product = wc_get_product($post_id); + if ($product) { + $product->set_manage_stock(true); + $product->set_stock_quantity($new_quantity); + $product->set_stock_status($new_stock_status); + $product->save(); + HesabixLogService::log(array("product ID $id_product-$id_attribute quantity changed. Old quantity: $old_quantity. New quantity: $new_quantity")); + $result["newQuantity"] = $new_quantity; + } + + return $result; + } catch (Error $error) { + HesabixLogService::writeLogStr("Error in Set Item New Quantity -> $error"); + } + } + + public static function syncLastChangeID(): bool + { + try { + HesabixLogService::writeLogStr("Sync Last Change ID"); + $hesabixApi = new Hesabix_Api(); + $lastChange = $hesabixApi->getLastChangeId(); + + if ($lastChange && isset($lastChange->LastId)) { + update_option('hesabix_last_log_check_id', $lastChange->LastId - 1); + return true; + } + } catch (Exception $error) { + HesabixLogService::writeLogStr("Error in syncing last change id -> " . $error->getMessage()); + } + + return false; + } + + public static function SaveProductManuallyToHesabix($woocommerceCode, $attributeId, $hesabixCode): bool + { + + $isProductExistInHesabix = self::CheckExistenceOfTheProductInHesabix($hesabixCode); + if (!$isProductExistInHesabix) { + $isProductValidInWoocommerce = self::CheckValidityOfTheProductInWoocommerce($woocommerceCode, $attributeId, $hesabixCode); + if ($isProductValidInWoocommerce) { + + $product = wc_get_product($woocommerceCode); + if ($attributeId != 0) + $variation = wc_get_product($attributeId); + + if ($attributeId == 0) { + $hesabixItem = HesabixItemService::mapProduct($product, $woocommerceCode); + } else { + $hesabixItem = HesabixItemService::mapProductVariation($product, $variation, $woocommerceCode); + } + + + $api = new Hesabix_Api(); + $hesabixItem["Code"] = $hesabixCode; + $response = $api->itemSave($hesabixItem); + if ($response->Success) { + if ($attributeId == 0) + $productCode = $woocommerceCode; + else + $productCode = $attributeId; + HesabixLogService::log(array("Item successfully added to Hesabix. Hesabix code: " . $hesabixCode . " - Product code: " . $productCode)); + + $wpFaService = new HesabixWpFaService(); + $wpFa = $wpFaService->getWpFa('product', $woocommerceCode, $attributeId); + if (!$wpFa) { + $wpFa = new WpFa(); + $wpFa->idHesabix = $hesabixCode; + $wpFa->idWp = $woocommerceCode; + $wpFa->idWpAttribute = $attributeId; + $wpFa->objType = 'product'; + $wpFaService->save($wpFa); + HesabixLogService::log(array("Item successfully added. Hesabix code: " . (string) $hesabixCode . ". Product ID: $woocommerceCode - $attributeId")); + return true; + } + } else { + HesabixLogService::log(array("Error in saving product to hesabix. Hesabix given code: " . $hesabixCode)); + return false; + } + } + } + + return false; + } + + public static function CheckExistenceOfTheProductInHesabix($hesabixCode): bool + { + $api = new Hesabix_Api(); + $response = $api->itemGet($hesabixCode); + if ($response->Success) { + HesabixLogService::writeLogStr("کالا با کد(" . $hesabixCode . ") در حسابیکس موجود است."); + return true; + } else if ($response->ErrorCode == "112") { + return false; + } else { + HesabixLogService::writeLogStr("Error in getting the existence of the product"); + return true; + } + } + + public static function CheckValidityOfTheProductInWoocommerce($woocommerceCode, $attributeId, $hesabixCode): bool + { + + $wpFaService = new HesabixWpFaService(); + $code = $wpFaService->getProductCodeByWpId($woocommerceCode, $attributeId); + if ($code) { + HesabixLogService::writeLogStr("این کد حسابیکسی وارد شده به کالای دیگری متصل است." . $code . " - " . $woocommerceCode . " - " . $attributeId); + return false; + } + + + global $wpdb; + + if ($attributeId != 0) + $productId = $attributeId; + else + $productId = $woocommerceCode; + + $found = $wpdb->get_var( + $wpdb->prepare( + "SELECT COUNT(*) FROM {$wpdb->posts} + WHERE ID = %d", + $productId + ) + ); + + if ($found) { + + return true; + } else { + HesabixLogService::writeLogStr("product not found in woocommerce. Given product code: " . $woocommerceCode . "-" . $attributeId); + return false; + } + } + + function checkNationalCode($NationalCode): void + { + $identicalDigits = ['1111111111', '2222222222', '3333333333', '4444444444', '5555555555', '6666666666', '7777777777', '8888888888', '9999999999']; + + if (strlen($NationalCode) === 10) { + $summation = 0; + $j = 10; + for ($i = 0; $i < 9; $i++) { + $digit = substr($NationalCode, $i, 1); + $temp = $digit * $j; + $j -= 1; + $summation += $temp; + } + $controlDigit = substr($NationalCode, 9, 1); + $retrieve = $summation % 11; + + if (in_array($NationalCode, $identicalDigits) === false) { + if ($retrieve < 2) { + if ($controlDigit != $retrieve) { + wc_add_notice(__('please enter a valid national code', 'hesabix'), 'error'); + } + } else { + if ($controlDigit != (11 - $retrieve)) { + wc_add_notice(__('please enter a valid national code', 'hesabix'), 'error'); + } + } + } + } else { + wc_add_notice(__('please enter a valid national code', 'hesabix'), 'error'); + } + } + + public function checkNationalCodeWithPhone($nationalCode, $billingPhone): bool + { + $api = new Hesabix_Api(); + + $formattedPhoneNumber = $this->convertPersianPhoneDigitsToEnglish($billingPhone); + $formattedPhoneNumber = $this->formatPhoneNumber($formattedPhoneNumber); + + $response = $api->checkMobileAndNationalCode($nationalCode, $formattedPhoneNumber); + if ($response->Success) { + if ($response->Result->Status == 1) { + return $response->Result->Data->Matched; + } else { + return false; + } + } else { + HesabixLogService::writeLogStr('Error Occurred in Checking Mobile and NationalCode. ErrorCode: ' . $response->ErrorCode . " - ErrorMessage: " . $response->ErrorMessage); + return false; + } + } + + function checkWebsite($Website): void + { + if (filter_var($Website, FILTER_VALIDATE_URL)) { + + } else { + wc_add_notice(__('please enter a valid Website URL', 'hesabix'), 'error'); + } + } + + public static function enableDebugMode(): void + { + update_option('hesabix_debug_mode', 1); + } + + public static function disableDebugMode(): void + { + update_option('hesabix_debug_mode', 0); + } + + function formatPhoneNumber($phoneNumber) + { + $phoneNumber = preg_replace('/\D/', '', $phoneNumber); + + if (substr($phoneNumber, 0, 2) == '98') { + $phoneNumber = substr($phoneNumber, 2); + } + + if (substr($phoneNumber, 0, 1) == '9' && strlen($phoneNumber) == 10) { + $phoneNumber = '0' . $phoneNumber; + } + + if (strlen($phoneNumber) == 10 && substr($phoneNumber, 0, 1) == '9') { + $phoneNumber = '0' . $phoneNumber; + } + + return $phoneNumber; + } + + public function convertPersianPhoneDigitsToEnglish($inputString): string + { + $newNumbers = range(0, 9); + $persianDecimal = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'); + $arabicDecimal = array('٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'); + $arabic = array('٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'); + $persian = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'); + + $string = str_replace($persianDecimal, $newNumbers, $inputString); + $string = str_replace($arabicDecimal, $newNumbers, $string); + $string = str_replace($persian, $newNumbers, $string); + + return str_replace($arabic, $newNumbers, $string); + } + + public function convertPersianDigitsToEnglish($inputString) + { + $newNumbers = range(0, 9); + $persianDecimal = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'); + $arabicDecimal = array('٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'); + $arabic = array('٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'); + $persian = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'); + + $string = str_replace($persianDecimal, $newNumbers, $inputString); + $string = str_replace($arabicDecimal, $newNumbers, $string); + $string = str_replace($persian, $newNumbers, $string); + + return str_replace($arabic, $newNumbers, $string); + } + + public function formatTransactionFee($transactionFee, $amount) + { + if ($transactionFee && $transactionFee > 0) { + $func = new Hesabix_Admin_Functions(); + $transactionFee = $func->convertPersianDigitsToEnglish($transactionFee); + + if ($transactionFee < 100 && $transactionFee > 0) + $transactionFee /= 100; + $transactionFee *= $amount; + if ($transactionFee < 1) + $transactionFee = 0; + } + return $transactionFee; + } + + public function convertCityCodeToName($cityCode) + { + $citiesArray = [ + 1 => [ + 'title' => 'تهران', + 'cities' => [ + 1 => 'تهران', + 331 => 'اسلام شهر', + 1813 => 'ری', + 3341 => 'لواسان', + 3351 => 'شهریار', + 3371 => 'ورامین', + 3381 => 'پیشوا', + 3391 => 'پاکدشت', + 3751 => 'قدس', + 3761 => 'رباطکریم', + 3971 => 'دماوند', + 3981 => 'فیروزکوه', + 16531 => 'جاجرود (خسروآباد)', + 16551 => 'بومهن', + 16571 => 'شهرصنعتی خرمدشت', + 16581 => 'پردیس', + 18131 => 'باقر شهر', + 18141 => 'جعفرابادباقراف', + 18151 => 'مرقدامام ره', + 18161 => 'کهریزک', + 18171 => 'طورقوزاباد', + 18181 => 'قاسم ابادشوراباد', + 18191 => 'قمصر', + 18331 => 'حسن آباد', + 18341 => 'شمس اباد', + 18351 => 'ابراهیم اباد', + 18361 => 'چرمشهر', + 18371 => 'قلعه محمدعلی خان', + 18381 => 'فرودگاه امام خمینی', + 18391 => 'وهن اباد', + 18441 => 'قلعه نوخالصه', + 18451 => 'گل تپه کبیر', + 18461 => 'محمودابادپیرزاده', + 18471 => 'فرون اباد', + 18631 => 'خاورشهر', + 18641 => 'اسلام اباد', + 18651 => 'لپه زنگ', + 18661 => 'قیامدشت', + 18686 => 'قرچک', + 18791 => 'قوچ حصار', + 18986 => 'خلازیر', + 19338 => 'تجریش', + 31130 => 'نصیرشهر', + 31133 => 'شهرک صنعتی نصیرشهر', + 31136 => 'شهرک قلعه میر', + 31641 => 'صفادشت', + 31686 => 'اندیشه', + 31691 => 'ملارد', + 31694 => 'گرمدره', + 33131 => 'احمدابادمستوفی', + 33141 => 'فیروزبهرام', + 33151 => 'گلدسته', + 33171 => 'صالح آباد', + 33186 => 'شاطره', + 33191 => 'چهاردانگه', + 33361 => 'سعیدآباد', + 33451 => 'فشم', + 33461 => 'لواسان بزرگ', + 33541 => 'باغستان', + 33560 => 'صباشهر', + 33561 => 'شاهدشهر', + 33571 => 'فردوسیه', + 33581 => 'وحیدیه', + 33591 => 'لم اباد', + 33711 => 'قلعه سین', + 33741 => 'عسگرابادعباسی', + 33751 => 'دهماسین', + 33761 => 'باغخواص', + 33771 => 'ایجدان', + 33781 => 'ابباریک', + 33831 => 'جواد آباد', + 33841 => 'خاوه', + 33861 => 'جلیل اباد', + 33871 => 'کریم اباد', + 33881 => 'قلعه خواجه', + 33930 => 'شهرک عباس آباد', + 33931 => 'داوداباد', + 33941 => 'شریف آباد', + 33971 => 'پارچین', + 33981 => 'حصارامیر', + 33991 => 'خاتون اباد', + 37551 => 'نصیرآباد', + 37571 => 'گلستان', + 37581 => 'کلمه', + 37611 => 'پرند', + 37614 => 'شهر صنعتی پرند', + 37631 => 'سلطان اباد', + 37650 => 'حصارک پایین', + 37651 => 'نسیم شهر', + 37652 => 'حصارک بالا', + 37653 => 'سبزدشت', + 37656 => 'احمدآبادجانسپار', + 37661 => 'اسماعیل آباد', + 39720 => 'جابان', + 39731 => 'رودهن', + 39741 => 'آبعلی', + 39751 => 'کیلان', + 39761 => 'آبسرد', + 39771 => 'سربندان', + 39780 => 'مهرآباد', + 39781 => 'مشا', + 39791 => 'مرا', + 39811 => 'هرانده', + 39831 => 'درده', + 39841 => 'حصاربن', + 39851 => 'ارجمند', + 39861 => 'امیریه', + ], + ], + 2 => [ + 'title' => 'گيلان', + 'cities' => [ + 41 => 'رشت', + 431 => 'بندرانزلی', + 441 => 'لاهیجان', + 4331 => 'ابکنار', + 4341 => 'خمام', + 4351 => 'فومن', + 4361 => 'صومعه سرا', + 4371 => 'هشتپر', + 4381 => 'ماسال', + 4391 => 'آستارا', + 4431 => 'سیاهکل', + 4441 => 'آستانه اشرفیه', + 4451 => 'منجیل', + 4461 => 'رودبار', + 4471 => 'لنگرود', + 4481 => 'رودسر', + 4491 => 'کلاچای', + 43331 => 'کپورچال', + 43341 => 'جیرهنده', + 43351 => 'لیچارکی حسن رود', + 43361 => 'سنگر', + 43381 => 'سراوان', + 43391 => 'خشکبیجار', + 43431 => 'لشت نشاء', + 43451 => 'خواچکین', + 43461 => 'کوچصفهان', + 43471 => 'بلسبنه', + 43481 => 'چاپارخانه', + 43491 => 'جیرکویه', + 43513 => 'ماکلوان', + 43531 => 'لولمان', + 43541 => 'شفت', + 43551 => 'ملاسرا', + 43561 => 'چوبر', + 43571 => 'ماسوله', + 43581 => 'گشت', + 43591 => 'احمد سر گوراب', + 43631 => 'مرجقل', + 43641 => 'گوراب زرمیخ', + 43651 => 'طاهرگوراب', + 43661 => 'ضیابر', + 43671 => 'مرکیه', + 43681 => 'هنده خاله', + 43691 => 'نوخاله اکبری', + 43741 => 'شیله وشت', + 43751 => 'جوکندان بزرگ', + 43761 => 'لیسار', + 43771 => 'بازارخطبه سرا', + 43780 => 'چوبر', + 43781 => 'حویق', + 43791 => 'پلاسی', + 43811 => 'بازار جمعه', + 43841 => 'رضوانشهر', + 43861 => 'پره سر', + 43871 => 'پلنگ پاره', + 43891 => 'اسالم', + 43931 => 'شیخ محله', + 43941 => 'ویرمونی', + 43951 => 'سیبلی', + 43961 => 'لوندویل', + 43971 => 'مشند', + 43981 => 'کوته کومه', + 43991 => 'حیران', + 44141 => 'رودبنه', + 44331 => 'پایین محله پاشاکی', + 44341 => 'گرماور', + 44351 => 'لیش', + 44361 => 'بارکوسرا', + 44371 => 'شیرین نسا', + 44381 => 'خرارود', + 44391 => 'دیلمان', + 44431 => 'لسکوکلایه', + 44441 => 'کیسم', + 44451 => 'شیرکوه چهارده', + 44461 => 'دهشال', + 44471 => 'کیاشهر', + 44481 => 'دستک', + 44491 => 'پرگاپشت مهدی خانی', + 44531 => 'لوشان', + 44541 => 'بیورزین', + 44551 => 'جیرنده', + 44561 => 'بره سر', + 44581 => 'ویشان', + 44591 => 'کلیشم', + 44631 => 'علی اباد', + 44641 => 'رستم آباد', + 44651 => 'توتکابن', + 44661 => 'کلشتر', + 44681 => 'اسکولک', + 44691 => 'کوکنه', + 44731 => 'سلوش', + 44741 => 'چاف وچمخاله', + 44751 => 'شلمان', + 44761 => 'کومله', + 44771 => 'دیوشل', + 44781 => 'پروش پایین', + 44791 => 'اطاقور', + 44841 => 'حسن سرا', + 44851 => 'طول لات', + 44861 => 'رانکوه', + 44871 => 'چابکسر', + 44881 => 'جنگ سرا', + 44891 => 'واجارگاه', + 44931 => 'رحیم آباد', + 44941 => 'بلترک', + 44951 => 'املش', + 44971 => 'کجید', + 44981 => 'گرمابدشت', + 44991 => 'شوییل', + 44992 => 'پونل', + ], + ], + 3 => [ + 'title' => 'آذربايجان شرقي', + 'cities' => [ + 51 => 'تبریز', + 531 => 'میانه', + 541 => 'مرند', + 551 => 'مراغه', + 5331 => 'شهرجدیدسهند', + 5351 => 'اسکو', + 5361 => 'سردرود', + 5371 => 'آذر شهر', + 5381 => 'شبستر', + 5391 => 'هریس', + 5431 => 'هادیشهر', + 5441 => 'جلفا', + 5451 => 'اهر', + 5461 => 'کلیبر', + 5471 => 'سراب', + 5491 => 'بستان آباد', + 5541 => 'عجب شیر', + 5551 => 'بناب', + 5561 => 'ملکان', + 5571 => 'هشترود', + 5581 => 'قره آغاج', + 5586 => 'اغچه ریش', + 53331 => 'ترک', + 53351 => 'ترکمانچای', + 53361 => 'خاتون اباد', + 53371 => 'شیخدراباد', + 53381 => 'قره بلاغ', + 53391 => 'آقکند', + 53431 => 'اچاچی', + 53441 => 'گوندوغدی', + 53451 => 'پورسخلو', + 53461 => 'کنگاور', + 53481 => 'قویوجاق', + 53491 => 'ارموداق', + 53531 => 'کهنمو', + 53541 => 'اربط', + 53551 => 'خسرو شهر', + 53561 => 'لاهیجان', + 53571 => 'خاص اباد (خاصبان)', + 53581 => 'ایلخچی', + 53591 => 'سرای (سرای ده)', + 53631 => 'کجوار', + 53641 => 'خلجان', + 53651 => '(ینگی اسپران (سفیدان جد', + 53661 => 'باسمنج', + 53671 => '(شادبادمشایخ (پینه شلوا', + 53681 => 'کندرود', + 53691 => 'مایان سفلی', + 53731 => 'تیمورلو', + 53740 => 'خراجو', + 53741 => 'قدمگاه (بادام یار)', + 53751 => 'ممقان', + 53761 => 'گوگان', + 53771 => 'شیرامین', + 53791 => 'هفت چشمه', + 53811 => 'وایقان', + 53831 => 'امند', + 53840 => 'کوزه کنان', + 53841 => 'خامنه', + 53851 => 'سیس', + 53861 => 'صوفیان', + 53871 => 'شند آباد', + 53881 => 'تسوج', + 53891 => 'شرفخانه', + 53941 => 'مینق', + 53950 => 'کلوانق', + 53951 => 'بخشایش', + 53961 => 'سرند', + 53971 => 'زرنق', + 53981 => 'بیلوردی', + 53991 => 'خواجه', + 54331 => 'گلین قیه', + 54341 => 'هرزندجدید (چای هرزند)', + 54351 => 'بناب جدید', + 54361 => 'زنوز', + 54371 => 'دولت اباد', + 54381 => 'یکان کهریز', + 54391 => 'یامچی', + 54431 => 'شجاع', + 54441 => 'داران', + 54451 => 'سیه رود', + 54461 => 'نوجه مهر', + 54471 => 'کشکسرای', + 54481 => 'خاروانا', + 54491 => 'هوراند', + 54531 => 'چول قشلاقی', + 54541 => 'ورگهان', + 54551 => 'افیل', + 54561 => 'اذغان (ازغان)', + 54571 => 'سیه کلان', + 54581 => 'ورزقان', + 54591 => 'اق براز', + 54631 => 'مولان', + 54641 => 'خمارلو', + 54651 => 'عاشقلو', + 54661 => 'اسکلو (اسگلو)', + 54671 => 'آبش احمد', + 54681 => 'یوزبند', + 54682 => 'شهرک صنعتی کاغذکنان', + 54685 => 'کندوان', + 54686 => 'تیل', + 54691 => 'لاریجان', + 54731 => 'اسبفروشان', + 54741 => 'ابرغان', + 54750 => 'دوزدوزان', + 54751 => 'شربیان', + 54761 => 'مهربان', + 54771 => 'رازلیق', + 54781 => 'اغمیون', + 54791 => 'اردها', + 54931 => 'قره چای حاج علی', + 54941 => 'قره بابا', + 54951 => 'سعیداباد', + 54961 => 'الانق', + 54971 => 'کردکندی', + 54981 => 'تیکمه داش', + 54991 => 'قره چمن', + 55330 => 'ورجوی', + 55341 => 'گل تپه', + 55351 => 'خداجو', + 55361 => 'داش اتان', + 55371 => 'داش بلاغ بازار', + 55381 => 'صومعه', + 55391 => 'علویان', + 55431 => 'شیراز', + 55441 => 'خضرلو', + 55451 => 'ینگجه', + 55461 => 'مهماندار', + 55471 => 'خانیان', + 55481 => 'دانالو', + 55491 => 'رحمانلو', + 55531 => 'زاوشت', + 55541 => 'القو', + 55551 => 'روشت بزرگ', + 55561 => 'خوشه مهر (خواجه امیر)', + 55571 => 'زوارق', + 55581 => '(خانه برق قدیم (شورخانه ب', + 55631 => 'لکلر', + 55641 => 'بایقوت', + 55651 => 'اروق', + 55661 => 'اق منار', + 55671 => 'لیلان', + 55681 => 'طوراغای (طوراغایی)', + 55731 => 'اوشندل', + 55741 => 'علی ابادعلیا', + 55751 => 'ذوالبین', + 55761 => 'نظر کهریزی', + 55771 => 'اتش بیگ', + 55781 => 'سلوک', + 55791 => 'نصیرابادسفلی', + 55831 => 'ارسگنای سفلی', + 55841 => '(سلطان اباد (س انمکزار', + 55851 => 'قلعه حسین اباد', + 55871 => 'ذاکرکندی', + 55881 => 'قوچ احمد', + 55891 => 'اغ زیارت', + ], + ], + 4 => [ + 'title' => 'خوزستان', + 'cities' => [ + 61 => 'اهواز', + 631 => 'آبادان', + 641 => 'خرمشهر', + 6331 => 'اروندکنار', + 6341 => 'ملاثانی', + 6351 => 'بندرماهشهر', + 6361 => 'بهبهان', + 6371 => 'آغاجاری', + 6381 => 'رامهرمز', + 6391 => 'ایذه', + 6431 => 'شادگان', + 6441 => 'سوسنگرد', + 6451 => 'شوشتر', + 6461 => 'دزفول', + 6471 => 'شوش', + 6481 => 'اندیمشک', + 6491 => 'مسجدسلیمان', + 61431 => 'الهائی', + 61481 => 'شیبان', + 61491 => 'ویس', + 63331 => 'فیاضی', + 63341 => 'تنگ یک', + 63351 => 'چوئبده', + 63361 => 'نهرسلیم', + 63381 => 'نهرابطر', + 63431 => 'عین دو', + 63441 => 'حمیدیه', + 63451 => 'ام الطمیر (سیدیوسف)', + 63461 => 'کوت عبدالله', + 63471 => 'قلعه چنعان', + 63481 => 'کریت برومی', + 63491 => 'غیزانیه بزرگ', + 63531 => 'چم کلگه', + 63541 => 'چمران', + 63561 => 'بندرامام خمینی', + 63571 => 'صالح شهر', + 63581 => 'اسیاب', + 63591 => 'هندیجان', + 63640 => 'تشان', + 63641 => 'گروه پدافندهوایی بهبها', + 63651 => 'شاه غالب ده ابراهیم', + 63661 => 'کردستان بزرگ', + 63671 => 'منصوریه', + 63681 => 'سردشت', + 63731 => 'امیدیه', + 63751 => 'میانکوه', + 63771 => 'زهره', + 63831 => 'رودزرد', + 63851 => 'نفت سفید', + 63861 => 'مشراگه', + 63871 => 'رامشیر', + 63881 => 'جایزان', + 63891 => 'دره تونم نمی', + 63931 => 'میداود', + 63941 => 'صیدون', + 63951 => 'باغ ملک', + 63961 => 'قلعه تل', + 63971 => 'چنارستان', + 63981 => 'پشت پیان', + 63991 => 'دهدز', + 64330 => 'خنافره', + 64331 => 'عبودی', + 64341 => 'دارخوین', + 64351 => 'درویشی', + 64361 => 'بوزی سیف', + 64371 => 'مینوشهر', + 64381 => 'حفاری شرقی', + 64431 => 'بروایه یوسف', + 64440 => 'کوت سیدنعیم', + 64441 => 'ابوحمیظه', + 64451 => 'هویزه', + 64461 => 'یزدنو', + 64471 => 'رفیع', + 64481 => 'بستان', + 64491 => 'سیدعباس', + 64510 => 'سرداران', + 64511 => 'شرافت', + 64531 => 'گوریه', + 64541 => 'جنت مکان', + 64551 => 'گتوند', + 64560 => 'ترکالکی', + 64561 => 'سماله', + 64571 => 'شهرک نورمحمدی', + 64581 => 'گاومیش اباد', + 64591 => 'عرب حسن', + 64631 => 'صفی آباد', + 64640 => 'چغامیش', + 64641 => 'حمزه', + 64650 => 'شمس آباد', + 64651 => 'امام', + 64652 => 'سیاه منصور', + 64661 => 'میانرود', + 64681 => 'چلون', + 64691 => 'سالند', + 64730 => 'حر', + 64731 => 'شاوور', + 64741 => 'مزرعه یک', + 64751 => 'خسرجی راضی حمد', + 64761 => 'الوان', + 64771 => 'علمه تیمورابوذرغفاری', + 64781 => 'شهرک بهرام', + 64791 => 'فتح المبین', + 64830 => 'آزادی', + 64831 => 'شهرک انصار', + 64841 => 'خواجوی', + 64850 => 'بیدروبه', + 64851 => 'حسینیه', + 64861 => 'کلگه دره دو', + 64871 => 'تله زنگ پایین', + 64881 => 'چم گلک', + 64931 => 'روستای عنبر', + 64941 => 'لالی', + 64951 => 'دره بوری', + 64961 => 'هفتگل', + 64971 => 'کوشکک', + 64980 => 'آبژدان', + 64981 => 'قلعه خواجه', + 64991 => 'گلگیر', + ], + ], + 5 => [ + 'title' => 'فارس', + 'cities' => [ + 71 => 'شیراز', + 731 => 'کازرون', + 741 => 'جهرم', + 7331 => 'قائمیه', + 7341 => 'زرقان', + 7351 => 'نور آباد', + 7361 => 'اردکان', + 7371 => 'مرودشت', + 7381 => 'اقلید', + 7391 => 'آباده', + 7431 => 'لار', + 7441 => 'گراش', + 7451 => 'استهبان', + 7461 => 'فسا', + 7471 => 'فیروز آباد', + 7481 => 'داراب', + 7491 => 'نی ریز', + 71431 => 'بندامیر', + 71451 => 'خیرابادتوللی', + 71461 => 'داریان', + 71491 => 'کم جان', + 71551 => 'شوریجه', + 71561 => 'مهارلو', + 71571 => 'کوهنجان', + 71581 => 'سلطان آباد', + 71591 => 'تفیهان', + 71641 => 'طسوج', + 71651 => 'اکبراباد', + 71661 => 'مظفری', + 71671 => 'کوشک بیدک', + 71681 => 'فتح اباد', + 71691 => 'ده شیب', + 71741 => 'خانه زنیان', + 71781 => 'پاسگاه چنارراهدار', + 71881 => 'موردراز', + 71991 => 'شهرجدیدصدرا', + 73131 => 'کلاتون', + 73141 => 'کلانی', + 73151 => 'کمارج مرکزی', + 73161 => 'مهبودی علیا', + 73171 => 'وراوی', + 73311 => 'حکیم باشی نصف میان (بالا)', + 73331 => 'کنار تخته', + 73341 => 'خشت', + 73351 => 'انارستان', + 73361 => 'نودان', + 73371 => 'مهرنجان', + 73381 => 'جره', + 73391 => 'بالاده', + 73411 => 'لپوئی', + 73431 => 'کامفیروز', + 73441 => 'خرامه', + 73451 => 'سروستان', + 73461 => 'کوار', + 73471 => 'رامجرد', + 73491 => 'گویم', + 73511 => 'خومه زار', + 73531 => 'بابامنیر', + 73541 => 'اهنگری', + 73551 => 'پرین', + 73560 => 'کوپن', + 73561 => 'حسین ابادرستم', + 73571 => 'مصیری', + 73591 => 'میشان سفلی', + 73611 => 'بهرغان', + 73631 => 'بیضا', + 73641 => 'هماشهر', + 73651 => 'کمهر', + 73661 => 'راشک علیا', + 73671 => 'هرایجان', + 73681 => 'بانش', + 73711 => 'کوشک', + 73731 => 'خانیمن', + 73741 => 'سعادت شهر', + 73751 => 'قادرآباد', + 73761 => 'ارسنجان', + 73771 => 'سیدان', + 73791 => 'کوشکک', + 73810 => 'مزایجان', + 73811 => 'خنجشت', + 73831 => 'امامزاده اسماعیل', + 73840 => 'مادرسلیمان', + 73841 => 'حسن آباد', + 73851 => 'اسپاس', + 73861 => 'سده', + 73881 => 'دژکرد', + 73891 => 'شهرمیان', + 73911 => 'بهمن', + 73931 => 'صغاد', + 73940 => 'حسامی', + 73941 => 'بوانات', + 73942 => 'کره ای', + 73951 => 'صفاشهر', + 73981 => 'سورمق', + 73991 => 'ایزدخواست', + 74110 => 'دوزه', + 74161 => 'بندبست', + 74171 => 'باب انار', + 74311 => 'فیشور', + 74331 => 'اوز', + 74341 => 'لامرد', + 74351 => 'جویم', + 74361 => 'بنارویه', + 74370 => 'خور', + 74371 => 'لطیفی', + 74380 => 'عمادده', + 74381 => 'بیرم', + 74390 => 'اهل', + 74391 => 'اشکنان', + 74410 => 'اسیر', + 74411 => 'کهنه', + 74414 => 'خوزی', + 74431 => 'خنج', + 74441 => 'علامرودشت', + 74450 => 'گله دار', + 74451 => 'مهر', + 74461 => 'رونیز', + 74471 => 'بنوان', + 74481 => 'ایج', + 74491 => 'درب قلعه', + 74541 => 'خاوران', + 74551 => 'قطب آباد', + 74561 => 'دنیان', + 74571 => 'سروو', + 74581 => 'مانیان', + 74591 => 'به جان', + 74611 => 'کوشک قاضی', + 74641 => 'نوبندگان', + 74650 => 'قره بلاغ', + 74651 => 'ششده', + 74661 => 'قاسم ابادسفلی', + 74671 => 'زاهدشهر', + 74681 => 'میانده', + 74691 => 'صحرارود', + 74711 => 'بایگان', + 74714 => 'امام شهر', + 74731 => 'مبارک آباد', + 74741 => 'میمند', + 74751 => 'افزر', + 74760 => 'قیر', + 74761 => 'کارزین', + 74771 => 'فراشبند', + 74780 => 'نوجین', + 74781 => 'دهرم', + 74791 => 'جوکان', + 74811 => 'مادوان', + 74814 => 'دبیران', + 74831 => 'ماه سالاری', + 74841 => 'رستاق', + 74850 => 'شهرپیر', + 74861 => 'حاجی آباد', + 74871 => 'فدامی', + 74880 => 'دوبرجی', + 74881 => 'چمن مروارید', + 74891 => 'جنت شهر', + 74911 => 'لای حنا', + 74931 => 'آباده طشک', + 74941 => 'قطاربنه', + 74971 => 'مشکان', + 74981 => 'قطرویه', + 74991 => 'هرگان', + ], + ], + 6 => [ + 'title' => 'اصفهان', + 'cities' => [ + 81 => 'اصفهان', + 831 => 'شاهین شهر', + 841 => 'خمینی شهر', + 851 => 'نجف آباد', + 861 => 'شهرضا', + 871 => 'کاشان', + 8161 => 'منطقه صنعتی محموداباد', + 8331 => 'مورچه خورت', + 8341 => 'دولت آباد', + 8351 => 'میمه', + 8361 => 'خور', + 8371 => 'کوهپایه', + 8381 => 'اردستان', + 8391 => 'نائین', + 8431 => 'درچه پیاز', + 8441 => 'زواره', + 8451 => 'فلاورجان', + 8461 => 'قهدریجان', + 8471 => 'زرین شهر', + 8481 => 'مبارکه', + 8491 => 'فولادشهر', + 8531 => 'تیران', + 8541 => 'دهق', + 8551 => 'علویجه', + 8561 => 'داران', + 8571 => 'چادگان', + 8591 => 'فریدونشهر', + 8641 => 'دهاقان', + 8651 => 'اسفرجان', + 8661 => 'سمیرم', + 8671 => 'حنا', + 8681 => 'مهرگرد', + 8731 => 'جوشقان استرک', + 8741 => 'آران و بیدگل', + 8751 => 'قمصر', + 8761 => 'نطنز', + 8771 => 'گلپایگان', + 8781 => 'گوگد', + 8791 => 'خوانسار', + 81351 => 'تودشک', + 81391 => 'سگزی', + 81431 => 'بهارستان', + 81561 => 'خوراسگان', + 81594 => 'گورت', + 81671 => 'دستجا', + 81681 => 'زیار', + 81751 => 'نصرآباد', + 81789 => 'ابریشم', + 81799 => 'اصفهان (سپاهان شهر)', + 83341 => 'پادگان اموزشی امام ص', + 83351 => 'پالایشگاه اصفهان', + 83361 => 'کلهرود', + 83371 => 'گرگاب', + 83431 => 'دستگرد', + 83441 => 'گز برخوار', + 83451 => 'خورزوق', + 83461 => 'حبیب آباد', + 83531 => 'موته', + 83541 => 'وزوان', + 83551 => 'لای بید', + 83561 => 'رباطاقاکمال', + 83581 => 'خسرواباد', + 83591 => 'کمشچه', + 83631 => 'جندق', + 83641 => 'فرخی', + 83651 => 'مزیک', + 83661 => 'مهرجان', + 83671 => 'بیاضه', + 83681 => 'چوپانان', + 83691 => 'بلان', + 83731 => 'محمدآباد', + 83741 => 'هرند', + 83751 => 'ورزنه', + 83761 => 'قهجاورستان', + 83771 => 'نیک آباد', + 83781 => 'اژیه', + 83791 => 'حسن اباد', + 83831 => 'کچومثقال', + 83841 => 'ظفرقند', + 83851 => 'نهوج', + 83861 => 'نیسیان', + 83871 => 'ومکان', + 83881 => 'همسار', + 83891 => 'فسخود', + 83931 => 'فوداز', + 83941 => 'اشکستان', + 83951 => 'کجان', + 83961 => 'نیستانک', + 83971 => 'انارک', + 83991 => 'بافران', + 84331 => 'تیرانچی', + 84341 => 'کوشک', + 84371 => 'قلعه امیریه', + 84431 => 'مهاباد', + 84441 => 'درقه', + 84451 => 'شهراب', + 84461 => 'تورزن', + 84471 => 'کریم اباد', + 84481 => 'تلک اباد', + 84491 => 'موغار', + 84531 => 'خوانسارک', + 84541 => 'پیربکران', + 84561 => 'کلیشادوسودرجان', + 84581 => 'کرسگان', + 84591 => 'بهاران شهر', + 84631 => 'سهروفیروزان', + 84651 => 'ایمانشهر', + 84671 => 'زازران', + 84681 => 'شرودان', + 84691 => 'جوجیل', + 84731 => 'ورنامخواست', + 84741 => 'سده لنجان', + 84751 => 'چرمهین', + 84761 => 'باغ بهادران', + 84771 => 'نوگوران', + 84781 => 'چمگردان', + 84791 => 'کرچگان', + 84831 => 'دیزیچه', + 84841 => 'زیباشهر', + 84851 => 'باغ ملک', + 84861 => 'دهسرخ', + 84871 => 'پلی اکریل', + 84881 => 'فولادمبارکه', + 84891 => 'کرکوند', + 84931 => 'زاینده رود', + 84951 => 'چم نور', + 84961 => 'کچوییه', + 84971 => 'اشیان', + 84981 => 'طالخونچه', + 84991 => 'تاسیسات سدنکواباد', + 85331 => 'رضوانشهر', + 85341 => 'ورپشت', + 85351 => 'عسگران', + 85371 => 'عزیزاباد', + 85381 => 'میراباد', + 85391 => 'حاجی اباد', + 85441 => 'خیراباد', + 85451 => 'اشن', + 85471 => 'خونداب', + 85531 => 'حسین اباد', + 85631 => 'غرغن', + 85641 => 'دامنه', + 85651 => 'بوئین و میاندشت', + 85661 => 'زرنه', + 85671 => 'بلطاق', + 85681 => 'کرچ', + 85691 => 'قره بلطاق', + 85711 => 'افوس', + 85731 => 'سازمان عمران زاینده رود', + 85741 => 'مشهدکاوه', + 85751 => 'اسکندری', + 85761 => 'رزوه', + 85771 => 'نهرخلج', + 85781 => 'چاه غلامرضارحیمی', + 85791 => 'اورگان', + 85831 => 'گلدشت', + 85851 => 'جوزدان', + 85861 => 'کهریزسنگ', + 85931 => 'نهضت اباد', + 85941 => 'قلعه سرخ', + 85961 => 'اسلام ابادموگویی', + 85971 => 'مصیر', + 85991 => 'برف انبار', + 86331 => 'قمشلو', + 86341 => 'پوده', + 86351 => 'مهیار', + 86361 => 'پرزان', + 86371 => 'منوچهراباد', + 86391 => 'شهرک صنایع شیمیایی ر', + 86431 => 'همگین', + 86451 => 'گلشن', + 86461 => 'کهرویه', + 86471 => 'قصرچم', + 86531 => 'امین اباد', + 86541 => 'مقصودبیک', + 86551 => 'سولار', + 86561 => 'منظریه', + 86631 => 'گرموک', + 86651 => 'هست', + 86671 => 'ونک', + 86751 => 'کهنگان', + 86771 => 'کمه', + 86781 => 'مورک', + 86791 => 'چهارراه', + 86831 => 'ده نسا سفلی', + 86841 => 'اغداش', + 86851 => 'چشمه رحمان', + 86861 => 'ورق', + 86881 => 'سعادت اباد', + 86891 => 'فتح اباد', + 87181 => 'نیاسر', + 87331 => 'سن سن', + 87351 => 'ده زیره', + 87361 => 'رحق', + 87371 => 'اب شیرین', + 87381 => 'نشلج', + 87391 => 'مشکات', + 87431 => 'سفیدشهر', + 87441 => 'مزرعه صدر', + 87461 => 'نوش آباد', + 87481 => 'ابوزیدآباد', + 87491 => 'کاغذی', + 87541 => 'قهرود', + 87551 => 'جوشقان و کامو', + 87561 => 'برزک', + 87571 => 'اسحق اباد', + 87581 => 'وادقان', + 87591 => 'اذان', + 87631 => 'طرق رود', + 87641 => 'اریسمان', + 87651 => 'ابیانه', + 87661 => 'بادرود', + 87671 => 'خالدآ باد', + 87681 => 'اوره', + 87731 => 'ملازجان', + 87741 => 'سعیداباد', + 87751 => 'مرغ', + 87771 => 'قرغن', + 87781 => 'کوچری', + 87831 => 'کلوچان', + 87841 => 'گلشهر', + 87861 => 'زرنجان', + 87871 => 'وانشان', + 87881 => 'تیکن', + 87931 => 'سنگ سفید', + 87941 => 'رحمت اباد', + 87951 => 'خم پیچ', + 87961 => 'مهراباد', + 87971 => 'تیدجان', + 87981 => 'خشکرود', + 87991 => 'ویست', + ], + ], + 7 => [ + 'title' => 'خراسان رضوي', + 'cities' => [ + 91 => 'مشهد', + 931 => 'نیشابور', + 951 => 'تربت حیدریه', + 961 => 'سبزوار', + 9331 => 'فیروزه', + 9341 => 'درود', + 9351 => 'طرقبه', + 9361 => 'چناران', + 9371 => 'کلات', + 9381 => 'سرخس', + 9391 => 'فریمان', + 9471 => 'قوچان', + 9491 => 'درگز', + 9531 => 'فیض آباد', + 9541 => 'رشتخوار', + 9551 => 'کدکن', + 9561 => 'خواف', + 9571 => 'تربت جام', + 9581 => 'صالح آباد', + 9591 => 'تایباد', + 9631 => 'داورزن', + 9641 => 'جغتای', + 9651 => 'ششتمد', + 9671 => 'کاشمر', + 9681 => 'بردسکن', + 9691 => 'گناباد', + 91671 => 'رضویه', + 93161 => 'همت آباد', + 93331 => 'شوراب', + 93341 => 'گلبوی پایین', + 93351 => 'مبارکه', + 93361 => 'چکنه', + 93371 => 'برزنون', + 93381 => 'فدیشه', + 93391 => 'بار', + 93431 => 'میراباد', + 93441 => 'فرخک', + 93451 => 'خرو', + 93461 => 'قدمگاه', + 93471 => 'اسحق اباد', + 93481 => 'خوجان', + 93491 => 'عشق آباد', + 93541 => 'ملک آباد', + 93551 => 'کورده', + 93561 => 'شاندیز', + 93571 => 'طوس سفلی', + 93581 => 'قرقی سفلی (شهیدکاوه)', + 93591 => 'کنه بیست', + 93631 => 'رادکان', + 93641 => 'سیداباد', + 93651 => 'گلبهار', + 93661 => 'سلوگرد', + 93671 => 'ارداک', + 93681 => 'بقمج', + 93691 => 'گلمکان', + 93741 => 'میامی', + 93751 => 'چاهک', + 93761 => 'شهرزو', + 93771 => 'گوش', + 93781 => 'نریمانی سفلی', + 93791 => 'تقی اباد', + 93831 => 'کچولی', + 93841 => 'شیرتپه', + 93851 => 'پس کمر', + 93861 => 'مزدآوند', + 93871 => 'بزنگان', + 93881 => 'گنبدلی', + 93891 => 'کندک لی', + 93931 => 'کته شمشیرسفلی', + ], + ], + 8 => [ + 'title' => 'قزوين', + 'cities' => [ + 341 => 'قزوین', + 3431 => 'الوند', + 3441 => 'آبیک', + 3451 => 'بوئین زهرا', + 3461 => 'آوج', + 3481 => 'تاکستان', + 3491 => 'محمدیه', + 34131 => 'محمودآبادنمونه', + 34151 => 'بیدستان', + 34161 => 'شریفیه', + 34171 => 'اقبالیه', + 34313 => 'نصرت آباد', + 34331 => 'الولک', + 34341 => 'کاکوهستان', + 34351 => 'فلار', + 34381 => 'مینودشت', + 34391 => 'زوارک', + 34431 => 'صمغ اباد', + 34441 => 'ناصراباد', + 34461 => 'رشتقون', + 34471 => 'قشلاق', + 34481 => 'خاکعلی', + 34491 => 'شهرک صنعتی لیا (قدیم)', + 34531 => 'سگز آباد', + 34541 => 'عصمت اباد', + 34551 => 'خرم اباد', + 34561 => 'اسفرورین', + 34571 => 'شال', + 34581 => 'دانسفهان', + 34631 => 'کلنجین', + 34641 => 'آبگرم', + 34651 => 'استبلخ', + 34671 => 'ارداق', + 34681 => 'نیارج', + 34691 => 'حصارولیعصر', + 34731 => 'ماهین', + 34741 => 'سیردان', + 34761 => 'سیاهپوش', + 34781 => 'نیارک', + 34791 => 'اقابابا', + 34811 => 'نرجه', + 34831 => 'خرمدشت', + 34851 => 'ضیاءآباد', + 34871 => 'حسین اباد', + 34891 => 'رحیم اباد', + 34913 => 'مهرگان', + 34931 => 'معلم کلایه', + 34941 => 'یحیی اباد', + 34951 => 'نیکویه', + 34961 => 'رازمیان', + 34971 => 'کوهین', + ], + ], + 9 => [ + 'title' => 'سمنان', + 'cities' => [ + 351 => 'سمنان', + 361 => 'شاهرود', + 3531 => 'علا', + 3541 => 'ابخوری', + 3551 => 'سرخه', + 3561 => 'مهدیشهر', + 3571 => 'شهمیرزاد', + 3581 => 'گرمسار', + 3591 => 'ایوانکی', + 3631 => 'میامی', + 3641 => 'بسطام', + 3651 => 'مجن', + 3661 => 'بیارجمند', + 3671 => 'دامغان', + 3681 => 'امیریه', + 35331 => 'خیراباد', + 35341 => 'ایستگاه میان دره', + 35381 => 'اهوان', + 35431 => 'جام', + 35441 => 'دوزهیر', + 35451 => 'معدن نمک', + 35531 => 'نظامی', + 35541 => 'اسداباد', + 35551 => 'لاسجرد', + 35561 => 'سیداباد', + 35571 => 'عبدالله ابادپایین', + 35581 => 'بیابانک', + 35591 => 'مومن اباد', + 35631 => 'درجزین', + 35641 => 'دربند', + 35651 => 'گل رودبار', + 35661 => 'ابگرم', + 35671 => 'افتر', + 35731 => 'فولادمحله', + 35741 => 'ده صوفیان', + 35751 => 'هیکو', + 35761 => 'چاشم', + 35831 => 'کردوان', + 35841 => 'مندولک', + 35851 => 'داوراباد', + 35861 => 'آرادان', + 35881 => 'بن کوه', + 35891 => 'کهن آباد', + 35931 => 'حسین ابادکوروس', + 35941 => 'کرک', + 35951 => 'گلستانک', + 35961 => 'لجران', + 36331 => 'جودانه', + 36341 => 'ابراهیم اباد', + 36351 => 'بکران', + 36361 => 'کرداباد', + 36371 => 'نردین', + 36381 => 'سوداغلان', + 36391 => 'فرومد', + 36431 => 'ابرسیج', + 36441 => 'میغان', + 36451 => 'قلعه نوخرقان', + 36461 => 'چهلدخترپادگان', + 36471 => 'کلاته خیج', + 36531 => 'نگارمن', + 36541 => 'دهملا', + 36551 => 'رویان', + 36561 => 'بدشت', + 36571 => 'سطوه', + 36581 => 'طرود', + 36591 => 'مغان', + 36631 => 'گیور', + 36641 => 'دستجرد', + 36651 => 'مسیح اباد', + 36661 => 'احمداباد', + 36671 => 'زمان اباد', + 36681 => 'سلمرود', + 36731 => 'جزن', + 36741 => 'برم', + 36751 => 'محمداباد', + 36761 => 'معصوم اباد', + 36771 => 'فرات', + 36781 => 'علیان', + 36791 => 'عمروان', + 36831 => 'قوشه', + 36841 => 'دروار', + 36851 => 'استانه', + 36861 => 'دیباج', + 36871 => 'طرزه', + 36881 => 'مهماندوست', + 36891 => 'کلاته ملا', + 36931 => 'قدرت اباد', + ], + ], + 10 => [ + 'title' => 'قم', + 'cities' => [ + 371 => 'قم', + 3731 => 'قنوات', + 3741 => 'دستجرد', + 37331 => 'امیرابادگنجی', + 37341 => 'قمرود', + 37351 => 'کهک', + 37361 => 'قلعه چم', + 37431 => 'قاهان', + 37441 => 'جعفریه', + 37451 => 'جنداب', + 37461 => 'سلفچگان', + ], + ], + 11 => [ + 'title' => 'مركزي', + 'cities' => [ + 381 => 'اراک', + 391 => 'ساوه', + 3771 => 'پرندک', + 3781 => 'محلات', + 3791 => 'دلیجان', + 3831 => 'کرهرود', + 3841 => 'خنداب', + 3851 => 'کمیجان', + 3861 => 'شازند', + 3871 => 'آستانه', + 3881 => 'خمین', + 3891 => 'رباطمراد', + 3931 => 'غرق آباد', + 3941 => 'مامونیه', + 3951 => 'تفرش', + 3961 => 'آشتیان', + 3991 => 'شهرجدیدمهاجران', + 37731 => 'سلطان اباد', + 37741 => 'اصفهانک', + 37751 => 'حسین اباد', + 37761 => 'خشکرود', + 37771 => 'حکیم اباد', + 37781 => 'یحیی اباد', + 37791 => 'صدراباد', + 37841 => 'نیمور', + 37851 => 'نخجیروان', + 37861 => 'باقراباد', + 37871 => 'بزیجان', + 37881 => 'عیسی اباد', + 37891 => 'خورهه', + 37961 => 'نراق', + 38341 => 'ساروق', + 38351 => 'داودآباد', + 38361 => 'کارچان', + 38451 => 'جاورسیان', + 38461 => 'ادشته', + 38471 => 'استوه', + 38481 => 'سنجان', + 38491 => 'اناج', + 38531 => 'وفس', + 38541 => 'خسروبیگ', + 38551 => 'میلاجرد', + 38561 => 'سمقاور', + 38571 => 'هزاوه', + 38631 => 'قدمگاه', + 38641 => 'هفته', + 38651 => 'لنجرود', + 38661 => 'توره', + 38671 => 'کزاز', + 38681 => 'کتیران بالا', + 38691 => 'نهرمیان', + 38731 => 'سرسختی بالا', + 38741 => 'لوزدرعلیا', + 38761 => 'هندودر', + 38771 => 'تواندشت علیا', + 38781 => 'مالمیر', + 38791 => 'چهارچریک', + 38841 => 'چهارچشمه', + 38851 => 'لکان', + 38861 => 'قورچی باشی', + 38871 => 'ورچه', + 38881 => 'فرفهان', + 38891 => 'امامزاده ورچه', + 38931 => 'رباطکفسان', + 38941 => 'ریحان علیا', + 38951 => 'جزنق', + 38961 => 'خوراوند', + 38971 => 'میشیجان علیا', + 38981 => 'گلدشت', + 38991 => 'دهنو', + 39331 => 'نوبران', + 39351 => 'یل اباد', + 39361 => 'رازقان', + 39371 => 'الویر', + 39381 => 'دوزج', + 39391 => 'علیشار', + 39431 => 'بالقلو', + 39441 => 'زاویه', + 39451 => 'چمران', + 39461 => 'قاقان', + 39471 => 'سامان', + 39481 => 'دخان', + 39491 => 'مراغه', + 39531 => 'فرمهین', + 39541 => 'شهراب', + 39551 => 'زاغر', + 39561 => 'کهک', + 39571 => 'فشک', + 39581 => 'اهنگران', + 39631 => 'مزرعه نو', + 39641 => 'صالح اباد', + 39651 => 'سیاوشان', + 39661 => 'اهو', + ], + ], + 12 => [ + 'title' => 'زنجان', + 'cities' => [ + 451 => 'زنجان', + 4531 => 'زرین آباد', + 4541 => 'ماهنشان', + 4551 => 'سلطانیه', + 4561 => 'ابهر', + 4571 => 'خرمدره', + 4581 => 'قیدار', + 4591 => 'آب بر', + 45331 => 'همایون', + 45341 => 'بوغداکندی', + 45351 => 'اژدهاتو', + 45371 => 'اسفجین', + 45381 => 'ارمغانخانه', + 45391 => 'قبله بلاغی', + 45431 => 'پری', + 45441 => 'اندابادعلیا', + 45451 => 'قره گل', + 45461 => 'نیک پی', + 45471 => 'دندی', + 45481 => 'سونتو', + 45491 => 'قلتوق', + 45531 => 'گوزلدره', + 45551 => 'سنبل اباد', + 45641 => 'درسجین', + 45651 => 'دولت اباد', + 45661 => 'کینه ورس', + 45731 => 'هیدج', + 45741 => 'صائین قلعه', + 45781 => 'اقبلاغ سفلی', + 45791 => 'سهرورد', + 45831 => 'کرسف', + 45841 => 'سجاس', + 45851 => 'محموداباد', + 45861 => 'باش قشلاق', + 45871 => 'گرماب', + 45881 => 'زرین رود', + 45891 => 'کهلا', + 45931 => 'گیلوان', + 45941 => 'دستجرده', + 45951 => 'سعیداباد', + 45961 => 'چورزق', + 45971 => 'حلب', + 45981 => 'درام', + ], + ], + 13 => [ + 'title' => 'مازندران', + 'cities' => [ + 461 => 'آمل', + 471 => 'بابل', + 481 => 'ساری', + 4631 => 'محمودآباد', + 4641 => 'نور', + 4651 => 'نوشهر', + 4661 => 'چالوس', + 4671 => 'سلمانشهر', + 4681 => 'تنکابن', + 4691 => 'رامسر', + 4731 => 'امیرکلا', + 4741 => 'بابلسر', + 4751 => 'فریدونکنار', + 4761 => 'قائم شهر', + 4771 => 'جویبار', + 4781 => 'زیر آب', + 4791 => 'پل سفید', + 4831 => 'کیاسر', + 4841 => 'نکا', + 4851 => 'بهشهر', + 4861 => 'گلوگاه', + 46181 => 'دابودشت', + 46331 => 'معلم کلا', + 46341 => 'سرخرود', + 46351 => 'وسطی کلا', + 46361 => 'رینه', + 46371 => 'سوا', + 46381 => 'باییجان', + 46391 => 'گزنک', + 46411 => 'ایزدشهر', + 46431 => 'چمستان', + 46441 => 'بنفشه ده', + 46451 => 'رییس کلا', + 46461 => 'اوز', + 46471 => 'بلده', + 46481 => 'تاکر', + 46491 => 'گلندرود', + 46531 => 'چلندر', + 46541 => 'صلاح الدین کلا', + 46551 => 'نارنج بن', + 46561 => 'رویان', + 46571 => 'کجور', + 46581 => 'پول', + 46591 => 'لشکنار', + 46631 => 'هیچرود', + 46641 => 'مرزن آباد', + 46651 => 'کردیچال', + 46661 => 'کلاردشت', + 46671 => 'کلنو', + 46681 => 'دلیر', + 46691 => 'سیاه بیشه', + 46731 => 'کلارآباد', + 46741 => 'عباس آباد', + 46751 => 'سرلنگا', + 46761 => 'کترا', + 46771 => 'گلعلی اباد', + 46781 => 'میان کوه سادات', + 46791 => 'مران سه هزار', + 46831 => 'نشتارود', + 46841 => 'قلعه گردن', + 46851 => 'خرم آباد', + 46861 => 'شیرود', + 46871 => 'سلیمان اباد', + 46881 => 'کشکو', + 46891 => 'لاک تراشان', + 46931 => 'سادات محله', + 46941 => 'کتالم وسادات شهر', + 46961 => 'اغوزکتی', + 46971 => 'جواهرده', + 46981 => 'جنت رودبار', + 46991 => 'تمل', + 47331 => 'خوشرودپی', + 47341 => 'اهنگرکلا', + 47351 => 'گاوانکلا', + 47381 => 'شورکش', + 47391 => 'اینج دان', + 47431 => 'عرب خیل', + 47441 => 'بهنمیر', + 47451 => 'کاسگرمحله', + 47461 => 'کله بست', + 47471 => 'بیشه سر', + 47491 => 'گتاب', + 47541 => 'درازکش', + 47551 => 'گردرودبار', + 47561 => 'مرزی کلا', + 47571 => 'شهیداباد', + 47581 => 'زرگرمحله', + 47631 => 'بالاجنیدلاک پل', + 47641 => 'خطیرکلا', + 47651 => 'حاجی کلاصنم', + 47661 => 'واسکس', + 47681 => 'ریکنده', + 47691 => 'ارطه', + 47731 => 'کیاکلا', + 47741 => 'بالادسته رکن کنار', + 47751 => 'بیزکی', + 47761 => 'کوهی خیل', + 47781 => 'سنگتاب', + 47791 => 'رکابدارکلا', + 47831 => 'شیرکلا', + 47841 => 'آلاشت', + 47851 => 'لفور (لفورک)', + 47861 => 'اتو', + 47871 => 'شیرگاه', + 47881 => 'پالند', + 47891 => 'چرات', + 47931 => 'ده میان', + 47941 => 'خشک دره', + 47951 => 'امافت', + 47961 => 'بالادواب', + 47971 => 'ورسک', + 47981 => 'کتی لته', + 48331 => 'اروست', + 48341 => 'فریم', + 48351 => 'سنگده', + 48361 => 'قادیکلا', + 48371 => 'تاکام', + 48390 => 'پایین هولار', + 48391 => 'بالاهولار', + 48431 => 'اسبوکلا', + 48441 => 'سورک', + 48451 => 'اسلام اباد', + 48461 => 'شهرک صنعتی گهرباران', + 48471 => 'فرح اباد (خزراباد)', + 48481 => 'دارابکلا', + 48491 => 'ماچک پشت', + 48531 => 'خورشید (امامیه)', + 48541 => 'زاغمرز', + 48551 => 'چلمردی', + 48561 => 'رستم کلا', + 48571 => 'پایین زرندین', + 48591 => 'بادابسر', + 48631 => 'تیرتاش', + 48641 => 'خلیل شهر', + 48661 => 'دامداری حسن ابوطالبی', + 48671 => 'بیشه بنه', + 48681 => 'سفیدچاه', + 48691 => 'دامداری حاج عزیزمجریان', + 48841 => 'میان دره', + 48872 => 'بندپی', + ], + ], + 14 => [ + 'title' => 'گلستان', + 'cities' => [ + 491 => 'گرگان', + 4871 => 'بندر گز', + 4881 => 'کردکوی', + 4891 => 'بندرترکمن', + 4931 => 'آق قلا', + 4941 => 'علی آباد', + 4951 => 'رامیان', + 4961 => 'آزاد شهر', + 4971 => 'گنبد کاووس', + 4981 => 'مینو دشت', + 4991 => 'کلاله', + 48731 => 'نوکنده', + 48733 => 'مراوه تپه', + 48961 => 'گمیش تپه', + 48971 => 'سیمین شهر', + 49351 => 'جلین', + 49361 => 'سرخنکلاته', + 49371 => 'تقی اباد', + 49391 => 'انبار آلوم', + 49431 => 'فاضل آباد', + 49471 => 'حاجیکلاته', + 49531 => 'خان ببین', + 49541 => 'دلند', + 49631 => 'نگین شهر', + 49641 => 'نوده خاندوز', + 49680 => 'تاتارعلیا', + 49751 => 'اینچه برون', + 49791 => 'کرند', + 49831 => 'گالیکش', + 49981 => 'عزیزاباد', + ], + ], + 15 => [ + 'title' => 'اردبيل', + 'cities' => [ + 561 => 'اردبیل', + 5631 => 'نمین', + 5641 => 'نیر', + 5651 => 'گرمی', + 5661 => 'مشگین شهر', + 5671 => 'بیله سوار', + 5681 => 'خلخال', + 5691 => 'پارس آباد', + 56331 => 'آبی بیگلو', + 56341 => 'ننه کران', + 56351 => 'عنبران', + 56361 => 'گرده', + 56371 => 'ثمرین', + 56381 => 'اردیموسی', + 56391 => 'سرعین', + 56431 => 'کورائیم', + 56441 => 'اسلام آباد', + 56451 => 'مهماندوست علیا', + 56461 => 'هیر', + 56471 => 'بقراباد', + 56481 => 'بودالالو', + 56491 => 'اراللوی بزرگ', + 56531 => 'دیزج', + 56541 => 'حمزه خانلو', + 56551 => 'زهرا', + 56561 => 'انی علیا', + 56571 => 'قاسم کندی', + 56581 => 'تازه کندانگوت', + 56591 => 'قره اغاج پایین', + 56631 => 'پریخان', + 56641 => 'قصابه', + 56651 => 'فخرآباد', + 56653 => 'لاهرود', + 56661 => 'رضی', + 56671 => 'قوشه سفلی', + 56681 => 'مرادلو', + 56691 => 'گنجوبه', + 56731 => 'گوگ تپه', + 56741 => 'انجیرلو', + 56751 => 'جعفر آباد', + 56761 => 'قشلاق اغداش کلام', + 56771 => 'خورخورسفلی', + 56781 => 'شورگل', + 56791 => 'نظرعلی بلاغی', + 56831 => 'لنبر', + 56841 => 'فیروزاباد', + 56851 => 'گیوی', + 56861 => 'خلفلو', + 56871 => 'هشتجین', + 56881 => 'برندق', + 56891 => 'کلور', + 56931 => 'تازه کندجدید', + 56941 => 'گوشلو', + 56961 => 'اق قباق علیا', + 56971 => 'شهرک غفاری', + 56981 => 'اصلاندوز', + 56991 => 'بران علیا', + ], + ], + 16 => [ + 'title' => 'آذربايجان غربي', + 'cities' => [ + 571 => 'ارومیه', + 573 => 'سیلوه', + 581 => 'خوی', + 591 => 'مهاباد', + 5751 => 'قوشچی', + 5761 => 'نقده', + 5771 => 'اشنویه', + 5781 => 'پیرانشهر', + 5791 => 'جلدیان', + 5831 => 'ایواوغلی', + 5837 => 'دیزج دیز', + 5841 => 'فیرورق', + 5861 => 'ماکو', + 5881 => 'سلماس', + 5891 => 'تازه شهر', + 5931 => 'گوگ تپه', + 5951 => 'بوکان', + 5961 => 'سردشت', + 5971 => 'میاندوآب', + 5981 => 'شاهیندژ', + 5991 => 'تکاب', + 57331 => 'باراندوز', + 57341 => 'دیزج دول', + 57351 => 'میاوق', + 57361 => 'ایبلو', + 57371 => 'دستجرد', + 57381 => 'نوشین', + 57391 => 'طلاتپه', + 57411 => 'سیلوانه', + 57431 => 'راژان', + 57441 => 'هاشم اباد', + 57451 => 'دیزج', + 57461 => 'زیوه', + 57471 => 'تویی', + 57481 => 'موانا', + 57531 => 'قره باغ', + 57541 => 'بهله', + 57551 => 'امام کندی', + 57561 => 'نازلو', + 57571 => 'سرو', + 57581 => 'کانسپی', + 57591 => 'ممکان', + 57641 => 'حسنلو', + 57651 => 'کهریزعجم', + 57661 => 'محمدیار', + 57671 => 'شیخ احمد', + 57681 => 'بیگم قلعه', + 57691 => 'راهدانه', + 57731 => 'شاهوانه', + 57741 => 'نالوس', + 57751 => 'ده شمس بزرگ', + 57761 => 'گلاز', + 57771 => 'لولکان', + 57781 => 'سیاوان', + 57831 => 'کله کین', + 57841 => 'شین اباد', + 57851 => 'چیانه', + 57861 => 'بیکوس', + 57871 => 'هنگ اباد', + 57941 => 'گردکشانه', + 57951 => 'پسوه', + 57961 => 'ریگ اباد', + 57971 => 'احمدغریب', + 58331 => 'سیه باز', + 58341 => 'بیله وار', + 58361 => 'ولدیان', + 58381 => 'قوروق', + 58391 => 'هندوان', + 58431 => 'بدلان', + 58441 => 'بلسورسفلی', + 58450 => 'زرآباد', + 58471 => 'استران', + 58481 => 'قطور', + 58516 => 'قره ضیاءالدین', + 58531 => 'شیرین بلاغ', + 58541 => 'مراکان', + 58551 => 'چورس', + 58561 => 'قورول علیا', + 58571 => 'بسطام', + 58631 => 'قره تپه', + 58641 => 'ریحانلوی علیا', + 58651 => 'زاویه سفلی', + 58661 => 'آواجیق', + 58671 => 'بازرگان', + 58681 => 'قم قشلاق', + 58691 => 'یولاگلدی', + 58716 => 'سیه چشمه', + 58731 => 'قرنقو', + 58751 => 'شوط', + 58761 => 'مرگنلر', + 58771 => 'پلدشت', + 58781 => 'نازک علیا', + 58791 => 'حسن کندی', + 58831 => 'وردان', + 58861 => 'قره قشلاق', + 58871 => 'تمر', + 58881 => 'ابگرم', + 58891 => 'سرنق', + 58931 => 'چهریق علیا', + 58941 => 'داراب', + 58951 => 'دلزی', + 58961 => 'اغ برزه', + 58971 => 'سنجی', + 59341 => 'خاتون باغ', + 59351 => 'حاجی حسن', + 59361 => 'سوگلی تپه', + 59371 => 'گلیجه', + 59381 => 'حاجی کند', + 59431 => 'باغچه', + 59441 => 'خورخوره', + 59450 => 'خلیفان', + 59451 => 'کاولان علیا', + 59461 => 'سیاقول علیا', + 59471 => 'اگریقاش', + 59481 => 'اوزون دره علیا', + 59531 => 'یکشوه', + 59541 => 'جوانمرد', + 59551 => 'اختتر', + 59561 => 'سیمینه', + 59571 => 'رحیم خان', + 59581 => 'گل تپه قورمیش', + 59631 => 'شلماش', + 59641 => 'اسلام اباد', + 59651 => 'بیوران سفلی', + 59671 => 'میرآباد', + 59681 => 'زمزیران', + 59691 => 'ربط', + 59730 => 'کشاورز', + 59731 => 'اقبال', + 59741 => 'ملاشهاب الدین', + 59751 => 'للکلو', + 59761 => 'بگتاش', + 59771 => 'چهار برج', + 59781 => 'گوگ تپه خالصه', + 59791 => 'تک اغاج', + 59831 => 'هاچاسو', + 59841 => 'هولاسو', + 59851 => 'قوزلوی افشار', + 59861 => 'محمودآباد', + 59871 => 'الی چین', + 59881 => 'حیدرباغی', + 59891 => 'حمزه قاسم', + 59931 => 'اوغول بیگ', + 59941 => 'دورباش', + 59951 => 'اقابیگ', + 59961 => 'احمدابادسفلی', + 59981 => 'باروق', + ], + ], + 17 => [ + 'title' => 'همدان', + 'cities' => [ + 651 => 'همدان', + 6531 => 'بهار', + 6541 => 'اسدآباد', + 6551 => 'کبودرآهنگ', + 6561 => 'فامنین', + 6571 => 'ملایر', + 6581 => 'تویسرکان', + 6591 => 'نهاوند', + 65141 => 'مریانج', + 65181 => 'جورقان', + 65331 => 'لالجین', + 65341 => 'دیناراباد', + 65351 => 'همه کسی', + 65361 => 'صالح آباد', + 65371 => 'پرلوک', + 65381 => 'حسین ابادبهارعاشوری', + 65391 => 'مهاجران', + 65431 => 'ویرایی', + 65441 => 'جنت اباد', + 65451 => 'موسی اباد', + 65461 => 'چنارسفلی', + 65471 => 'چنارعلیا', + 65481 => 'آجین', + 65491 => 'طویلان سفلی', + 65531 => 'کوریجان', + 65541 => 'کوهین', + 65551 => 'قهوردسفلی', + 65561 => 'اکنلو', + 65571 => 'شیرین سو', + 65581 => 'گل تپه', + 65591 => 'داق داق اباد', + 65631 => 'قهاوند', + 65641 => 'تجرک', + 65651 => 'کوزره', + 65661 => 'چانگرین', + 65671 => 'دمق', + 65681 => 'رزن', + 65691 => 'قروه درجزین', + 65731 => 'ازناو', + 65741 => 'جوزان', + 65751 => 'زنگنه', + 65761 => 'سامن', + 65771 => 'اورزمان', + 65781 => 'جوکار', + 65791 => 'اسلام اباد', + 65831 => 'جعفریه (قلعه جعفربیک)', + 65841 => 'سرکان', + 65851 => 'میانده', + 65861 => 'فرسفج', + 65871 => 'ولاشجرد', + 65881 => 'اشتران', + 65891 => 'باباپیر', + 65931 => 'جهان اباد', + 65941 => 'باباقاسم', + 65951 => 'بابارستم', + 65960 => 'برزول', + 65961 => 'گیان', + 65971 => 'دهفول', + 65981 => 'فیروزان', + 65991 => 'شهرک صنعتی بوعلی', + 65992 => 'پایگاه نوژه', + 65993 => 'علیصدر', + 65995 => 'ازندریان', + 65998 => 'گنبد', + 66000 => 'پادگان قهرمان', + ], + ], + 18 => [ + 'title' => 'كردستان', + 'cities' => [ + 661 => 'سنندج', + 6631 => 'کامیاران', + 6641 => 'دیواندره', + 6651 => 'بیجار', + 6661 => 'قروه', + 6671 => 'مریوان', + 6681 => 'سقز', + 6691 => 'بانه', + 66171 => 'شویشه', + 66331 => 'شاهینی', + 66341 => 'طای', + 66351 => 'گازرخانی', + 66361 => 'نشورسفلی', + 66371 => 'شیروانه', + 66381 => 'خامسان', + 66391 => 'موچش', + 66431 => 'شریف اباد', + 66441 => 'کوله', + 66451 => 'هزارکانیان', + 66461 => 'زرینه', + 66471 => 'گورباباعلی', + 66481 => 'گاوشله', + 66491 => 'خرکه', + 66531 => 'یاسوکند', + 66541 => 'توپ اغاج', + 66551 => 'اق بلاغ طغامین', + 66561 => 'بابارشانی', + 66571 => 'خسرواباد', + 66591 => 'جعفراباد', + 66631 => 'دلبران', + 66641 => 'دزج', + 66651 => 'کانی گنجی', + 66661 => 'بلبان آباد', + 66671 => 'دهگلان', + 66681 => 'قوریچای', + 66691 => 'سریش آباد', + 66711 => 'کانی دینار', + 66731 => 'نی', + 66741 => 'برده رشه', + 66751 => 'چناره', + 66761 => 'پیرخضران', + 66771 => 'بیساران', + 66781 => 'سروآباد', + 66791 => 'اورامان تخت', + 66831 => 'سرا', + 66841 => 'گل تپه', + 66851 => 'تیلکو', + 66861 => 'صاحب', + 66871 => 'خورخوره', + 66881 => 'کسنزان', + 66891 => 'میرده', + 66931 => 'ننور', + 66941 => 'بوئین سفلی', + 66951 => 'آرمرده', + 66961 => 'بوالحسن', + 66971 => 'کانی سور', + 66981 => 'کوخان', + 66991 => 'شوی', + ], + ], + 19 => [ + 'title' => 'كرمانشاه', + 'cities' => [ + 671 => 'کرمانشاه', + 6731 => 'هرسین', + 6741 => 'کنگاور', + 6751 => 'سنقر', + 6761 => 'اسلام آبادغرب', + 6771 => 'سرپل ذهاب', + 6781 => 'قصرشیرین', + 6791 => 'پاوه', + 67131 => 'رباط', + 67331 => 'هفت اشیان', + 67341 => 'هلشی', + 67351 => 'دوردشت', + 67361 => 'سنقراباد', + 67371 => 'بیستون', + 67381 => 'جعفراباد', + 67391 => 'مرزبانی', + 67431 => 'فش', + 67441 => 'فرامان', + 67451 => 'سلطان اباد', + 67461 => 'صحنه', + 67471 => 'قزوینه', + 67481 => 'دهلقین', + 67491 => 'درکه', + 67531 => 'باوله', + 67541 => 'گردکانه علیا', + 67551 => 'اگاه علیا', + 67561 => 'سطر', + 67571 => 'کیوه نان', + 67580 => 'میان راهان', + 67581 => 'کرکسار', + 67591 => 'کندوله', + 67631 => 'زاوله علیا', + 67641 => 'حمیل', + 67651 => 'ریجاب', + 67661 => 'کرندغرب', + 67671 => 'گهواره', + 67681 => 'کوزران', + 67691 => 'قلعه شیان', + 67731 => 'حسن اباد', + 67741 => 'سراب ذهاب', + 67751 => 'ترک ویس', + 67761 => 'ازگله', + 67771 => 'تازه آباد', + 67781 => 'نساردیره', + 67791 => 'سرمست', + 67831 => 'تپه رش', + 67841 => 'خسروی', + 67861 => 'سومار', + 67871 => 'گیلانغرب', + 67891 => 'قیلان', + 67911 => 'شاهو', + 67931 => 'باینگان', + 67940 => 'بانوره', + 67941 => 'نوسود', + 67951 => 'نودشه', + 67961 => 'روانسر', + 67971 => 'دولت اباد', + 67981 => 'جوانرود', + 67991 => 'میراباد', + ], + ], + 20 => [ + 'title' => 'لرستان', + 'cities' => [ + 681 => 'خرم آباد', + 691 => 'بروجرد', + 6831 => 'نورآباد', + 6841 => 'کوهدشت', + 6851 => 'پلدختر', + 6861 => 'الیگودرز', + 6871 => 'ازنا', + 6881 => 'دورود', + 6891 => 'الشتر', + 68141 => 'ماسور', + 68181 => 'بیرانوند', + 68331 => 'برخوردار', + 68341 => 'فرهاداباد', + 68351 => 'دم باغ', + 68361 => 'کهریزوروشت', + 68371 => 'چشمه کیزاب علیا', + 68381 => 'هفت چشمه', + 68391 => 'تقی اباد', + 68431 => 'خوشناموند', + 68441 => 'اشتره گل گل', + 68451 => 'چقابل', + 68461 => 'سوری', + 68471 => 'کونانی', + 68481 => 'گراب', + 68491 => 'درب گنبد', + 68531 => 'پاعلم (پل تنگ)', + 68541 => 'واشیان نصیرتپه', + 68551 => 'چمشک زیرتنگ', + 68561 => 'افرینه', + 68571 => 'معمولان', + 68580 => 'ویسیان', + 68581 => 'میان تاگان', + 68591 => 'پل شوراب پایین', + 68631 => 'شاهپوراباد', + 68641 => 'چمن سلطان', + 68651 => 'کیزاندره', + 68661 => 'قلعه بزنوید', + 68671 => 'شول آباد', + 68681 => 'حیه', + 68691 => 'مرگ سر', + 68731 => 'مومن آباد', + 68741 => 'رازان', + 68751 => 'سیاه گوشی (پل هرو)', + 68761 => 'زاغه', + 68771 => 'سرابدوره', + 68781 => 'چاه ذوالفقار', + 68791 => 'چم پلک', + 68831 => 'ژان', + 68841 => 'کاغه', + 68851 => 'چالانچولان', + 68861 => 'سپید دشت', + 68871 => 'چم سنگر', + 68881 => 'ایستگاه تنگ هفت', + 68891 => 'مکینه حکومتی', + 68931 => 'سراب سیاهپوش', + 68951 => 'ده رحم', + 68961 => 'فیروز آباد', + 68971 => 'اشترینان', + 68981 => 'بندیزه', + 68991 => 'دره گرگ', + ], + ], + 21 => [ + 'title' => 'بوشهر', + 'cities' => [ + 751 => 'بوشهر', + 7531 => 'بندرگناوه', + 7541 => 'خورموج', + 7551 => 'اهرم', + 7561 => 'برازجان', + 75111 => 'نخل تقی', + 75331 => 'بندر ریگ', + 75341 => 'چهارروستایی', + 75351 => 'شول', + 75361 => 'بندر دیلم', + 75371 => 'امام حسن', + 75381 => 'چغادک', + 75390 => 'سیراف', + 75391 => 'عسلویه', + 75431 => 'بادوله', + 75441 => 'شنبه', + 75451 => 'کاکی', + 75461 => 'خارک', + 75471 => 'دلوار', + 75481 => 'بنه گز', + 75491 => 'اباد', + 75531 => 'بردخون', + 75540 => 'بردستان', + 75541 => 'بندردیر', + 75551 => 'آبدان', + 75560 => 'انارستان', + 75561 => 'ریز', + 75570 => 'بنک', + 75571 => 'بندرکنگان', + 75581 => 'جم', + 75591 => 'ابگرمک', + 75631 => 'دالکی', + 75641 => 'شبانکاره', + 75651 => 'آبپخش', + 75661 => 'سعدآباد', + 75671 => 'وحدتیه', + 75681 => 'تنگ ارم', + 75691 => 'کلمه', + ], + ], + 22 => [ + 'title' => 'كرمان', + 'cities' => [ + 761 => 'کرمان', + 771 => 'رفسنجان', + 781 => 'سیرجان', + 7631 => 'ماهان', + 7641 => 'گلباف', + 7651 => 'راور', + 7661 => 'بم', + 7671 => 'بروات', + 7681 => 'راین', + 7691 => 'محمدآباد', + 7731 => 'سرچشمه', + 7741 => 'انار', + 7751 => 'شهربابک', + 7761 => 'زرند', + 7771 => 'کیانشهر', + 7781 => 'کوهبنان', + 7791 => 'چترود', + 7831 => 'پاریز', + 7841 => 'بردسیر', + 7851 => 'بافت', + 7861 => 'جیرفت', + 7871 => 'عنبرآباد', + 7881 => 'کهنوج', + 7891 => 'منوجان', + 76331 => 'ده بالا', + 76361 => 'جوپار', + 76371 => 'باغین', + 76381 => 'اختیارآباد', + 76391 => 'زنگی آباد', + 76431 => 'جوشان', + 76451 => 'اندوهجرد', + 76461 => 'شهداد', + 76471 => 'کشیت', + 76541 => 'فیض اباد', + 76641 => 'دریجان', + 76731 => 'نرماشیر', + 76741 => 'فهرج', + 76771 => 'برج معاز', + 76791 => 'نظام شهر', + 76831 => 'خانه خاتون', + 76841 => 'ابارق', + 76861 => 'گروه', + 76871 => 'گزک', + 76891 => 'محی آباد', + 76941 => 'تهرود', + 76951 => 'میرابادارجمند', + 77331 => 'داوران', + 77341 => 'خنامان', + 77351 => 'کبوترخان', + 77361 => 'هرمزاباد', + 77371 => 'کشکوئیه', + 77381 => 'گلشن', + 77391 => 'صفائیه', + 77431 => 'امین شهر', + 77461 => 'بهرمان', + 77471 => 'جوادیه الهیه نوق', + 77511 => 'خاتون آباد', + 77541 => 'محمدابادبرفه', + 77551 => 'خورسند', + 77561 => 'خبر', + 77571 => 'کمسرخ', + 77581 => 'جوزم', + 77591 => 'دهج', + 77631 => 'دشت خاک', + 77651 => 'حتکن', + 77661 => 'ریحان', + 77671 => 'جرجافک', + 77691 => 'یزدان شهر', + 77731 => 'شعبجره', + 77751 => 'سیریز', + 77761 => 'خانوک', + 77861 => 'جور', + 77931 => 'هوتک', + 77951 => 'کاظم آباد', + 77961 => 'هجدک', + 77971 => 'حرجند', + 78151 => 'نجف شهر', + 78331 => 'بلورد', + 78341 => 'ملک اباد', + 78361 => 'عماداباد', + 78371 => 'زیدآباد', + 78380 => 'هماشهر', + 78431 => 'نگار', + 78441 => 'گلزار', + 78451 => 'لاله زار', + 78461 => 'قلعه عسکر', + 78471 => 'مومن اباد', + 78481 => 'چناربرین', + 78491 => 'کمال اباد', + 78541 => 'امیراباد', + 78551 => 'بزنجان', + 78561 => 'رابر', + 78571 => 'پتکان', + 78591 => 'ارزوئیه', + 78631 => 'جبالبارز', + 78661 => 'درب بهشت', + 78691 => 'رضی ابادبالا', + 78731 => 'میجان علیا', + 78761 => 'مردهک', + 78771 => 'دوساری', + 78781 => 'حسین ابادجدید', + 78791 => 'بلوک', + 78831 => 'رودبار', + 78841 => 'قلعه گنج', + 78851 => 'نودژ', + 78871 => 'فاریاب', + 78941 => 'سرخ قلعه', + 78971 => 'خیراباد', + ], + ], + 23 => [ + 'title' => 'هرمزگان', + 'cities' => [ + 791 => 'بندرعباس', + 7931 => 'خمیر', + 7941 => 'کیش', + 7951 => 'قشم', + 7961 => 'بستک', + 7971 => 'بندرلنگه', + 7981 => 'میناب', + 7991 => 'دهبارز', + 79331 => 'پشته ایسین', + 79341 => 'پل شرقی', + 79351 => 'فین', + 79361 => 'سیاهو', + 79370 => 'سرگز', + 79371 => 'فارغان', + 79381 => 'باغات', + 79391 => 'حاجی آباد', + 79431 => 'ابگرم خورگو', + 79441 => 'قلعه قاضی', + 79450 => 'تخت', + 79451 => 'حسن لنگی پایین', + 79460 => 'گروک', + 79461 => 'سیریک', + 79471 => 'گونمردی', + 79491 => 'گوهرت', + 79531 => 'درگهان', + 79541 => 'سوزا', + 79551 => 'هرمز', + 79561 => 'جزیره لارک شهری', + 79571 => 'هنگام جدید', + 79581 => 'جزیره سیری', + 79591 => 'ابوموسی', + 79611 => 'جناح', + 79631 => 'پدل', + 79641 => 'کنگ', + 79651 => 'دژگان', + 79661 => 'رویدر', + 79671 => 'دهنگ', + 79691 => 'کمشک', + 79711 => 'کوشکنار', + 79731 => 'گزیر', + 79741 => 'بندرمغویه', + 79751 => 'چارک', + 79761 => 'دشتی', + 79771 => 'پارسیان', + 79781 => 'جزیره لاوان', + 79791 => 'بندرجاسک', + 79831 => 'بندر', + 79841 => 'سندرک', + 79851 => 'درپهن', + 79861 => 'کلورجکدان', + 79871 => 'گوهران', + 79881 => 'سردشت', + 79911 => 'بیکاه', + 79931 => 'جغین', + 79941 => 'زیارت علی', + 79951 => 'ماشنگی', + 79961 => 'گوربند', + 79971 => 'تیاب', + 79981 => 'بندزرک', + 79991 => 'هشتبندی', + ], + ], + 24 => [ + 'title' => 'چهارمحال و بختياري', + 'cities' => [ + 881 => 'شهر کرد', + 8831 => 'فرخ شهر', + 8834 => 'دزک', + 8841 => 'هفشجان', + 8844 => 'هارونی', + 8851 => 'سامان', + 8861 => 'فارسان', + 8871 => 'بروجن', + 8881 => 'اردل', + 8891 => 'لردگان', + 88139 => 'کیان', + 88331 => 'طاقانک', + 88351 => 'خراجی', + 88361 => 'دستناء', + 88371 => 'شلمزار', + 88381 => 'گهرو', + 88431 => 'سورشجان', + 88451 => 'مرغملک', + 88461 => 'سودجان', + 88561 => 'نافچ', + 88571 => 'وردنجان', + 88581 => 'بن', + 88591 => 'پردنجان', + 88631 => 'باباحیدر', + 88651 => 'چلگرد', + 88661 => 'شهریاری', + 88671 => 'جونقان', + 88731 => 'نقنه', + 88741 => 'فرادنبه', + 88751 => 'سفید دشت', + 88761 => 'بلداجی', + 88771 => 'اورگان', + 88781 => 'گندمان', + 88791 => 'امام قیس', + 88831 => 'ناغان', + 88841 => 'گل سفید', + 88861 => 'چوله دان', + 88881 => 'دشتک', + 88941 => 'آلونی', + 88951 => 'مال خلیفه', + 88961 => 'چمن بید', + 88971 => 'سردشت', + 88991 => 'منج', + ], + ], + 25 => [ + 'title' => 'يزد', + 'cities' => [ + 891 => 'یزد', + 8931 => 'ابرکوه', + 8951 => 'اردکان', + 8961 => 'میبد', + 8971 => 'بافق', + 8981 => 'مهریز', + 8991 => 'تفت', + 89331 => 'فراغه', + 89351 => 'مهردشت', + 89361 => 'اسفنداباد', + 89416 => 'اشکذر', + 89418 => 'زارچ', + 89431 => 'شاهدیه', + 89441 => 'فهرج', + 89451 => 'خضر آباد', + 89481 => 'ندوشن', + 89491 => 'حمیدیا', + 89531 => 'احمد آباد', + 89551 => 'عقدا', + 89571 => 'انارستان', + 89581 => 'زرین', + 89631 => 'بفروئیه', + 89731 => 'اسفیج', + 89751 => 'مبارکه', + 89761 => 'بهاباد', + 89771 => 'کوشک', + 89781 => 'بنستان', + 89831 => 'تنگ چنار (چنار)', + 89851 => 'ارنان', + 89861 => 'بهادران', + 89871 => 'مروست', + 89881 => 'هرات', + 89891 => 'فتح اباد', + 89931 => 'ناحیه صنعتی پیشکوه', + 89941 => 'نصراباد', + 89951 => 'علی اباد', + 89961 => 'نیر', + 89981 => 'ناحیه صنعتی گاریزات', + 89991 => 'دهشیر', + ], + ], + 26 => [ + 'title' => 'سيستان و بلوچستان', + 'cities' => [ + 981 => 'زاهدان', + 991 => 'ایرانشهر', + 9831 => 'نصرت آباد', + 9841 => 'میرجاوه', + 9861 => 'زابل', + 9871 => 'زهک', + 9875 => 'خواجه احمد', + 9891 => 'خاش', + 9931 => 'سرباز', + 9941 => 'بمپور', + 9951 => 'سراوان', + 9961 => 'سوران', + 9971 => 'چابهار', + 9981 => 'کنارک', + 9991 => 'نیکشهر', + ], + ], + 27 => [ + 'title' => 'ايلام', + 'cities' => [ + 6931 => 'ایلام', + 6941 => 'ایوان', + 6951 => 'سرآبله', + 6961 => 'دره شهر', + 6971 => 'آبدانان', + 6981 => 'دهلران', + 6991 => 'مهران', + 69331 => 'چنارباشی', + 69341 => 'بیشه دراز', + 69351 => 'چشمه کبود', + 69361 => 'چوار', + 69371 => 'بانویزه', + 69381 => 'چمن سیدمحمد', + 69391 => 'هفت چشمه', + 69441 => 'شورابه ملک', + 69451 => 'کلان', + 69471 => 'زرنه', + 69511 => 'شباب', + 69531 => 'توحید', + 69541 => 'بلاوه تره سفلی', + 69551 => 'لومار', + 69561 => 'آسمان آباد', + 69571 => 'سراب کارزان', + 69581 => 'شهرک سرتنگ', + 69591 => 'علی اباد', + 69631 => 'ماژین', + 69641 => 'ارمو', + 69661 => 'چشمه شیرین', + 69671 => 'بدره', + 69681 => 'شهرک ولیعصر', + 69731 => 'گنداب', + 69741 => 'ژیور', + 69751 => 'سراب باغ', + 69761 => 'مورموری', + 69771 => 'سیاه گل', + 69781 => 'اب انار', + 69831 => 'چم هندی', + 69841 => 'موسیان', + 69851 => 'گولاب', + 69861 => 'میمه', + 69871 => 'پهله', + 69881 => 'عین خوش', + 69891 => 'دشت عباس', + 69931 => 'شهرک اسلامیه', + 69951 => 'صالح آباد', + 69970 => 'دلگشا', + 69971 => 'ارکواز', + 69972 => 'مهر', + 69981 => 'دول کبودخوشادول', + 69991 => 'پاریاب', + ], + ], + 28 => [ + 'title' => 'كهگيلويه و بويراحمد', + 'cities' => [ + 7571 => 'دهدشت', + 7581 => 'دوگنبدان', + 7591 => 'یاسوج', + 75731 => 'سوق', + 75741 => 'لنده', + 75751 => 'لیکک', + 75761 => 'چرام', + 75771 => 'دیشموک', + 75781 => 'قلعه رییسی', + 75791 => 'قلعه دختر', + 75831 => 'باباکلان', + 75841 => 'مظفراباد', + 75851 => 'دیل', + 75861 => 'شاه بهرام', + 75871 => 'چاه تلخاب علیا', + 75881 => 'باشت', + 75891 => 'سربیشه', + 75911 => 'مادوان', + 75941 => 'چیتاب', + 75951 => 'گراب سفلی', + 75961 => 'مارگون', + 75971 => 'میمند', + 75981 => 'پاتاوه', + 75991 => 'سی سخت', + ], + ], + 29 => [ + 'title' => 'خراسان شمالي', + 'cities' => [ + 941 => 'بجنورد', + 9431 => 'گرمه', + 9441 => 'جاجرم', + 9451 => 'آشخانه', + 9461 => 'شیروان', + 9481 => 'فاروج', + 9661 => 'اسفراین', + ], + ], + 30 => [ + 'title' => 'خراسان جنوبي', + 'cities' => [ + 971 => 'بیرجند', + 9741 => 'سربیشه', + 9751 => 'نهبندان', + 9761 => 'قاین', + 9771 => 'فردوس', + 9781 => 'بشرویه', + 9791 => 'طبس', + ], + ], + 31 => [ + 'title' => 'البرز', + 'cities' => [ + 31 => 'کرج', + 3331 => 'نظرآباد', + 3361 => 'هشتگرد', + 31541 => 'ادران', + 31551 => 'آسارا', + 31638 => 'گرمدره', + 31656 => 'فردیس', + 31776 => 'مشکین دشت', + 31778 => 'محمدشهر', + 31836 => 'کرج (مهرشهر)', + 31849 => 'ماهدشت', + 31871 => 'اشتهارد', + 31991 => 'کمالشهر', + 33351 => 'تنکمان', + 33611 => 'گلسار', + 33618 => 'شهر جدید هشتگرد', + 33651 => 'کوهسار', + 33661 => 'چهارباغ', + 33691 => 'طالقان', + ], + ], + ]; + foreach ($citiesArray as $province) { + foreach ($province['cities'] as $code => $cityName) { + if ($code == $cityCode) { + return $cityName; + } + } + } + return false; + } + +} \ No newline at end of file diff --git a/admin/partials/hesabix-admin-setting.php b/admin/partials/hesabix-admin-setting.php new file mode 100644 index 0000000..c35fb4d --- /dev/null +++ b/admin/partials/hesabix-admin-setting.php @@ -0,0 +1,2645 @@ + + +
+
+

+

+ +

+
+ +
+
+
+ + + +
+

+

+
+
+
+ + + +
+

+

+
+
+
+ + + +
+

+

+
+
+
+ + + +
+

+

+
+
+
+ + + +
+
+

+

+
+ +
+
+ + + + +
+
+

+

+
+
+ +
+
+ + + + +
+
+

+

+
+
+
+ + + +
+
+
+

+
+ +
+
+ __('Enable or Disable Debug Mode', 'hesabix'), + 'id' => 'hesabix_debug_mode_checkbox', + 'default' => 'no', + 'type' => 'checkbox', + ); + + return $fields; + } + + public static function hesabix_extra_setting() + { + ?> +
+
+ + + + +
+

+

+ db_version(); + $max_execution_time = ini_get('max_execution_time'); + $memory_limit = ini_get('memory_limit'); + $upload_max_filesize = ini_get('upload_max_filesize'); + $post_max_size = ini_get('post_max_size'); + + $is_connected = get_option('hesabix_account_api') ? true : false; + $connection_status = $is_connected ? __('Connected', 'hesabix') : __('Disconnected', 'hesabix'); + $connection_color = $is_connected ? 'white' : 'white'; + + $business_info = array(); + if ($is_connected) { + try { + $subscription_info = self::getSubscriptionInfo(); + if (!empty($subscription_info['businessName'])) { + $business_info = $subscription_info; + } + } catch (Exception $e) { + } + } + ?> +
+
+
+
+ + + +
+
+ +
+
+ +
+
+
+
+ + +
+
+ + + + +
+ +
+ + +
+ +
+
+ +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+
+ + + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+ +
+ init($hesabi_setting_fields); ?> +
+
+ + + +
+
+ + + +
+ +
+
+ +
+ +
+ + save_fields($fields); + } + + public static function hesabix_catalog_setting_fields() + { + $warehouses = Hesabix_Setting::hesabix_get_warehouses(); + + $fields[] = array( + 'title' => __('Catalog Settings', 'hesabix'), + 'type' => 'title', + 'desc' => '', + 'id' => 'catalog_options' + ); + + $fields[] = array( + 'title' => __('Update Price', 'hesabix'), + 'desc' => __('Update Price after change in Hesabix', 'hesabix'), + 'id' => 'hesabix_item_update_price', + 'default' => 'no', + 'type' => 'checkbox' + ); + + $fields[] = array( + 'title' => __('Update Quantity', 'hesabix'), + 'desc' => __('Update Quantity after change in Hesabix', 'hesabix'), + 'id' => 'hesabix_item_update_quantity', + 'default' => 'no', + 'type' => 'checkbox' + ); + + // $fields[] = array( + // 'title' => __("Update product's quantity based on", 'hesabix'), + // 'id' => 'hesabix_item_update_quantity_based_on', + // 'type' => 'select', + // 'options' => $warehouses, + // ); + + $fields[] = array( + 'title' => "", + 'desc' => __('Remove The Titles for Attributes When Saving Product To Hesabix', 'hesabix'), + 'id' => 'hesabix_remove_attributes_titles', + 'default' => 'no', + 'type' => 'checkbox' + ); + + $fields[] = array( + 'title' => "", + 'desc' => __('Do not update purchase and sales titles in hesabix', 'hesabix'), + 'id' => 'hesabix_do_not_update_titles_in_hesabix', + 'default' => 'no', + 'type' => 'checkbox' + ); + + $fields[] = array( + 'title' => "", + 'desc' => __('Do not submit product in Hesabix automatically by saving product in woocommerce', 'hesabix'), + 'id' => 'hesabix_do_not_submit_product_automatically', + 'default' => 'no', + 'type' => 'checkbox' + ); + + $fields[] = array( + 'title' => "", + 'desc' => __('Do not update product price in Hesabix by editing product in woocommerce', 'hesabix'), + 'id' => 'hesabix_do_not_update_product_price_in_hesabix', + 'default' => 'no', + 'type' => 'checkbox' + ); + + $fields[] = array( + 'title' => "", + 'desc' => __('Do not update product barcode in Hesabix by saving product in woocommerce', 'hesabix'), + 'id' => 'hesabix_do_not_update_product_barcode_in_hesabix', + 'default' => 'no', + 'type' => 'checkbox' + ); + + $fields[] = array( + 'title' => "", + 'desc' => __('Do not update product category in Hesabix by saving product in woocommerce', 'hesabix'), + 'id' => 'hesabix_do_not_update_product_category_in_hesabix', + 'default' => 'no', + 'type' => 'checkbox' + ); + + $fields[] = array( + 'title' => "", + 'desc' => __('Do not update product code in Hesabix by saving product in woocommerce', 'hesabix'), + 'id' => 'hesabix_do_not_update_product_product_code_in_hesabix', + 'default' => 'no', + 'type' => 'checkbox' + ); + + $fields[] = array( + 'title' => "", + 'desc' => __('Show Hesabix ID in Products Page', 'hesabix'), + 'id' => 'hesabix_show_product_code_in_products_page', + 'default' => 'no', + 'type' => 'checkbox' + ); + + $fields[] = array( + 'title' => "", + 'desc' => __('Show Hesabix Code in Woocommerce Excel Export', 'hesabix'), + 'id' => 'hesabix_show_hesabix_code_in_excel_export', + 'default' => 'no', + 'type' => 'checkbox' + ); + + $fields[] = array( + 'title' => "", + 'desc' => __('Set Special Sale as Discount in invoice', 'hesabix'), + 'id' => 'hesabix_set_special_sale_as_discount', + 'default' => 'no', + 'type' => 'checkbox' + ); + + $options_to_update_sale_price = array(); + $options_to_update_sale_price[0] = __("The Sale price does not change", 'hesabix'); + $options_to_update_sale_price[1] = __("The Sale price gets removed", 'hesabix'); + $options_to_update_sale_price[2] = __("The sale price get changes in proportion to the regular price", 'hesabix'); + + $fields[] = array( + 'title' => __("Update sale price", 'hesabix'), + 'id' => 'hesabix_item_update_sale_price', + 'type' => 'select', + 'options' => $options_to_update_sale_price, + ); + + $fields[] = array('type' => 'sectionend', 'id' => 'catalog_options'); + + return $fields; + } + + public static function hesabix_catalog_setting() + { + $hesabi_setting_fields = self::hesabix_catalog_setting_fields(); + $Html_output = new Hesabix_Html_output(); + ?> +
+
+

+

+ +

+
+
+ + +
+ init($hesabi_setting_fields); ?> +
+
+ +
+
+
+ save_fields($hesabi_setting_fields); + } + + public static function hesabix_customers_setting_fields() + { + + $fields[] = array( + 'title' => __('Customers Settings', 'hesabix'), + 'type' => 'title', + 'desc' => '', + 'id' => 'customer_options' + ); + + $fields[] = array( + 'title' => __('Update Customer Address', 'hesabix'), + 'desc' => __('Choose when update Customer address in Hesabix.', 'hesabix'), + 'id' => 'hesabix_contact_address_status', + 'type' => 'select', + 'options' => array( + '1' => __('Use first customer address', 'hesabix'), + '2' => __('update address with Invoice address', 'hesabix'), + '3' => __('update address with Delivery address', 'hesabix') + ), + ); + + $fields[] = array( + 'title' => __('Customer\'s Group', 'hesabix'), + 'desc' => __('Enter a Customer\'s Group in Hesabix', 'hesabix'), + 'id' => 'hesabix_contact_node_family', + 'type' => 'text', + 'default' => 'مشتریان فروشگاه آنلاین' + ); + + $fields[] = array( + 'title' => __('Save Customer\'s group', 'hesabix'), + 'desc' => __('Automatically save Customer\'s group in hesabix', 'hesabix'), + 'id' => 'hesabix_contact_automatic_save_node_family', + 'default' => 'yes', + 'type' => 'checkbox' + ); + $fields[] = array( + 'title' => __('Customer\'s detail auto save and update', 'hesabix'), + 'desc' => __('Save and update Customer\'s detail automatically in hesabix', 'hesabix'), + 'id' => 'hesabix_contact_automatically_save_in_hesabix', + 'type' => 'checkbox', + 'default' => 'yes' + ); + + $fields[] = array('type' => 'sectionend', 'id' => 'customer_options'); + + return $fields; + } + + public static function hesabix_customers_setting() + { + $hesabi_setting_fields = self::hesabix_customers_setting_fields(); + + $add_fields = get_option('hesabix_contact_add_fields', '1'); + $nationalCodeCheck = get_option('hesabix_contact_NationalCode_checkbox_hesabix') == 'yes'; + $economicCodeCheck = get_option('hesabix_contact_EconomicCode_checkbox_hesabix') == 'yes'; + $registrationNumberCheck = get_option('hesabix_contact_RegistrationNumber_checkbox_hesabix') == 'yes'; + $websiteCheck = get_option('hesabix_contact_Website_checkbox_hesabix') == 'yes'; + + $nationalCodeRequired = get_option('hesabix_contact_NationalCode_isRequired_hesabix') == 'yes'; + $economicCodeRequired = get_option('hesabix_contact_EconomicCode_isRequired_hesabix') == 'yes'; + $registrationNumberRequired = get_option('hesabix_contact_RegistrationNumber_isRequired_hesabix') == 'yes'; + $websiteRequired = get_option('hesabix_contact_Website_isRequired_hesabix') == 'yes'; + + $nationalCodeMetaName = get_option('hesabix_contact_NationalCode_text_hesabix', null); + $economicCodeMetaName = get_option('hesabix_contact_EconomicCode_text_hesabix', null); + $registrationNumberMetaName = get_option('hesabix_contact_RegistrationNumber_text_hesabix', null); + $websiteMetaName = get_option('hesabix_contact_Website_text_hesabix', null); + + $Html_output = new Hesabix_Html_output(); + ?> + +
+
+

+

+ +

+
+ +
+ +
+
+
+ init($hesabi_setting_fields); ?> + +
+ +
+
+
+ +
+

+

+ +

+ +
+ +
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+
+ +
+ +
+
+
+ __('Invoice Settings', 'hesabix'), + 'type' => 'title', + 'desc' => '', + 'id' => 'invoice_options' + ); + + $fields[] = array( + 'title' => __('Add invoice in which status', 'hesabix'), + 'id' => 'hesabix_invoice_status', + 'type' => 'custom_status_selector', + 'options' => array( + 'pending' => __('Pending payment', 'hesabix'), + 'processing' => __('Processing', 'hesabix'), + 'on-hold' => __('On hold', 'hesabix'), + 'completed' => __('Completed', 'hesabix'), + 'cancelled' => __('Cancelled', 'hesabix'), + 'refunded' => __('Refunded', 'hesabix'), + 'failed' => __('Failed', 'hesabix'), + 'checkout-draft' => __('Draft', 'hesabix'), + ), + ); + + $fields[] = array( + 'title' => __('Save Shipping Costs', 'hesabix'), + 'id' => 'hesabix_invoice_freight', + 'type' => 'freight_switch', + 'options' => [ + 'disabled' => __("Don't Save", 'hesabix'), + 0 => __("Save as Freight", 'hesabix'), + 1 => __("Save as Service", 'hesabix') + ], + 'desc' => __('Choose how shipping costs should be handled in invoices', 'hesabix'), + ); + + $fields[] = array( + 'title' => __('Service Code For Freight', 'hesabix'), + 'id' => 'hesabix_invoice_freight_code', + 'type' => 'text', + 'placeholder' => __('Enter Freight Service Code', 'hesabix'), + 'desc' => __('Required when "Save as Service" is selected. Create this service in Hesabix first.', 'hesabix'), + ); + + if (is_plugin_active('dokan-lite/dokan.php')) { + $fields[] = array( + 'title' => __("Submit invoice base on Dokan orders", 'hesabix'), + 'id' => 'hesabix_invoice_dokan', + 'type' => 'radio', + 'options' => [ + 0 => __("Inactive", 'hesabix'), + 1 => __("Submit parent order", 'hesabix'), + 2 => __("Submit children orders", 'hesabix') + ], + 'default' => 0 + ); + } + + $fields[] = array('type' => 'sectionend', 'id' => 'invoice_options'); + + return $fields; + } + public static function hesabix_invoice_setting() + { + $hesabi_setting_fields = self::hesabix_invoice_setting_fields(); + $Html_output = new Hesabix_Html_output(); + ?> + +
+
+

+

+ +

+
+ +
+
+
+ + + +

+
+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+
+
+ +
+
+
+ init($hesabi_setting_fields); ?> + +
+ +
+
+
+
+ + + + alert("کد خدمت حمل و نقل تعریف نشده است");'; + } + ?> + __('API Settings', 'hesabix'), + 'type' => 'title', + 'desc' => '', + 'id' => 'api_options' + ); + + $fields[] = array( + 'title' => __('API Key', 'hesabix'), + 'desc' => __('Find API key in Setting->Access Tokens Menu', 'hesabix'), + 'id' => 'hesabix_account_api', + 'type' => 'text', + ); + + $fields[] = array( + 'title' => __('API Address', 'hesabix'), + 'id' => 'hesabix_api_address', + 'type' => 'select', + 'options' => array( + "0" => "app.hesabix.ir", + "1" => "next.hesabix.ir", + "2" => "hesabix.dragonizzer.ir", + "custom" => __("Custom Address", 'hesabix') + ) + ); + + $fields[] = array( + 'title' => __('Custom API Address', 'hesabix'), + 'desc' => __('Enter your custom API address (e.g., your-domain.com)', 'hesabix'), + 'id' => 'hesabix_custom_api_address', + 'type' => 'text', + 'class' => 'custom-api-address-field' + ); + $fields[] = array('type' => 'sectionend', 'id' => 'api_options'); + + return $fields; + } + public static function hesabix_api_setting() + { + $businessInfo = self::getSubscriptionInfo(); + $isBusinessInfo = false; + if ($businessInfo["expireDate"] != '' && $businessInfo["expireDate"] != null) { + $isBusinessInfo = true; + $expireDate = strtotime($businessInfo["expireDate"]); + $expireDateStr = date("Y/m/d", $expireDate); + } + + $hesabi_setting_fields = self::hesabix_api_setting_fields(); + $Html_output = new Hesabix_Html_output(); + ?> + +
+
+

+

+ +

+
+ + +
+

+
+
+
+ + + +
+

+

+
+ +
+
+ + + +
+

+

+
+ +
+
+ + + +
+

+

+
+ +
+
+ + + +
+

+

+
+
+
+ + +
+ + +
+
+ + + + +
+
+
    +
  • +
  • +
  • +
  • +
  • API Settings in Hesabix.', 'hesabix'); ?> +
  • +
  • +
  • +
+
+
+ +
+ init($hesabi_setting_fields); ?> +
+ + +
+
+
+ +
+
+ + + + +
+
+

+

+
+
+
+ save_fields($hesabi_setting_fields); + $api_key = get_option('hesabix_account_api'); + if (!empty($api_key)) { + Hesabix_Setting::hesabix_set_webhook(); + } + } + public static function hesabix_export_setting() + { + $productExportResult = (isset($_GET['productExportResult'])) ? wc_clean($_GET['productExportResult']) : null; + $productImportResult = (isset($_GET['productImportResult'])) ? wc_clean($_GET['productImportResult']) : null; + $error = (isset($_GET['error'])) ? wc_clean($_GET['error']) : null; + + if (!is_null($productExportResult) && $productExportResult === 'true') { + $processed = (isset($_GET['processed'])) ? wc_clean($_GET['processed']) : null; + if ($processed == 0) { + echo '
'; + echo '

' . __('No products were exported, All products were exported or there are no product', 'hesabix'); + echo '

'; + } else { + echo '
'; + echo '

' . sprintf(__('Export products completed. %s products added/updated.', 'hesabix'), $processed); + echo '

'; + } + } elseif ($productExportResult === 'false') { + if (!is_null($error) && $error === '-1') { + echo '
'; + echo '

' . __('Export products fail. Hesabix has already contained products.', 'hesabix'); + echo '

'; + } else { + echo '
'; + echo '

' . __('Export products fail. Please check the log file.', 'hesabix'); + echo '

'; + } + } + + if (!is_null($productImportResult) && $productImportResult === 'true') { + $processed = (isset($_GET['processed'])) ? wc_clean($_GET['processed']) : null; + if ($processed == 0) { + echo '
'; + echo '

' . __('No products were imported, All products were imported or there are no product', 'hesabix'); + echo '

'; + } else { + echo '
'; + echo '

' . sprintf(__('Import products completed. %s products added/updated.', 'hesabix'), $processed); + echo '

'; + } + } elseif ($productImportResult === 'false') { + echo '
'; + echo '

' . __('Import products fail. Please check the log file.', 'hesabix'); + echo '

'; + } + $productOpeningQuantityExportResult = (isset($_GET['productOpeningQuantityExportResult'])) ? wc_clean($_GET['productOpeningQuantityExportResult']) : null; + if (!is_null($productOpeningQuantityExportResult) && $productOpeningQuantityExportResult === 'true') { + echo '
'; + echo '

' . __('Export product opening quantity completed.', 'hesabix'); + echo '

'; + } elseif (!is_null($productOpeningQuantityExportResult) && $productOpeningQuantityExportResult === 'false') { + $shareholderError = (isset($_GET['shareholderError'])) ? wc_clean($_GET['shareholderError']) : null; + $noProduct = (isset($_GET['noProduct'])) ? wc_clean($_GET['noProduct']) : null; + if ($shareholderError == 'true') { + echo '
'; + echo '

' . __('Export product opening quantity fail. No Shareholder exists, Please define Shareholder in Hesabix', 'hesabix'); + echo '

'; + } elseif ($noProduct == 'true') { + echo '
'; + echo '

' . __('No product available for Export product opening quantity.', 'hesabix'); + echo '

'; + } else { + echo '
'; + echo '

' . __('Export product opening quantity fail. Please check the log file.', 'hesabix'); + echo '

'; + } + } + $customerExportResult = (isset($_GET['customerExportResult'])) ? wc_clean($_GET['customerExportResult']) : null; + + if (!is_null($customerExportResult) && $customerExportResult === 'true') { + $processed = (isset($_GET['processed'])) ? wc_clean($_GET['processed']) : null; + if ($processed == 0) { + echo '
'; + echo '

' . __('No customers were exported, All customers were exported or there are no customer', 'hesabix'); + echo '

'; + } else { + echo '
'; + echo '

' . sprintf(__('Export customers completed. %s customers added.', 'hesabix'), $processed); + echo '

'; + } + } elseif (!is_null($customerExportResult) && $customerExportResult === 'false') { + if (!is_null($error) && $error === '-1') { + echo '
'; + echo '

' . __('Export customers fail. Hesabix has already contained customers.', 'hesabix'); + echo '

'; + } else { + echo '
'; + echo '

' . __('Export customers fail. Please check the log file.', 'hesabix'); + echo '

'; + } + } + + ?> +
+

+
+
+
+
+
+ +
+ +
+
+

+ +

+
+
+
+
+ +
    +
  • با انجام این عملیات محصولات لینک نشده از فروشگاه وارد حسابیکس می شوند.
  • +
  • اگر محصولات از قبل هم در فروشگاه تعریف شده اند و هم در حسابیکس و به هم لینک نشده اند باید از + گزینه + همسان سازی دستی محصولات استفاده کنید. +
  • +
  • با انجام این عملیات موجودی محصولات وارد حسابیکس نمی شود و برای وارد کردن موجودی محصولات + فروشگاه + در حسابیکس، باید از گزینه استخراج موجودی اول دوره استفاده کنید. +
  • +
+
+
+
+ +
+
+
+ +
+ +
+
+

+ +

+
+
+
+
+ +
    +
  • با انجام این عملیات موجودی کنونی محصولات در فروشگاه بعنوان موجودی اول دوره محصولات در حسابیکس + ثبت می شوند. +
  • +
  • بطور کلی فقط یک بار باید از این گزینه استفاده کنید، + که این کار باید پس از خروج محصولات به حسابیکس و یا پس از همسان سازی دستی تمام محصولات + انجام شود. +
  • +
+
+
+
+ +
+
+
+ +
+ +
+
+

+ +

+
+
+
+
+ +
    +
  • با انجام این عملیات مشتریان لینک نشده از فروشگاه وارد حسابیکس می شوند.
  • +
  • + اگر یک مشتری بیش از یک بار وارد حسابیکس شده است می توانید از گزینه ادغام تراکنش ها در حسابیکس + استفاده کنید. +
  • +
+
+
+
+ +
+
+
+ +
+ +
+
+

+ +

+
+
+
+
+ +
    +
  • با انجام این عملیات محصولات لینک نشده از حسابیکس وارد فروشگاه می شوند.
  • +
  • اگر محصولات از قبل هم در فروشگاه تعریف شده اند و هم در حسابیکس و به هم لینک نشده اند باید از + گزینه + همسان سازی دستی محصولات استفاده کنید. +
  • +
  • محصولات در وضعیت خصوصی وارد فروشگاه می شوند و سپس هر زمان مایل بودید می توانید وضعیت را به + منتشر شده تغییر دهید. +
  • +
  • تمامی محصولات بعنوان محصول ساده (و نه متغیر) وارد فروشگاه می شوند.
  • +
+
+
+
+ +
+
+ + + + +
+

+ +

+
+
+
+ + + +
+

+

+
+
+
+ + + +
+

+

+
+
+
+ + + + + +
+

+

+
+
+
+ +
+

+ +

+
+
+ +
+
+ +
+
+
+
+

+ +

+
+
+ + + + + +
+
+ +
+
+
+
+

+
+ +
+
+ +
+ + + + +
+
+ + + + +
+ +
+ +
+
+
+ +
+
+
+

+

+
+
+ +
+
+ +
+
+
+
+

+ +

+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+

+
+
+ + + $storeProductsCount, + "hesabixProductsCount" => $hesabixProductsCount, + "linkedProductsCount" => $linkedProductsCount + ); + } + public static function getProductCountsInHesabix() + { + $hesabix = new Hesabix_Api(); + + $filters = array(array("Property" => "khadamat", "Operator" => "=", "Value" => 0)); + + $response = $hesabix->itemGetItems(array('Filters' => $filters)); + if ($response->Success) { + return $response->data->FilteredCount; + } else { + return 0; + } + } + public static function getLinkedProductsCount() + { + global $wpdb; + + return $wpdb->get_var( + $wpdb->prepare( + "SELECT COUNT(*) FROM {$wpdb->prefix}hesabix WHERE obj_type = 'product'" + ) + ); + } + public static function getProductCountsInStore() + { + if (!function_exists('wc_get_products')) { + return 0; + } + + $args = array( + 'limit' => -1, + 'status' => array('publish', 'private', 'draft'), + 'return' => 'ids', + ); + + $products = wc_get_products($args); + return count($products); + } + + public static function getCustomersCount() + { + if (!class_exists('WP_User_Query')) { + return 0; + } + + $args = array( + 'fields' => 'ID', + 'number' => -1, + ); + + $user_query = new WP_User_Query($args); + return $user_query->get_total(); + } + + public static function getOrdersCount() + { + if (!function_exists('wc_get_orders')) { + return 0; + } + + $args = array( + 'limit' => -1, + 'return' => 'ids', + ); + + $orders = wc_get_orders($args); + return count($orders); + } + public static function getSubscriptionInfo() + { + $businessName = ''; + $credit = ''; + $expireDate = ''; + $plan = ''; + + $hesabix = new Hesabix_Api(); + $response = $hesabix->settingGetSubscriptionInfo(); + + if (isset($response->Success) && $response->Success && isset($response->Result)) { + $businessName = $response->Result->name ?? 'نامشخص'; + $credit = $response->Result->credit ?? 0; + $expireDate = $response->Result->expireDate ?? null; + $plan = $response->Result->subscription ?? 'ندارد'; + } + + return array( + "businessName" => $businessName, + "credit" => $credit, + "expireDate" => $expireDate, + "plan" => $plan + ); + } + public static function hesabix_set_webhook($show_errors = true) + { + $url = get_site_url() . '/index.php?hesabix_webhook=1&token=' . substr(wp_hash(AUTH_KEY . 'hesabix/webhook'), 0, 10); + + $hookPassword = get_option('hesabix_webhook_password'); + + $hesabix_api = new Hesabix_Api(); + $response = $hesabix_api->settingSetChangeHook($url, $hookPassword); + + if (is_object($response)) { + if ($response->Success) { + update_option('hesabix_live_mode', 1); + update_option('hesabix_account_bid', $response->bid); + update_option('hesabix_account_year', $response->year); + + + if (Hesabix_Admin_Functions::isDateInFiscalYear(date('Y-m-d H:i:s')) === 0) { + if ($show_errors) { + echo '
'; + echo '

' . __('The fiscal year has passed or not arrived. Please check the fiscal year settings in Hesabix.', 'hesabix') . '

'; + echo '
'; + } + update_option('hesabix_live_mode', 0); + } + + + $default_currency = $hesabix_api->settingGetCurrency(); + if ($default_currency->Success) { + + $woocommerce_currency = get_woocommerce_currency(); + $hesabix_currency = $default_currency->Result->moneyName; + if ($hesabix_currency == $woocommerce_currency || ($hesabix_currency == 'IRR' && $woocommerce_currency == 'IRT') || ($hesabix_currency == 'IRT' && $woocommerce_currency == 'IRR')) { + update_option('hesabix_hesabix_default_currency', $hesabix_currency); + } else { + update_option('hesabix_hesabix_default_currency', 0); + update_option('hesabix_live_mode', 0); + + if ($show_errors) { + echo '
'; + echo '

' . __('Hesabix and WooCommerce default currency must be same.', 'hesabix'); + echo '

'; + } + } + } else { + if ($show_errors) { + echo '
'; + echo '

' . __('Cannot check the Hesabix default currency. Error Message: ', 'hesabix') . $default_currency->ErrorMessage . '

'; + echo '
'; + } + HesabixLogService::log(array("Cannot check the Hesabix default currency. Error Message: $default_currency->ErrorMessage. Error Code: $default_currency->ErrorCode")); + } + + + if (get_option('hesabix_live_mode') && $show_errors) { + echo '
'; + echo '

' . __('API Setting updated. Test Successfully', 'hesabix') . '

'; + echo '
'; + } + } else { + update_option('hesabix_live_mode', 0); + + if ($response->ErrorCode === 108) { + if ($show_errors) { + echo '
'; + echo '

' . __('Cannot connect to Hesabix. Business expired.', 'hesabix') . $response->ErrorMessage . '

'; + echo '
'; + } + update_option('hesabix_business_expired', 1); + } else { + if ($show_errors) { + echo '
'; + echo '

' . __('Cannot set Hesabix webHook. Error Message:', 'hesabix') . $response->ErrorMessage . '

'; + echo '
'; + } + update_option('hesabix_business_expired', 0); + } + + HesabixLogService::log(array("Cannot set Hesabix webHook. Error Message: $response->ErrorMessage. Error Code: $response->ErrorCode")); + } + } else { + update_option('hesabix_live_mode', 0); + + if ($show_errors) { + echo '
'; + echo '

' . __('Cannot connect to Hesabix servers. Please check your Internet connection', 'hesabix') . '

'; + echo '
'; + } + + HesabixLogService::log(array("Cannot connect to hesabix servers. Check your internet connection")); + } + + return $response; + } + + public static function hesabix_get_banks() + { + $hesabix_api = new Hesabix_Api(); + $banks = $hesabix_api->settingGetBanks(); + + if (is_object($banks) && $banks->Success) { + $available_banks = array(); + $available_banks[-1] = __('Choose', 'hesabix'); + foreach ($banks->Result as $bank) { + if ($bank->Currency == get_woocommerce_currency() || (get_woocommerce_currency() == 'IRT' && $bank->Currency == 'IRR') || (get_woocommerce_currency() == 'IRR' && $bank->Currency == 'IRT')) { + $available_banks['bank' . $bank->Code] = $bank->Name . ' - ' . $bank->Branch . ' - ' . $bank->AccountNumber; + } + } + + if (empty($available_banks)) { + $available_banks[0] = __('Define at least one bank in Hesabix', 'hesabix'); + } + + return $available_banks; + } else { + update_option('hesabix_live_mode', 0); + + echo '
'; + echo '

' . __('Cannot get Banks detail.', 'hesabix') . '

'; + echo '
'; + + HesabixLogService::log(array("Cannot get banking information. Error Code: $banks->ErrorCode. Error Message: $banks->ErrorMessage.")); + + return array('0' => __('Cannot get Banks detail.', 'hesabix')); + } + } + + public static function hesabix_get_cashes() + { + $hesabix_api = new Hesabix_Api(); + $cashes = $hesabix_api->settingGetCashes(); + + if (is_object($cashes) && $cashes->Success) { + $available_cashes = array(); + foreach ($cashes->Result as $cash) { + if ($cash->Currency == get_woocommerce_currency() || (get_woocommerce_currency() == 'IRT' && $cash->Currency == 'IRR') || (get_woocommerce_currency() == 'IRR' && $cash->Currency == 'IRT')) { + $available_cashes['cash' . $cash->Code] = $cash->Name; + } + } + return $available_cashes; + } + } + + public static function hesabix_get_projects() + { + $hesabix_api = new Hesabix_Api(); + $projects = $hesabix_api->settingGetProjects(); + + if (is_object($projects) && $projects->Success) { + $available_projects = array(); + $available_projects[-1] = __('Choose', 'hesabix'); + foreach ($projects->data as $project) { + $available_projects[$project->id] = $project->name; + } + + return $available_projects; + } else { + update_option('hesabix_live_mode', 0); + echo '
'; + echo '

' . __('Cannot get Projects detail.', 'hesabix') . '

'; + echo '
'; + HesabixLogService::log(array("Cannot get projects information. Error Code:$projects->ErrorCode. Error Message: $projects->ErrorMessage.")); + + return array('0' => __('Cannot get projects detail.', 'hesabix')); + } + } + + public static function hesabix_get_salesmen() + { + $hesabix_api = new Hesabix_Api(); + $salesmen = $hesabix_api->settingGetSalesmen(); + + if (is_object($salesmen) && $salesmen->Success) { + $available_salesmen = array(); + $available_salesmen[-1] = __('Choose', 'hesabix'); + foreach ($salesmen->result as $salesman) { + $available_salesmen[$salesman->code] = $salesman->nikename; + } + + return $available_salesmen; + } else { + update_option('hesabix_live_mode', 0); + echo '
'; + echo '

' . __('Cannot get Salesmen detail.', 'hesabix') . '

'; + echo '
'; + HesabixLogService::log(array("Cannot get salesmen information. Error Code: $salesmen->ErrorCode Error Message: .$salesmen->ErrorMessage.")); + + return array('0' => __('Cannot get salesmen detail.', 'hesabix')); + } + } + + public static function hesabix_log_setting() + { + $cleanLogResult = (isset($_GET['cleanLogResult'])) ? wc_clean($_GET['cleanLogResult']) : null; + + if (!is_null($cleanLogResult) && $cleanLogResult === 'true') { + echo '
'; + echo '

' . __('The log file was cleared.', 'hesabix') . '

'; + echo '
'; + } elseif ($cleanLogResult === 'false') { + echo '
'; + echo '

' . __('Log file not found.', 'hesabix') . '

'; + echo '
'; + } + + self::hesabix_tab_log_html(); + } + + public static function hesabix_tab_log_html() + { + $logFiles = []; + for ($i = 0; $i < 10; $i++) { + $logDate = date("20y-m-d", strtotime(-$i . "day")); + if (file_exists(WP_CONTENT_DIR . '/hesabix-' . $logDate . '.txt')) { + $logFiles[] = $logDate; + } + } + $hasLogs = count($logFiles) > 0; + $defaultLogDate = $hasLogs ? $logFiles[0] : date("20y-m-d"); + $defaultLogFile = WP_CONTENT_DIR . '/hesabix-' . $defaultLogDate . '.txt'; + $logFileContent = ($hasLogs && file_exists($defaultLogFile)) ? file_get_contents($defaultLogFile) : ''; + ?> +
+
+
+ + + +

+
+
    +
  • +
  • +
  • +
  • +
  • +
  • +
+
+

+

+
+ + > + + + + + + +
+
+
+

:

+
+ $logDate) { + $isActive = ($idx === 0) ? ' active' : ''; + echo ''; + } + } else { + echo '' . __('No logs found.', 'hesabix') . ''; + } ?> +
+
+ +
+

:

+ +
+
+ + settingGetWarehouses(); + + if (is_object($warehouses->data)) { + $available_warehouses = array(); + $available_warehouses[-1] = __('Accounting quantity (Total inventory)', 'hesabix'); + + return $available_warehouses; + } + + if (is_object($warehouses) && $warehouses->Success) { + $available_warehouses = array(); + $available_warehouses[-1] = __('Accounting quantity (Total inventory)', 'hesabix'); + foreach ($warehouses->data as $warehouse) { + $available_warehouses[$warehouse->code] = $warehouse->name; + } + + return $available_warehouses; + } else { + update_option('hesabix_live_mode', 0); + echo '
'; + echo '

' . __('Cannot get warehouses.', 'hesabix') . '

'; + echo '
'; + HesabixLogService::log(array("Cannot get warehouses. Error Code: $warehouses->ErrorCode. Error Message: .$warehouses->ErrorMessage.")); + + return array('0' => __('Cannot get warehouses.', 'hesabix')); + } + } + +} + +Hesabix_Setting::init(); + +add_action('wp_ajax_hesabix_save_catalog_settings_ajax', function () { + + if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error(array('message' => 'Security check failed')); + return; + } + + + + + $fields_to_save = array( + 'hesabix_item_update_price' => isset($_POST['hesabix_item_update_price']) ? 'yes' : 'no', + 'hesabix_item_update_quantity' => isset($_POST['hesabix_item_update_quantity']) ? 'yes' : 'no', + 'hesabix_item_update_quantity_based_on' => isset($_POST['hesabix_item_update_quantity_based_on']) ? sanitize_text_field($_POST['hesabix_item_update_quantity_based_on']) : '', + 'hesabix_remove_attributes_titles' => isset($_POST['hesabix_remove_attributes_titles']) ? 'yes' : 'no', + 'hesabix_do_not_update_titles_in_hesabix' => isset($_POST['hesabix_do_not_update_titles_in_hesabix']) ? 'yes' : 'no', + 'hesabix_do_not_submit_product_automatically' => isset($_POST['hesabix_do_not_submit_product_automatically']) ? 'yes' : 'no', + 'hesabix_do_not_update_product_price_in_hesabix' => isset($_POST['hesabix_do_not_update_product_price_in_hesabix']) ? 'yes' : 'no', + 'hesabix_do_not_update_product_barcode_in_hesabix' => isset($_POST['hesabix_do_not_update_product_barcode_in_hesabix']) ? 'yes' : 'no', + 'hesabix_do_not_update_product_category_in_hesabix' => isset($_POST['hesabix_do_not_update_product_category_in_hesabix']) ? 'yes' : 'no', + 'hesabix_do_not_update_product_product_code_in_hesabix' => isset($_POST['hesabix_do_not_update_product_product_code_in_hesabix']) ? 'yes' : 'no', + 'hesabix_show_product_code_in_products_page' => isset($_POST['hesabix_show_product_code_in_products_page']) ? 'yes' : 'no', + 'hesabix_show_hesabix_code_in_excel_export' => isset($_POST['hesabix_show_hesabix_code_in_excel_export']) ? 'yes' : 'no', + 'hesabix_set_special_sale_as_discount' => isset($_POST['hesabix_set_special_sale_as_discount']) ? 'yes' : 'no', + 'hesabix_item_update_sale_price' => isset($_POST['hesabix_item_update_sale_price']) ? sanitize_text_field($_POST['hesabix_item_update_sale_price']) : '' + ); + + $success = true; + foreach ($fields_to_save as $option_name => $option_value) { + $result = update_option($option_name, $option_value); + if (!$result && get_option($option_name) !== $option_value) { + $success = false; + } + } + + if ($success) { + wp_send_json_success(array('message' => __('Settings saved successfully', 'hesabix'), 'options' => $fields_to_save)); + } else { + wp_send_json_error(array('message' => __('Failed to save settings', 'hesabix'))); + } +}); + +add_action('wp_ajax_hesabix_get_log_file_ajax', function () { + if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error(array('message' => 'Security check failed')); + return; + } + $log_date = isset($_POST['log_date']) ? sanitize_text_field($_POST['log_date']) : ''; + $file = WP_CONTENT_DIR . '/hesabix-' . $log_date . '.txt'; + if (file_exists($file)) { + $content = file_get_contents($file); + wp_send_json_success($content); + } else { + wp_send_json_error(); + } +}); + +add_action('wp_ajax_hesabix_delete_log_file_ajax', function () { + if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error(array('message' => 'Security check failed')); + return; + } + $log_date = isset($_POST['log_date']) ? sanitize_text_field($_POST['log_date']) : ''; + $file = WP_CONTENT_DIR . '/hesabix-' . $log_date . '.txt'; + if (file_exists($file) && unlink($file)) { + wp_send_json_success(); + } else { + wp_send_json_error(); + } +}); + +add_action('wp_ajax_hesabix_delete_all_logs_ajax', function () { + if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error(array('message' => 'Security check failed')); + return; + } + $prefix = WP_CONTENT_DIR . '/hesabix-'; + $files = glob($prefix . '*'); + $success = true; + if ($files) { + foreach ($files as $file) { + if (is_file($file)) { + if (!unlink($file)) { + $success = false; + } + } + } + } + if ($success) { + wp_send_json_success(); + } else { + wp_send_json_error(); + } +}); + +add_action('wp_ajax_hesabix_save_extra_settings_ajax', function () { + + if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error(array('message' => 'Security check failed')); + return; + } + + + $fields_to_save = array( + 'hesabix_debug_mode_checkbox' => isset($_POST['hesabix_debug_mode_checkbox']) ? 'yes' : 'no', + 'hesabix_set_rpp_for_sync_products_into_hesabix' => isset($_POST['hesabix_set_rpp_for_sync_products_into_hesabix']) ? sanitize_text_field($_POST['hesabix_set_rpp_for_sync_products_into_hesabix']) : '', + 'hesabix_set_rpp_for_sync_products_into_woocommerce' => isset($_POST['hesabix_set_rpp_for_sync_products_into_woocommerce']) ? sanitize_text_field($_POST['hesabix_set_rpp_for_sync_products_into_woocommerce']) : '', + 'hesabix_set_rpp_for_import_products' => isset($_POST['hesabix_set_rpp_for_import_products']) ? sanitize_text_field($_POST['hesabix_set_rpp_for_import_products']) : '', + 'hesabix_set_rpp_for_export_products' => isset($_POST['hesabix_set_rpp_for_export_products']) ? sanitize_text_field($_POST['hesabix_set_rpp_for_export_products']) : '', + 'hesabix_set_rpp_for_export_opening_products' => isset($_POST['hesabix_set_rpp_for_export_opening_products']) ? sanitize_text_field($_POST['hesabix_set_rpp_for_export_opening_products']) : '' + ); + + $success = true; + foreach ($fields_to_save as $option_name => $option_value) { + $result = update_option($option_name, $option_value); + if (!$result && get_option($option_name) !== $option_value) { + $success = false; + } + } + + if ($success) { + wp_send_json_success(array('message' => __('Settings saved successfully', 'hesabix'))); + } else { + wp_send_json_error(array('message' => __('Failed to save settings', 'hesabix'))); + } +}); + +add_action('wp_ajax_hesabix_save_invoice_settings_ajax', function () { + + if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error(array('message' => 'Security check failed')); + return; + } + + + $fields_to_save = array( + 'hesabix_invoice_status' => isset($_POST['hesabix_invoice_status']) ? sanitize_text_field($_POST['hesabix_invoice_status']) : '', + 'hesabix_invoice_project' => isset($_POST['hesabix_invoice_project']) ? sanitize_text_field($_POST['hesabix_invoice_project']) : '', + 'hesabix_invoice_salesman' => isset($_POST['hesabix_invoice_salesman']) ? sanitize_text_field($_POST['hesabix_invoice_salesman']) : '', + 'hesabix_invoice_salesman_percentage' => isset($_POST['hesabix_invoice_salesman_percentage']) ? sanitize_text_field($_POST['hesabix_invoice_salesman_percentage']) : '', + 'hesabix_invoice_draft_save_in_hesabix' => isset($_POST['hesabix_invoice_draft_save_in_hesabix']) ? 'yes' : 'no', + 'hesabix_invoice_freight' => isset($_POST['hesabix_invoice_freight']) ? sanitize_text_field($_POST['hesabix_invoice_freight']) : '', + 'hesabix_invoice_freight_code' => isset($_POST['hesabix_invoice_freight_code']) ? sanitize_text_field($_POST['hesabix_invoice_freight_code']) : '' + ); + + + if (is_plugin_active('dokan-lite/dokan.php')) { + $fields_to_save['hesabix_invoice_dokan'] = isset($_POST['hesabix_invoice_dokan']) ? sanitize_text_field($_POST['hesabix_invoice_dokan']) : '0'; + } + + $success = true; + foreach ($fields_to_save as $option_name => $option_value) { + $result = update_option($option_name, $option_value); + if (!$result && get_option($option_name) !== $option_value) { + $success = false; + } + } + + if ($success) { + wp_send_json_success(array('message' => __('Settings saved successfully', 'hesabix'))); + } else { + wp_send_json_error(array('message' => __('Failed to save settings', 'hesabix'))); + } +}); + +add_action('wp_ajax_hesabix_save_customers_settings_ajax', function () { + + if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error(array('message' => 'Security check failed')); + return; + } + + + $fields_to_save = array( + 'hesabix_contact_address_status' => isset($_POST['hesabix_contact_address_status']) ? sanitize_text_field($_POST['hesabix_contact_address_status']) : '', + 'hesabix_contact_node_family' => isset($_POST['hesabix_contact_node_family']) ? sanitize_text_field($_POST['hesabix_contact_node_family']) : '', + 'hesabix_contact_automatic_save_node_family' => isset($_POST['hesabix_contact_automatic_save_node_family']) ? 'yes' : 'no', + 'hesabix_contact_automatically_save_in_hesabix' => isset($_POST['hesabix_contact_automatically_save_in_hesabix']) ? 'yes' : 'no' + ); + + $success = true; + foreach ($fields_to_save as $option_name => $option_value) { + $result = update_option($option_name, $option_value); + if (!$result && get_option($option_name) !== $option_value) { + $success = false; + } + } + + if ($success) { + wp_send_json_success(array('message' => __('Settings saved successfully', 'hesabix'))); + } else { + wp_send_json_error(array('message' => __('Failed to save settings', 'hesabix'))); + } +}); + + + +add_action('wp_ajax_hesabix_get_sync_stats_ajax', function () { + + if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'hesabix_ajax_nonce')) { + wp_send_json_error(array('message' => 'Security check failed')); + return; + } + + $result = Hesabix_Setting::getProductsCount(); + wp_send_json_success([ + 'storeProductsCount' => $result['storeProductsCount'], + 'hesabixProductsCount' => $result['hesabixProductsCount'], + 'linkedProductsCount' => $result['linkedProductsCount'], + ]); +}); diff --git a/admin/partials/ssbhesabix-html-output.php b/admin/partials/hesabix-html-output.php similarity index 55% rename from admin/partials/ssbhesabix-html-output.php rename to admin/partials/hesabix-html-output.php index 77271c2..5836605 100644 --- a/admin/partials/ssbhesabix-html-output.php +++ b/admin/partials/hesabix-html-output.php @@ -1,371 +1,542 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - */ - -class Ssbhesabix_Html_output { - public static function init($options = array()) { - if (!empty($options)) { - foreach ($options as $value) { - if (!isset($value['type'])) continue; - if (!isset($value['id'])) $value['id'] = ''; - if (!isset($value['title'])) $value['title'] = isset($value['name']) ? $value['name'] : ''; - if (!isset($value['class'])) $value['class'] = ''; - if (!isset($value['css'])) $value['css'] = ''; - if (!isset($value['default'])) $value['default'] = ''; - if (!isset($value['desc'])) $value['desc'] = ''; - if (!isset($value['desc_tip'])) $value['desc_tip'] = false; - $custom_attributes = array(); - if (!empty($value['custom_attributes']) && is_array($value['custom_attributes'])) { - foreach ($value['custom_attributes'] as $attribute => $attribute_value) { - $custom_attributes[] = esc_attr($attribute) . '="' . esc_attr($attribute_value) . '"'; - } - } - if (true === $value['desc_tip']) { - $description = ''; - $tip = $value['desc']; - } elseif (!empty($value['desc_tip'])) { - $description = $value['desc']; - $tip = $value['desc_tip']; - } elseif (!empty($value['desc'])) { - $description = $value['desc']; - $tip = ''; - } else { - $description = $tip = ''; - } - if ($description && in_array($value['type'], array('textarea', 'radio'))) { - $description = '

' . wp_kses_post($description) . '

'; - } elseif ($description && in_array($value['type'], array('checkbox'))) { - $description = wp_kses_post($description); - } elseif ($description) { - $description = '' . wp_kses_post($description) . ''; - } - if (isset($value['placeholder']) && !empty($value['placeholder'])) { - $placeholder = $value['placeholder']; - } else { - $placeholder = ''; - } - if ($tip && in_array($value['type'], array('checkbox'))) { - - $tip = '

' . $tip . '

'; - } - switch ($value['type']) { - case 'title': - if (!empty($value['title'])) { - echo '

' . esc_html($value['title']) . '

'; - } - if (!empty($value['desc'])) { - echo wpautop(wptexturize(wp_kses_post($value['desc']))); - } - echo '' . "\n\n"; - break; - case 'sectionend': - echo '
'; - break; - case 'text': - case 'email': - case 'number': - case 'color' : - case 'password' : - $type = $value['type']; - $class = ''; - $option_value = self::get_option($value['id'], $value['default']); - if ($value['type'] == 'color') { - $type = 'text'; - $value['class'] .= 'colorpick'; - $description .= ''; - } - ?> - - - - - - - /> - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
    - $val) { - ?> -
  • - -
  • - -
-
- - - - - -
- -
- - - - - -
- - - -
- $value['id'], - 'id' => $value['id'], - 'sort_column' => 'menu_order', - 'sort_order' => 'ASC', - 'show_option_none' => ' ', - 'class' => $value['class'], - 'echo' => false, - 'selected' => absint(self::get_option($value['id'])) - ); - if (isset($value['args'])) { - $args = wp_parse_args($value['args'], $args); - } - ?> - - - - - $value) { - update_option($name, wc_clean($value)); - } - echo '

' . __( 'Settings were saved successfully.', 'ssbhesabix' ) . '

'; - return true; - } -//===================================================================================================== -} - -Ssbhesabix_Html_output::init(); + $attribute_value) { + $custom_attributes[] = esc_attr($attribute) . '="' . esc_attr($attribute_value) . '"'; + } + } + if (true === $value['desc_tip']) { + $description = ''; + $tip = $value['desc']; + } elseif (!empty($value['desc_tip'])) { + $description = $value['desc']; + $tip = $value['desc_tip']; + } elseif (!empty($value['desc'])) { + $description = $value['desc']; + $tip = ''; + } else { + $description = $tip = ''; + } + if ($description && in_array($value['type'], array('textarea', 'radio'))) { + $description = '

' . wp_kses_post($description) . '

'; + } elseif ($description && in_array($value['type'], array('checkbox'))) { + $description = wp_kses_post($description); + } elseif ($description) { + $description = '' . wp_kses_post($description) . ''; + } + if (isset($value['placeholder']) && !empty($value['placeholder'])) { + $placeholder = $value['placeholder']; + } else { + $placeholder = ''; + } + if ($tip && in_array($value['type'], array('checkbox'))) { + + $tip = '

' . $tip . '

'; + } + switch ($value['type']) { + case 'title': + if (!empty($value['title'])) { + + } + if (!empty($value['desc'])) { + echo wpautop(wptexturize(wp_kses_post($value['desc']))); + } + echo '' . "\n\n"; + break; + case 'sectionend': + echo '
'; + break; + case 'text': + case 'email': + case 'number': + case 'color' : + case 'password' : + $type = $value['type']; + $class = ''; + $option_value = self::get_option($value['id'], $value['default']); + if ($value['type'] == 'color') { + $type = 'text'; + $value['class'] .= 'colorpick'; + $description .= ''; + } + ?>> + + + + + + + /> + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ $val) { + $is_selected = in_array($key, $option_value); + $status_class = 'hesabix-status-' . str_replace('-', '-', $key); + ?> +
+ /> +
+ '; + break; + case 'processing': + echo ''; + break; + case 'on-hold': + echo ''; + break; + case 'completed': + echo ''; + break; + case 'cancelled': + echo ''; + break; + case 'refunded': + echo ''; + break; + case 'failed': + echo ''; + break; + case 'checkout-draft': + echo ''; + break; + default: + echo ''; + } + ?> +
+
+
+
+ +
+
+
+ +
+
+ + + + + + + + +
+ +
    + $val) { + ?> +
  • + +
  • + +
+
+ + + + + + + +
+
+ $val) : ?> +
+
+
+ '; + break; + case '0': + echo ''; + break; + case '1': + echo ''; + break; + } + ?> +
+
+
+ +
+
+
+ +
+ +
+ + + + + + +
+ +
+ + + + + +
+ + + +
+ $value['id'], + 'id' => $value['id'], + 'sort_column' => 'menu_order', + 'sort_order' => 'ASC', + 'show_option_none' => ' ', + 'class' => $value['class'], + 'echo' => false, + 'selected' => absint(self::get_option($value['id'])) + ); + if (isset($value['args'])) { + $args = wp_parse_args($value['args'], $args); + } + ?> + + + + + $value) { + update_option($name, wc_clean($value)); + } + + return true; + } + +} + +Hesabix_Html_output::init(); diff --git a/admin/partials/ssbhesabix-admin-display.php b/admin/partials/ssbhesabix-admin-display.php deleted file mode 100644 index 37d189e..0000000 --- a/admin/partials/ssbhesabix-admin-display.php +++ /dev/null @@ -1,397 +0,0 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - */ - -class Ssbhesabix_Admin_Display -{ - /** - * Ssbhesabix_Admin_Display constructor. - */ - public function __construct() - { - add_action('admin_menu', array(__CLASS__, 'hesabix_add_menu')); - } - - /** - * Hook in methods - * @since 1.0.0 - * @access static - */ - - /** - * @since 1.0.0 - * @access public - */ - - static function hesabix_add_menu() - { - $iconUrl = plugins_url('/hesabix-accounting/admin/img/menu-icon.png'); - add_menu_page("حسابیکس", "حسابیکس", "manage_options", "ssbhesabix-option", array(__CLASS__, 'hesabix_plugin_page'), $iconUrl, null); - add_submenu_page("ssbhesabix-option", "تنظیمات حسابیکس", "تنظیمات حسابیکس", "manage_options", 'ssbhesabix-option', array(__CLASS__, 'hesabix_plugin_page')); - } - - function hesabix_plugin_sync_products_manually() - { - $page = $_GET["p"]; - $rpp = $_GET["rpp"]; - if (isset($_GET['data'])) { - $data = $_GET["data"]; - $codesNotFoundInHesabix = explode(",", $data); - } - //set default values to page and rpp - if (!$page) $page = 1; - if (!$rpp) $rpp = 10; - - $result = self::getProductsAndRelations($page, $rpp); - $pageCount = ceil($result["totalCount"] / $rpp); - $i = ($page - 1) * $rpp; - $rpp_options = [10, 15, 20, 30, 50]; - - $showTips = true; - if (!isset($_COOKIE['syncProductsManuallyHelp'])) { - setcookie('syncProductsManuallyHelp', 'ture'); - } else { - $showTips = false; - } - - self::hesabix_plugin_header(); - ?> -
-

-

- همسان سازی دستی کالاهای فروشگاه با حسابیکس - مشاهده نکات مهم -
- - - - - -

-
- - - - - - - - - - - - - - - - - - - - - - -
#IDنام کالاشناسه محصولکد حسابیکس
ID; ?>post_title; ?>sku; ?> - -
- - | - | - - - برو - - - < صفحه قبل - صفحه بعد > - -
- -
-
-
- get_results("SELECT id_hesabix FROM " . $wpdb->prefix . "ssbhesabix WHERE obj_type = 'product' GROUP BY id_hesabix HAVING COUNT(id_hesabix) > 1;"); - - $rows = $wpdb->get_results( - "SELECT id_hesabix - FROM {$wpdb->prefix}ssbhesabix - WHERE obj_type = 'product' - GROUP BY id_hesabix - HAVING COUNT(id_hesabix) > 1" - ); - - $ids = array(); - - foreach ($rows as $row) - $ids[] = $row->id_hesabix; - - $idsStr = implode(',', $ids); - //$rows = $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . "ssbhesabix WHERE obj_type = 'product' AND id_hesabix IN ($idsStr) ORDER BY id_hesabix"); - - $rows = $wpdb->get_results( - $wpdb->prepare( - "SELECT * - FROM {$wpdb->prefix}ssbhesabix - WHERE obj_type = 'product' - AND id_hesabix IN ($idsStr) - ORDER BY id_hesabix" - ) - ); - - $i = 0; - - self::hesabix_plugin_header(); - ?> -
-
- کد محصولات تکراری -
- - - - - - - - - - - - - - - - - - - -
#کد حسابیکسشناسه محصولشناسه متغیر
id_hesabix; ?>id_ps; ?>id_ps_attribute; ?>
-
- -
-
- ابزارهای افزونه حسابیکس -
- - حذف دیتای افزونه -
- نصب دیتای افزونه -
- get_results("SELECT post.ID,post.post_title,post.post_parent,post_excerpt,wc.sku FROM `" . $wpdb->prefix . "posts` as post -// LEFT OUTER JOIN `" . $wpdb->prefix . "wc_product_meta_lookup` as wc -// ON post.id = wc.product_id -// WHERE post.post_type IN('product','product_variation') AND post.post_status IN('publish','private') -// ORDER BY post.post_title ASC LIMIT $offset,$rpp"); - - $rows = $wpdb->get_results( - $wpdb->prepare( - "SELECT post.ID, post.post_title, post.post_parent, post.post_excerpt, wc.sku - FROM {$wpdb->posts} AS post - LEFT OUTER JOIN {$wpdb->prefix}wc_product_meta_lookup AS wc - ON post.ID = wc.product_id - WHERE post.post_type IN ('product', 'product_variation') - AND post.post_status IN ('publish', 'private') - ORDER BY post.post_title ASC - LIMIT %d, %d", - $offset, - $rpp - ) - ); - - - -// $totalCount = $wpdb->get_var("SELECT COUNT(*) FROM `" . $wpdb->prefix . "posts` as post -// LEFT OUTER JOIN `" . $wpdb->prefix . "wc_product_meta_lookup` as wc -// ON post.id = wc.product_id -// WHERE post.post_type IN('product','product_variation') AND post.post_status IN('publish','private')"); - - $totalCount = $wpdb->get_var( - "SELECT COUNT(*) - FROM {$wpdb->posts} AS post - LEFT OUTER JOIN {$wpdb->prefix}wc_product_meta_lookup AS wc - ON post.ID = wc.product_id - WHERE post.post_type IN ('product', 'product_variation') - AND post.post_status IN ('publish', 'private')" - ); - - -// $links = $wpdb->get_results("SELECT * FROM `" . $wpdb->prefix . "ssbhesabix` -// WHERE obj_type ='product'"); - - $links = $wpdb->get_results( - "SELECT * - FROM {$wpdb->prefix}ssbhesabix - WHERE obj_type = 'product'" - ); - - foreach ($rows as $r) { - if ($r->post_excerpt) - $r->post_title = $r->post_title . ' [' . $r->post_excerpt . ']'; - } - - foreach ($links as $link) { - foreach ($rows as $r) { - if ($r->ID == $link->id_ps && $link->id_ps_attribute == 0) { - $r->id_hesabix = $link->id_hesabix; - } else if ($r->ID == $link->id_ps_attribute) { - $r->id_hesabix = $link->id_hesabix; - } - } - } - - return array("data" => $rows, "totalCount" => $totalCount); - } -//======================================================================================================================================== - /** - * @since 1.0.0 - * @access public - */ - public static function hesabix_plugin_page() - { - $iconsArray = ['home', 'cog', 'box-open', 'users', 'file-invoice-dollar', 'money-check-alt', 'file-export', 'sync-alt', 'file-alt', 'cog']; - if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) { - $setting_tabs = apply_filters('ssbhesabix_setting_tab', array( - 'home' => __('Home', 'ssbhesabix'), - 'api' => __('API', 'ssbhesabix'), - 'catalog' => __('Catalog', 'ssbhesabix'), - 'customers' => __('Customers', 'ssbhesabix'), - 'invoice' => __('Invoice', 'ssbhesabix'), - 'payment' => __('Payment Methods', 'ssbhesabix'), - 'export' => __('Import and export data', 'ssbhesabix'), - 'sync' => __('Sync', 'ssbhesabix'), - 'log' => __('Log', 'ssbhesabix'), - 'extra' => __('Extra Settings', 'ssbhesabix') - )); - $current_tab = (isset($_GET['tab'])) ? wc_clean($_GET['tab']) : 'home'; - self::hesabix_plugin_header(); - ?> - - $setting_tabvalue) { - switch ($setting_tabkey) { - case $current_tab: - do_action('ssbhesabix_' . $setting_tabkey . '_setting_save_field'); - do_action('ssbhesabix_' . $setting_tabkey . '_setting'); - break; - } - } - } else { - echo '
' . __('Hesabix Plugin requires the WooCommerce to work!, Please install/activate woocommerce and try again', 'ssbhesabix') . '
'; - } - } -//======================================================================================================================================== - public static function hesabix_plugin_header() - { - $logoUrl = plugins_url('/hesabix-accounting/admin/img/hesabix-logo.fa.png'); - ?> - - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - */ -class Ssbhesabix_Admin_Functions -{ - public static function isDateInFiscalYear($date) - { - $hesabixApi = new Ssbhesabix_Api(); - $fiscalYear = $hesabixApi->settingGetFiscalYear(); - if (is_object($fiscalYear)) { - - if ($fiscalYear->Success) { - $fiscalYearStartTimeStamp = strtotime($fiscalYear->Result->StartDate); - $fiscalYearEndTimeStamp = strtotime($fiscalYear->Result->EndDate); - $dateTimeStamp = strtotime($date); - - if ($dateTimeStamp >= $fiscalYearStartTimeStamp && $dateTimeStamp <= $fiscalYearEndTimeStamp) { - return 1; - } else { - return 0; - } - } else { - HesabixLogService::log(array("Cannot get FiscalDate. Error Code: $fiscalYear->ErrroCode. Error Message: $fiscalYear->ErrorMessage")); - return false; - } - } - HesabixLogService::log(array("Cannot connect to Hesabix for get FiscalDate.")); - return false; - } -//==================================================================================================================== - public function getProductVariations($id_product) - { - if (!isset($id_product)) { - return false; - } - $product = wc_get_product($id_product); - - if (is_bool($product)) return false; - if ($product->is_type('variable')) { - $children = $product->get_children($args = '', $output = OBJECT); - $variations = array(); - foreach ($children as $value) { - $product_variatons = new WC_Product_Variation($value); - if ($product_variatons->exists()) { - $variations[] = $product_variatons; - } - } - return $variations; - } - return false; - } -//======================================================================================================== - public function setItems($id_product_array) - { - if (!isset($id_product_array) || $id_product_array[0] == null) return false; - if (is_array($id_product_array) && empty($id_product_array)) return true; - - $items = array(); - foreach ($id_product_array as $id_product) { - $product = new WC_Product($id_product); - if ($product->get_status() === "draft") continue; - - $items[] = ssbhesabixItemService::mapProduct($product, $id_product, false); - - $variations = $this->getProductVariations($id_product); - if ($variations) - foreach ($variations as $variation) - $items[] = ssbhesabixItemService::mapProductVariation($product, $variation, $id_product, false); - } - - if (count($items) === 0) return false; - if (!$this->saveItems($items)) return false; - return true; - } -//==================================================================================================================== - public function saveItems($items) - { - $hesabix = new Ssbhesabix_Api(); - $wpFaService = new HesabixWpFaService(); - - $response = $hesabix->itemBatchSave($items); - if ($response->Success) { - foreach ($response->Result as $item) - $wpFaService->saveProduct($item); - return true; - } else { - HesabixLogService::log(array("Cannot add/update Hesabix items. Error Code: " . (string)$response->ErrorCode . ". Error Message: $response->ErrorMessage.")); - return false; - } - } -//==================================================================================================================== - public function getContactCodeByCustomerId($id_customer) - { - if (!isset($id_customer)) { - return false; - } - - global $wpdb; - //$row = $wpdb->get_row("SELECT `id_hesabix` FROM " . $wpdb->prefix . "ssbhesabix WHERE `id_ps` = $id_customer AND `obj_type` = 'customer'"); - - $row = $wpdb->get_row( - $wpdb->prepare( - "SELECT `id_hesabix` FROM {$wpdb->prefix}ssbhesabix - WHERE `id_ps` = %d AND `obj_type` = 'customer'", - $id_customer - ) - ); - - if (is_object($row)) { - return $row->id_hesabix; - } else { - return null; - } - } -//==================================================================================================================== - public function setContact($id_customer, $type = 'first', $id_order = '') - { - if (!isset($id_customer)) return false; - - $code = $this->getContactCodeByCustomerId($id_customer); - - $hesabixCustomer = ssbhesabixCustomerService::mapCustomer($code, $id_customer, $type, $id_order); - - $hesabix = new Ssbhesabix_Api(); - $response = $hesabix->contactSave($hesabixCustomer); - - if ($response->Success) { - $wpFaService = new HesabixWpFaService(); - $wpFaService->saveCustomer($response->Result); - return $response->Result->Code; - } else { - HesabixLogService::log(array("Cannot add/update customer. Error Code: " . (string)$response->ErrroCode . ". Error Message: " . (string)$response->ErrorMessage . ". Customer ID: $id_customer")); - return false; - } - } -//==================================================================================================================== - public function setGuestCustomer($id_order) - { - if (!isset($id_order)) return false; - - //$order = new WC_Order($id_order); - $order = wc_get_order($id_order); - - $contactCode = $this->getContactCodeByPhoneOrEmail($order->get_billing_phone(), $order->get_billing_email()); - - $hesabixCustomer = ssbhesabixCustomerService::mapGuestCustomer($contactCode, $id_order); - - $hesabix = new Ssbhesabix_Api(); - $response = $hesabix->contactSave($hesabixCustomer); - - if ($response->Success) { - $wpFaService = new HesabixWpFaService(); - $wpFaService->saveCustomer($response->Result); - return (int)$response->Result->Code; - } else { - HesabixLogService::log(array("Cannot add/update contact. Error Code: " . (string)$response->ErrroCode . ". Error Message: " . (string)$response->ErrorMessage . ". Customer ID: Guest Customer")); - return false; - } - } -//==================================================================================================================== - public function getContactCodeByPhoneOrEmail($phone, $email) - { - if (!$email && !$phone) return null; - - $hesabix = new Ssbhesabix_Api(); - $response = $hesabix->contactGetByPhoneOrEmail($phone, $email); - - if (is_object($response)) { - if ($response->Success && $response->Result->TotalCount > 0) { - $contact_obj = $response->Result->List; - - if (!$contact_obj[0]->Code || $contact_obj[0]->Code == '0' || $contact_obj[0]->Code == '000000') return null; - - foreach ($contact_obj as $contact) { - if (($contact->phone == $phone || $contact->mobile = $phone) && $contact->email == $email) - return (int)$contact->Code; - } - foreach ($contact_obj as $contact) { - if ($phone && $contact->phone == $phone || $contact->mobile = $phone) - return (int)$contact->Code; - } - foreach ($contact_obj as $contact) { - if ($email && $contact->email == $email) - return (int)$contact->Code; - } - return null; - } - } else { - HesabixLogService::log(array("Cannot get Contact list. Error Message: (string)$response->ErrorMessage. Error Code: (string)$response->ErrorCode.")); - } - - return null; - } -//==================================================================================================================== - //Invoice - public function setOrder($id_order, $orderType = 0, $reference = null) - { - if (!isset($id_order)) { - return false; - } - - $wpFaService = new HesabixWpFaService(); - - $number = $this->getInvoiceNumberByOrderId($id_order); - if (!$number) { - $number = null; - if ($orderType == 2) //return if saleInvoice not set before - { - return false; - } - } - -// $order = new WC_Order($id_order); - $order = wc_get_order($id_order); - - $dokanOption = get_option("ssbhesabix_invoice_dokan", 0); - - if ($dokanOption && is_plugin_active("dokan-lite/dokan.php")) { - $orderCreated = $order->get_created_via(); - if ($dokanOption == 1 && $orderCreated !== 'checkout') - return false; - else if ($dokanOption == 2 && $orderCreated === 'checkout') - return false; - } - - $id_customer = $order->get_customer_id(); - if ($id_customer !== 0) { - - $contactCode = $this->setContact($id_customer, 'first', $id_order); - - if ($contactCode == null) { - if (!$contactCode) { - return false; - } - } - HesabixLogService::writeLogStr("order ID " . $id_order); - if (get_option('ssbhesabix_contact_address_status') == 2) { - $this->setContact($id_customer, 'billing', $id_order); - } elseif (get_option('ssbhesabix_contact_address_status') == 3) { - $this->setContact($id_customer, 'shipping', $id_order); - } - } else { - $contactCode = $this->setGuestCustomer($id_order); - if (!$contactCode) { - return false; - } - } - - global $notDefinedProductID; - $notDefinedItems = array(); - $products = $order->get_items(); - foreach ($products as $product) { - if ($product['product_id'] == 0) continue; - $itemCode = $wpFaService->getProductCodeByWpId($product['product_id'], $product['variation_id']); - if ($itemCode == null) { - $notDefinedItems[] = $product['product_id']; - } - } - - if (!empty($notDefinedItems)) { - if (!$this->setItems($notDefinedItems)) { - HesabixLogService::writeLogStr("Cannot add/update Invoice. Failed to set products. Order ID: $id_order"); - return false; - } - } - - $invoiceItems = array(); - $i = 0; - $failed = false; - foreach ($products as $key => $product) { - $itemCode = $wpFaService->getProductCodeByWpId($product['product_id'], $product['variation_id']); - - if ($itemCode == null) { - $pId = $product['product_id']; - $vId = $product['variation_id']; - HesabixLogService::writeLogStr("Item not found. productId: $pId, variationId: $vId, Order ID: $id_order"); - - $failed = true; - break; - } - -// $wcProduct = new WC_Product($product['product_id']); - - if($product['variation_id']) { - $wcProduct = wc_get_product($product['variation_id']); - } else { - $wcProduct = wc_get_product($product['product_id']); - } - - global $discount, $price; - if( $wcProduct->is_on_sale() && get_option('ssbhesabix_set_special_sale_as_discount') === 'yes' ) { - $price = $this->getPriceInHesabixDefaultCurrency($wcProduct->get_regular_price()); - $discount = $this->getPriceInHesabixDefaultCurrency($wcProduct->get_regular_price() - $wcProduct->get_sale_price()); - $discount *= $product['quantity']; - } else { - $price = $this->getPriceInHesabixDefaultCurrency($product['subtotal'] / $product['quantity']); - $discount = $this->getPriceInHesabixDefaultCurrency($product['subtotal'] - $product['total']); - } - - $item = array( - 'RowNumber' => $i, - 'ItemCode' => $itemCode, - 'Description' => Ssbhesabix_Validation::invoiceItemDescriptionValidation($product['name']), - 'Quantity' => (int)$product['quantity'], - 'UnitPrice' => (float)$price, - 'Discount' => (float)$discount, - 'Tax' => (float)$this->getPriceInHesabixDefaultCurrency($product['total_tax']), - ); - - $invoiceItems[] = $item; - $i++; - } - - if ($failed) { - HesabixLogService::writeLogStr("Cannot add/update Invoice. Item code is NULL. Check your invoice products and relations with Hesabix. Order ID: $id_order"); - return false; - } - - if (empty($invoiceItems)) { - HesabixLogService::log(array("Cannot add/update Invoice. At least one item required.")); - return false; - } - - $date_obj = $order->get_date_created(); - switch ($orderType) { - case 0: - $date = $date_obj->date('Y-m-d H:i:s'); - break; - case 2: - $date = date('Y-m-d H:i:s'); - break; - default: - $date = $date_obj->date('Y-m-d H:i:s'); - } - - if ($reference === null) - $reference = $id_order; - - $order_shipping_method = ""; - foreach ($order->get_items('shipping') as $item) - $order_shipping_method = $item->get_name(); - - $note = $order->customer_note; - if ($order_shipping_method) - $note .= "\n" . __('Shipping method', 'ssbhesabix') . ": " . $order_shipping_method; - - global $freightOption, $freightItemCode; - $freightOption = get_option("ssbhesabix_invoice_freight"); - - if($freightOption == 1) { - $freightItemCode = get_option('ssbhesabix_invoice_freight_code'); - if(!isset($freightItemCode) || !$freightItemCode) HesabixLogService::writeLogStr("کد هزینه حمل و نقل تعریف نشده است" . "\n" . "Freight service code is not set"); - - $freightItemCode = $this->convertPersianDigitsToEnglish($freightItemCode); - - if($this->getPriceInHesabixDefaultCurrency($order->get_shipping_total()) != 0) { - $invoiceItem = array( - 'RowNumber' => $i, - 'ItemCode' => $freightItemCode, - 'Description' => 'هزینه حمل و نقل', - 'Quantity' => 1, - 'UnitPrice' => (float) $this->getPriceInHesabixDefaultCurrency($order->get_shipping_total()), - 'Discount' => 0, - 'Tax' => (float) $this->getPriceInHesabixDefaultCurrency($order->get_shipping_tax()) - ); - $invoiceItems[] = $invoiceItem; - } - } - - $data = array( - 'Number' => $number, - 'InvoiceType' => $orderType, - 'ContactCode' => $contactCode, - 'Date' => $date, - 'DueDate' => $date, - 'Reference' => $reference, - 'Status' => 2, - 'Tag' => json_encode(array('id_order' => $id_order)), - 'InvoiceItems' => $invoiceItems, - 'Note' => $note, - 'Freight' => '' - ); - - if($freightOption == 0) { - $freight = $this->getPriceInHesabixDefaultCurrency($order->get_shipping_total() + $order->get_shipping_tax()); - $data['Freight'] = $freight; - } - - $invoice_draft_save = get_option('ssbhesabix_invoice_draft_save_in_hesabix', 'no'); - if ($invoice_draft_save != 'no') - $data['Status'] = 0; - - $invoice_project = get_option('ssbhesabix_invoice_project', -1); - $invoice_salesman = get_option('ssbhesabix_invoice_salesman', -1); - $invoice_salesman_percentage = get_option('ssbhesabix_invoice_salesman_percentage', 0); - if ($invoice_project != -1) $data['Project'] = $invoice_project; - if ($invoice_salesman != -1) $data['SalesmanCode'] = $invoice_salesman; - if($invoice_salesman_percentage) if($invoice_salesman_percentage != 0) $data['SalesmanPercent'] = $this->convertPersianDigitsToEnglish($invoice_salesman_percentage); - - $GUID = $this->getGUID($id_order); - $hesabix = new Ssbhesabix_Api(); - $response = $hesabix->invoiceSave($data, $GUID); -// $response = $hesabix->invoiceSave($data, ''); - - if ($response->Success) { - global $wpdb; - - switch ($orderType) { - case 0: - $obj_type = 'order'; - break; - case 2: - $obj_type = 'returnOrder'; - break; - } - - if ($number === null) { - $wpdb->insert($wpdb->prefix . 'ssbhesabix', array( - 'id_hesabix' => (int)$response->Result->Number, - 'obj_type' => $obj_type, - 'id_ps' => $id_order, - )); - HesabixLogService::log(array("Invoice successfully added. Invoice number: " . (string)$response->Result->Number . ". Order ID: $id_order")); - } else { - $wpFaId = $wpFaService->getWpFaId($obj_type, $id_order); - - $wpdb->update($wpdb->prefix . 'ssbhesabix', array( - 'id_hesabix' => (int)$response->Result->Number, - 'obj_type' => $obj_type, - 'id_ps' => $id_order, - ), array('id' => $wpFaId)); - HesabixLogService::log(array("Invoice successfully updated. Invoice number: " . (string)$response->Result->Number . ". Order ID: $id_order")); - } - - $warehouse = get_option('ssbhesabix_item_update_quantity_based_on', "-1"); - if ($warehouse != "-1" && $orderType === 0) - $this->setWarehouseReceipt($invoiceItems, (int)$response->Result->Number, $warehouse, $date, $invoice_project); - - return true; - } else { - foreach ($invoiceItems as $item) { - HesabixLogService::log(array("Cannot add/update Invoice. Error Code: " . (string)$response->ErrorCode . ". Error Message: " . (string)$response->ErrorMessage . ". Order ID: $id_order" . "\n" - . "Hesabix Id:" . $item['ItemCode'] - )); - } - return false; - } - } -//======================================================================================================================== - public function setWarehouseReceipt($items, $invoiceNumber, $warehouseCode, $date, $project) - { - $invoiceOption = get_option('ssbhesabix_invoice_freight'); - if($invoiceOption == 1) { - $invoiceFreightCode = get_option('ssbhesabix_invoice_freight_code'); - for ($i = 0 ; $i < count($items) ; $i++) { - if($items[$i]["ItemCode"] == $invoiceFreightCode) { - unset($items[$i]); - } - } - } - - $data = array( - 'WarehouseCode' => $warehouseCode, - 'InvoiceNumber' => $invoiceNumber, - 'InvoiceType' => 0, - 'Date' => $date, - 'Items' => $items - ); - - if ($project != -1) - $data['Project'] = $project; - - $hesabix = new Ssbhesabix_Api(); - $response = $hesabix->saveWarehouseReceipt($data); - - if ($response->Success) - HesabixLogService::log(array("Warehouse receipt successfully saved/updated. warehouse receipt number: " . (string)$response->Result->Number . ". Invoice number: $invoiceNumber")); - else - HesabixLogService::log(array("Cannot save/update Warehouse receipt. Error Code: " . (string)$response->ErrorCode . ". Error Message: " . (string)$response->ErrorMessage . ". Invoice number: $invoiceNumber")); - } -//======================================================================================================================== - public static function getPriceInHesabixDefaultCurrency($price) - { - if (!isset($price)) return false; - - $woocommerce_currency = get_woocommerce_currency(); - $hesabix_currency = get_option('ssbhesabix_hesabix_default_currency'); - - if (!is_numeric($price)) - $price = intval($price); - - if ($hesabix_currency == 'IRR' && $woocommerce_currency == 'IRT') - $price *= 10; - - if ($hesabix_currency == 'IRT' && $woocommerce_currency == 'IRR') - $price /= 10; - - return $price; - } -//======================================================================================================================== - public static function getPriceInWooCommerceDefaultCurrency($price) - { - if (!isset($price)) return false; - - $woocommerce_currency = get_woocommerce_currency(); - $hesabix_currency = get_option('ssbhesabix_hesabix_default_currency'); - - if (!is_numeric($price)) - $price = intval($price); - - if ($hesabix_currency == 'IRR' && $woocommerce_currency == 'IRT') - $price /= 10; - - if ($hesabix_currency == 'IRT' && $woocommerce_currency == 'IRR') - $price *= 10; - - return $price; - } -//======================================================================================================================== - public function setOrderPayment($id_order) - { - if (!isset($id_order)) { - return false; - } - - $hesabix = new Ssbhesabix_Api(); - $number = $this->getInvoiceCodeByOrderId($id_order); - if (!$number) { - return false; - } - - //$order = new WC_Order($id_order); - $order = wc_get_order($id_order); - - if ($order->get_total() <= 0) { - return true; - } - - - $transaction_id = $order->get_transaction_id(); - //transaction id cannot be null or empty - if ($transaction_id == '') { - $transaction_id = '-'; - } - - global $financialData; - if(get_option('ssbhesabix_payment_option') == 'no') { - $bank_code = $this->getBankCodeByPaymentMethod($order->get_payment_method()); - if ($bank_code != false) { - $payTempValue = substr($bank_code, 0, 4); - - switch($payTempValue) { - case 'bank': - $payTempValue = substr($bank_code, 4); - $financialData = array('bankCode' => $payTempValue);break; - case 'cash': - $payTempValue = substr($bank_code, 4); - $financialData = array('cashCode' => $payTempValue);break; - } - } else { - HesabixLogService::log(array("Cannot add Hesabix Invoice payment - Bank Code not defined. Order ID: $id_order")); - return false; - } - } elseif (get_option('ssbhesabix_payment_option') == 'yes') { - $defaultBankCode = $this->convertPersianDigitsToEnglish(get_option('ssbhesabix_default_payment_method_code')); - if($defaultBankCode != false) { - $financialData = array('bankCode' => $defaultBankCode); - } else { - HesabixLogService::writeLogStr("Default Bank Code is not Defined"); - return false; - } - } - - $date_obj = $order->get_date_paid(); - if ($date_obj == null) { - $date_obj = $order->get_date_modified(); - } - - global $accountPath; - - if(get_option("ssbhesabix_cash_in_transit") == "1" || get_option("ssbhesabix_cash_in_transit") == "yes") { - $func = new Ssbhesabix_Admin_Functions(); - $cashInTransitFullPath = $func->getCashInTransitFullPath(); - if(!$cashInTransitFullPath) { - HesabixLogService::writeLogStr("Cash in Transit is not Defined in Hesabix ---- وجوه در راه در حسابیکس یافت نشد"); - return false; - } else { - $accountPath = array("accountPath" => $cashInTransitFullPath); - } - } - - $response = $hesabix->invoiceGet($number); - if ($response->Success) { - if ($response->Result->Paid > 0) { - // payment submited before - } else { - $paymentMethod = $order->get_payment_method(); - $transactionFee = 0; - if(isset($paymentMethod)) { - if(get_option("ssbhesabix_payment_transaction_fee_$paymentMethod") > 0) $transactionFee = $this->formatTransactionFee(get_option("ssbhesabix_payment_transaction_fee_$paymentMethod"), $this->getPriceInHesabixDefaultCurrency($order->get_total())); - else $transactionFee = $this->formatTransactionFee(get_option("ssbhesabix_invoice_transaction_fee"), $this->getPriceInHesabixDefaultCurrency($order->get_total())); - } - - if(isset($transactionFee) && $transactionFee != null) $response = $hesabix->invoiceSavePayment($number, $financialData, $accountPath, $date_obj->date('Y-m-d H:i:s'), $this->getPriceInHesabixDefaultCurrency($order->get_total()), $transaction_id,'', $transactionFee); - else $response = $hesabix->invoiceSavePayment($number, $financialData, $accountPath, $date_obj->date('Y-m-d H:i:s'), $this->getPriceInHesabixDefaultCurrency($order->get_total()), $transaction_id,'', 0); - - if ($response->Success) { - HesabixLogService::log(array("Hesabix invoice payment added. Order ID: $id_order")); - return true; - } else { - HesabixLogService::log(array("Cannot add Hesabix Invoice payment. Order ID: $id_order. Error Code: " . (string)$response->ErrorCode . ". Error Message: " . (string)$response->ErrorMessage . ".")); - return false; - } - } - return true; - } else { - HesabixLogService::log(array("Error while trying to get invoice. Invoice Number: $number. Error Code: " . (string)$response->ErrorCode . ". Error Message: " . (string)$response->ErrorMessage . ".")); - return false; - } - } -//======================================================================================================================== - public function getCashInTransitFullPath() { - $api = new Ssbhesabix_Api(); - $accounts = $api->settingGetAccounts(); - foreach ($accounts->Result as $account) { - if($account->Name == "وجوه در راه") { - return $account->FullPath; - } - } - return false; - } -//======================================================================================================================== - public function getInvoiceNumberByOrderId($id_order) - { - if (!isset($id_order)) return false; - - global $wpdb; - $row = $wpdb->get_row("SELECT `id_hesabix` FROM " . $wpdb->prefix . "ssbhesabix WHERE `id_ps` = $id_order AND `obj_type` = 'order'"); - - if (is_object($row)) { - return $row->id_hesabix; - } else { - return false; - } - } -//======================================================================================================================== - public function getBankCodeByPaymentMethod($payment_method) - { - $code = get_option('ssbhesabix_payment_method_' . $payment_method); - - if (isset($code)) - return $code; - else - return false; - } -//======================================================================================================================== - public function getInvoiceCodeByOrderId($id_order) - { - if (!isset($id_order)) return false; - - global $wpdb; - $row = $wpdb->get_row("SELECT `id_hesabix` FROM " . $wpdb->prefix . "ssbhesabix WHERE `id_ps` = $id_order AND `obj_type` = 'order'"); - - if (is_object($row)) { - return $row->id_hesabix; - } else { - return false; - } - } -//======================================================================================================================== - public function exportProducts($batch, $totalBatch, $total, $updateCount) - { - HesabixLogService::writeLogStr("Exporting Products"); - try { - $wpFaService = new HesabixWpFaService(); - $extraSettingRPP = get_option("ssbhesabix_set_rpp_for_export_products"); - $rpp=500; - if($extraSettingRPP) { - if($extraSettingRPP != '-1' && $extraSettingRPP != '0') { - $rpp=$extraSettingRPP; - } - } - $result = array(); - $result["error"] = false; - global $wpdb; - - if ($batch == 1) { -// $total = $wpdb->get_var("SELECT COUNT(*) FROM `" . $wpdb->prefix . "posts` -// WHERE post_type = 'product' AND post_status IN('publish','private')"); - - $total = $wpdb->get_var( - $wpdb->prepare( - "SELECT COUNT(*) FROM {$wpdb->posts} - WHERE post_type = 'product' AND post_status IN ('publish', 'private')" - ) - ); - - $totalBatch = ceil($total / $rpp); - } - - $offset = ($batch - 1) * $rpp; -// $products = $wpdb->get_results("SELECT ID FROM `" . $wpdb->prefix . "posts` -// WHERE post_type = 'product' AND post_status IN('publish','private') ORDER BY 'ID' ASC LIMIT $offset,$rpp"); - - $products = $wpdb->get_results( - $wpdb->prepare( - "SELECT ID FROM {$wpdb->posts} - WHERE post_type = 'product' AND post_status IN ('publish', 'private') - ORDER BY ID ASC - LIMIT %d, %d", - $offset, - $rpp - ) - ); - - $items = array(); - - foreach ($products as $item) { - $id_product = $item->ID; - $product = new WC_Product($id_product); - - $id_obj = $wpFaService->getWpFaId('product', $id_product, 0); - - if (!$id_obj) { - $hesabixItem = ssbhesabixItemService::mapProduct($product, $id_product); - array_push($items, $hesabixItem); - $updateCount++; - } - - $variations = $this->getProductVariations($id_product); - if ($variations) { - foreach ($variations as $variation) { - $id_attribute = $variation->get_id(); - $id_obj = $wpFaService->getWpFaId('product', $id_product, $id_attribute); - - if (!$id_obj) { - $hesabixItem = ssbhesabixItemService::mapProductVariation($product, $variation, $id_product); - array_push($items, $hesabixItem); - $updateCount++; - } - } - } - } - - if (!empty($items)) { - $count = 0; - $hesabix = new Ssbhesabix_Api(); - $response = $hesabix->itemBatchSave($items); - if ($response->Success) { - foreach ($response->Result as $item) { - $json = json_decode($item->Tag); - - global $wpdb; - $wpdb->insert($wpdb->prefix . 'ssbhesabix', array( - 'id_hesabix' => (int)$item->Code, - 'obj_type' => 'product', - 'id_ps' => (int)$json->id_product, - 'id_ps_attribute' => (int)$json->id_attribute, - )); - HesabixLogService::log(array("Item successfully added. Item Code: " . (string)$item->Code . ". Product ID: $json->id_product - $json->id_attribute")); - } - $count += count($response->Result); - } else { - HesabixLogService::log(array("Cannot add bulk item. Error Message: " . (string)$response->ErrorMessage . ". Error Code: " . (string)$response->ErrorCode . ".")); - } - sleep(2); - } - - $result["batch"] = $batch; - $result["totalBatch"] = $totalBatch; - $result["total"] = $total; - $result["updateCount"] = $updateCount; - return $result; - } catch(Error $error) { - HesabixLogService::writeLogStr("Error in export products: " . $error->getMessage()); - } - } -//======================================================================================================================== - public function importProducts($batch, $totalBatch, $total, $updateCount) - { - HesabixLogService::writeLogStr("Import Products"); - try { - $wpFaService = new HesabixWpFaService(); - $extraSettingRPP = get_option("ssbhesabix_set_rpp_for_import_products"); - - $rpp=100; - if($extraSettingRPP) { - if($extraSettingRPP != '-1' && $extraSettingRPP != '0') { - $rpp=$extraSettingRPP; - } - } - - $result = array(); - $result["error"] = false; - global $wpdb; - $hesabix = new Ssbhesabix_Api(); - $filters = array(array("Property" => "khadamat", "Operator" => "=", "Value" => 0)); - - if ($batch == 1) { - $total = 0; - $response = $hesabix->itemGetItems(array('Take' => 1, 'Filters' => $filters)); - if ($response->Success) { - $total = $response->Result->FilteredCount; - $totalBatch = ceil($total / $rpp); - } else { - HesabixLogService::log(array("Error while trying to get products for import. Error Message: $response->ErrorMessage. Error Code: $response->ErrorCode.")); - $result["error"] = true; - return $result; - }; - } - - $id_product_array = array(); - $offset = ($batch - 1) * $rpp; - - $response = $hesabix->itemGetItems(array('Skip' => $offset, 'Take' => $rpp, 'SortBy' => 'Id', 'Filters' => $filters)); - if ($response->Success) { - $items = $response->Result->List; - $from = $response->Result->From; - $to = $response->Result->To; - - foreach ($items as $item) { - $wpFa = $wpFaService->getWpFaByHesabixId('product', $item->Code); - if ($wpFa) continue; - - $clearedName = preg_replace("/\s+|\/|\\\|\(|\)/", '-', trim($item->Name)); - $clearedName = preg_replace("/\-+/", '-', $clearedName); - $clearedName = trim($clearedName, '-'); - $clearedName = preg_replace(["/۰/", "/۱/", "/۲/", "/۳/", "/۴/", "/۵/", "/۶/", "/۷/", "/۸/", "/۹/"], - ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], $clearedName); - - // add product to database - $wpdb->insert($wpdb->posts, array( - 'post_author' => get_current_user_id(), - 'post_date' => current_time('mysql'), - 'post_date_gmt' => current_time('mysql', 1), - 'post_content' => '', - 'post_title' => $item->Name, - 'post_excerpt' => '', - 'post_status' => 'private', - 'comment_status' => 'open', - 'ping_status' => 'closed', - 'post_password' => '', - 'post_name' => $clearedName, - 'to_ping' => '', - 'pinged' => '', - 'post_modified' => current_time('mysql'), - 'post_modified_gmt' => current_time('mysql', 1), - 'post_content_filtered' => '', - 'post_parent' => 0, - 'guid' => home_url('/product/' . $clearedName . '/'), - 'menu_order' => 0, - 'post_type' => 'product', - 'post_mime_type' => '', - 'comment_count' => 0, - )); - - $postId = $wpdb->insert_id; - $id_product_array[] = $postId; - $price = self::getPriceInWooCommerceDefaultCurrency($item->SellPrice); - - // add product link to hesabix - $wpdb->insert($wpdb->prefix . 'ssbhesabix', array( - 'obj_type' => 'product', - 'id_hesabix' => (int)$item->Code, - 'id_ps' => $postId, - 'id_ps_attribute' => 0, - )); - - update_post_meta($postId, '_manage_stock', 'yes'); - update_post_meta($postId, '_sku', $item->Barcode); - update_post_meta($postId, '_regular_price', $price); - update_post_meta($postId, '_price', $price); - update_post_meta($postId, '_stock', $item->Stock); - - $new_stock_status = ($item->Stock > 0) ? "instock" : "outofstock"; - wc_update_product_stock_status($postId, $new_stock_status); - $updateCount++; - } - - } else { - HesabixLogService::log(array("Error while trying to get products for import. Error Message: (string)$response->ErrorMessage. Error Code: (string)$response->ErrorCode.")); - $result["error"] = true; - return $result; - } - sleep(2); - - $result["batch"] = $batch; - $result["totalBatch"] = $totalBatch; - $result["total"] = $total; - $result["updateCount"] = $updateCount; - return $result; - } catch(Error $error) { - HesabixLogService::writeLogStr("Error in importing products" . $error->getMessage()); - } - } -//======================================================================================================================== - public function exportOpeningQuantity($batch, $totalBatch, $total) - { - try { - $wpFaService = new HesabixWpFaService(); - - $result = array(); - $result["error"] = false; - $extraSettingRPP = get_option("ssbhesabix_set_rpp_for_export_opening_products"); - - $rpp=500; - if($extraSettingRPP) { - if($extraSettingRPP != '-1' && $extraSettingRPP != '0') { - $rpp=$extraSettingRPP; - } - } - - global $wpdb; - - if ($batch == 1) { - $total = $wpdb->get_var( - $wpdb->prepare( - "SELECT COUNT(*) FROM {$wpdb->posts} - WHERE post_type = 'product' AND post_status IN ('publish', 'private')" - ) - ); - $totalBatch = ceil($total / $rpp); - } - - $offset = ($batch - 1) * $rpp; - - $products = $wpdb->get_results( - $wpdb->prepare( - "SELECT ID FROM {$wpdb->posts} - WHERE post_type = 'product' AND post_status IN ('publish', 'private') - ORDER BY ID ASC - LIMIT %d, %d", - $offset, - $rpp - ) - ); - - $items = array(); - - foreach ($products as $item) { - $variations = $this->getProductVariations($item->ID); - if (!$variations) { - $id_obj = $wpFaService->getWpFaId('product', $item->ID, 0); - - if ($id_obj != false) { - $product = new WC_Product($item->ID); - $quantity = $product->get_stock_quantity(); - $price = $product->get_regular_price() ? $product->get_regular_price() : $product->get_price(); - - $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id` = " . $id_obj . " AND `obj_type` = 'product'"); - - if (is_object($product) && is_object($row) && $quantity > 0 && $price > 0) { - array_push($items, array( - 'Code' => $row->id_hesabix, - 'Quantity' => $quantity, - 'UnitPrice' => $this->getPriceInHesabixDefaultCurrency($price), - )); - } - } - } else { - foreach ($variations as $variation) { - $id_attribute = $variation->get_id(); - $id_obj = $wpFaService->getWpFaId('product', $item->ID, $id_attribute); - if ($id_obj != false) { - $quantity = $variation->get_stock_quantity(); - $price = $variation->get_regular_price() ? $variation->get_regular_price() : $variation->get_price(); - - $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id` = " . $id_obj . " AND `obj_type` = 'product'"); - - if (is_object($variation) && is_object($row) && $quantity > 0 && $price > 0) { - array_push($items, array( - 'Code' => $row->id_hesabix, - 'Quantity' => $quantity, - 'UnitPrice' => $this->getPriceInHesabixDefaultCurrency($price), - )); - } - } - } - } - } - - if (!empty($items)) { - $hesabix = new Ssbhesabix_Api(); - $response = $hesabix->itemUpdateOpeningQuantity($items); - if ($response->Success) { - // continue batch loop - } else { - HesabixLogService::log(array("ssbhesabix - Cannot set Opening quantity. Error Code: ' . $response->ErrorCode . '. Error Message: ' . $response->ErrorMessage")); - $result['error'] = true; - if ($response->ErrorCode = 199 && $response->ErrorMessage == 'No-Shareholders-Exist') { - $result['errorType'] = 'shareholderError'; - return $result; - } - return $result; - } - } - sleep(2); - $result["batch"] = $batch; - $result["totalBatch"] = $totalBatch; - $result["total"] = $total; - $result["done"] = $batch == $totalBatch; - return $result; - } catch(Error $error) { - HesabixLogService::writeLogStr("Error in Exporting Opening Quantity" . $error->getMessage()); - } - } -//======================================================================================================================== - public function exportCustomers($batch, $totalBatch, $total, $updateCount) - { - HesabixLogService::writeLogStr("Export Customers"); - $wpFaService = new HesabixWpFaService(); - - $result = array(); - $result["error"] = false; - $rpp = 500; - global $wpdb; - - if ($batch == 1) { - $total = $wpdb->get_var("SELECT COUNT(*) FROM `" . $wpdb->prefix . "users`"); - $totalBatch = ceil($total / $rpp); - } - - $offset = ($batch - 1) * $rpp; - $customers = $wpdb->get_results("SELECT ID FROM `" . $wpdb->prefix . "users` ORDER BY ID ASC LIMIT $offset,$rpp"); - - $items = array(); - foreach ($customers as $item) { - $id_customer = $item->ID; - $id_obj = $wpFaService->getWpFaId('customer', $id_customer); - if (!$id_obj) { - $hesabixCustomer = ssbhesabixCustomerService::mapCustomer(null, $id_customer); - array_push($items, $hesabixCustomer); - $updateCount++; - } - } - - if (!empty($items)) { - $hesabix = new Ssbhesabix_Api(); - $response = $hesabix->contactBatchSave($items); - if ($response->Success) { - foreach ($response->Result as $item) { - $json = json_decode($item->Tag); - - $wpdb->insert($wpdb->prefix . 'ssbhesabix', array( - 'id_hesabix' => (int)$item->Code, - 'obj_type' => 'customer', - 'id_ps' => (int)$json->id_customer, - )); - - HesabixLogService::log(array("Contact successfully added. Contact Code: " . $item->Code . ". Customer ID: " . (int)$json->id_customer)); - } - } else { - HesabixLogService::log(array("Cannot add bulk contacts. Error Message: $response->ErrorMessage. Error Code: $response->ErrorCode.")); - } - } - - $result["batch"] = $batch; - $result["totalBatch"] = $totalBatch; - $result["total"] = $total; - $result["updateCount"] = $updateCount; - - return $result; - } -//======================================================================================================================== - public function syncOrders($from_date, $end_date, $batch, $totalBatch, $total, $updateCount) - { - HesabixLogService::writeLogStr("Sync Orders"); - $wpFaService = new HesabixWpFaService(); - - $result = array(); - $result["error"] = false; - $rpp = 10; - global $wpdb; - - if (!isset($from_date) || empty($from_date)) { - $result['error'] = 'inputDateError'; - return $result; - } - - if (!isset($end_date) || empty($end_date)) { - $result['error'] = 'inputDateError'; - return $result; - } - - if (!$this->isDateInFiscalYear($from_date)) { - $result['error'] = 'fiscalYearError'; - return $result; - } - - if (!$this->isDateInFiscalYear($end_date)) { - $result['error'] = 'fiscalYearError'; - return $result; - } - - if ($batch == 1) { - if (get_option('woocommerce_custom_orders_table_enabled') === 'yes') { - $total = $wpdb->get_var("SELECT COUNT(*) FROM `" . $wpdb->prefix . "wc_orders` - WHERE type = 'shop_order' AND date_created_gmt >= '" . $from_date . "' AND date_created_gmt <= '". $end_date ."'"); - } else { - $total = $wpdb->get_var("SELECT COUNT(*) FROM `" . $wpdb->prefix . "posts` - WHERE post_type = 'shop_order' AND post_date >= '" . $from_date . "' AND post_date <= '". $end_date ."'"); - } - $totalBatch = ceil($total / $rpp); - } - - $offset = ($batch - 1) * $rpp; - - if (get_option('woocommerce_custom_orders_table_enabled') === 'yes') { - $orders = $wpdb->get_results("SELECT ID FROM `" . $wpdb->prefix . "wc_orders` - WHERE type = 'shop_order' AND date_created_gmt >= '" . $from_date . "' - AND date_created_gmt <= '". $end_date ."' - ORDER BY ID ASC LIMIT $offset,$rpp"); - } else { - $orders = $wpdb->get_results("SELECT ID FROM `" . $wpdb->prefix . "posts` - WHERE post_type = 'shop_order' AND post_date >= '" . $from_date . "' - AND post_date <= '". $end_date ."' - ORDER BY ID ASC LIMIT $offset,$rpp"); - } - - HesabixLogService::writeLogStr("Orders count: " . count($orders)); - - $statusesToSubmitInvoice = get_option('ssbhesabix_invoice_status'); - $statusesToSubmitInvoice = implode(',', $statusesToSubmitInvoice); - $statusesToSubmitReturnInvoice = get_option('ssbhesabix_invoice_return_status'); - $statusesToSubmitReturnInvoice = implode(',', $statusesToSubmitReturnInvoice); - $statusesToSubmitPayment = get_option('ssbhesabix_payment_status'); - $statusesToSubmitPayment = implode(',', $statusesToSubmitPayment); - - $id_orders = array(); - foreach ($orders as $order) { - //$order = new WC_Order($order->ID); - $order = wc_get_order($order->ID); - - $id_order = $order->get_id(); - $id_obj = $wpFaService->getWpFaId('order', $id_order); - $current_status = $order->get_status(); - - if (!$id_obj) { - if (strpos($statusesToSubmitInvoice, $current_status) !== false) { - if ($this->setOrder($id_order)) { - array_push($id_orders, $id_order); - $updateCount++; - - if (strpos($statusesToSubmitPayment, $current_status) !== false) - $this->setOrderPayment($id_order); - - // set return invoice - if (strpos($statusesToSubmitReturnInvoice, $current_status) !== false) { - $this->setOrder($id_order, 2, $this->getInvoiceCodeByOrderId($id_order)); - } - } - } - } else { - if (strpos($statusesToSubmitPayment, $current_status) !== false) - $this->setOrderPayment($id_order); - } - } - - $result["batch"] = $batch; - $result["totalBatch"] = $totalBatch; - $result["total"] = $total; - $result["updateCount"] = $updateCount; - return $result; - } -//======================================================================================================================== - public function syncProducts($batch, $totalBatch, $total) - { - try { - HesabixLogService::writeLogStr("Sync products price and quantity from hesabix to store: part $batch"); - $result = array(); - $result["error"] = false; - $extraSettingRPP = get_option("ssbhesabix_set_rpp_for_sync_products_into_woocommerce"); - - $rpp=200; - if($extraSettingRPP) { - if($extraSettingRPP != '-1' && $extraSettingRPP != '0') { - $rpp=$extraSettingRPP; - } - } - - $hesabix = new Ssbhesabix_Api(); - $filters = array(array("Property" => "khadamat", "Operator" => "=", "Value" => 0)); - - if ($batch == 1) { - $response = $hesabix->itemGetItems(array('Take' => 1, 'Filters' => $filters)); - if ($response->Success) { - $total = $response->Result->FilteredCount; - $totalBatch = ceil($total / $rpp); - } else { - HesabixLogService::log(array("Error while trying to get products for sync. Error Message: $response->ErrorMessage. Error Code: $response->ErrorCode.")); - $result["error"] = true; - return $result; - } - } - - $offset = ($batch - 1) * $rpp; - $response = $hesabix->itemGetItems(array('Skip' => $offset, 'Take' => $rpp, 'SortBy' => 'Id', 'Filters' => $filters)); - - $warehouse = get_option('ssbhesabix_item_update_quantity_based_on', "-1"); - - if ($warehouse != "-1") { - $products = $response->Result->List; - $codes = []; - foreach ($products as $product) - $codes[] = $product->Code; - $response = $hesabix->itemGetQuantity($warehouse, $codes); - } - - if ($response->Success) { - $products = $warehouse == "-1" ? $response->Result->List : $response->Result; - foreach ($products as $product) { - self::setItemChanges($product); - } - } else { - HesabixLogService::log(array("Error while trying to get products for sync. Error Message: $response->ErrorMessage. Error Code: $response->ErrorCode.")); - $result["error"] = true; - return $result; - } - - $result["batch"] = $batch; - $result["totalBatch"] = $totalBatch; - $result["total"] = $total; - return $result; - } catch (Error $error) { - HesabixLogService::writeLogStr("Error in sync products: " . $error->getMessage()); - } - } -//======================================================================================================================== - public function syncProductsManually($data) - { - HesabixLogService::writeLogStr('Sync Products Manually'); - - $hesabix_item_codes = array(); - foreach ($data as $d) { - if ($d["hesabix_id"]) { - $hesabix_item_codes[] = str_pad($d["hesabix_id"], 6, "0", STR_PAD_LEFT); - } - } - - $hesabix = new Ssbhesabix_Api(); - - $filters = array(array("Property" => "Code", "Operator" => "in", "Value" => $hesabix_item_codes)); - $response = $hesabix->itemGetItems(array('Take' => 100, 'Filters' => $filters)); - - if ($response->Success) { - $products = $response->Result->List; - $products_codes = array(); - foreach ($products as $product) - $products_codes[] = $product->Code; - $diff = array_diff($hesabix_item_codes, $products_codes); - if (is_array($diff) && count($diff) > 0) { - return array("result" => false, "data" => $diff); - } - } - - $id_product_array = array(); - global $wpdb; - - foreach ($data as $d) { - $row = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id_ps_attribute` = " . $d["id"] . " AND `obj_type` = 'product'"); - - if (!is_object($row)) { - $row = $wpdb->get_row("SELECT * FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id_ps` = " . $d["id"] . " AND `obj_type` = 'product'"); - } - if (is_object($row)) { - if (!$d["hesabix_id"]) - $wpdb->delete($wpdb->prefix . 'ssbhesabix', array('id' => $row->id)); - else - $wpdb->update($wpdb->prefix . 'ssbhesabix', array('id_hesabix' => $d["hesabix_id"]), array('id' => $row->id)); - } else { - if (!$d["hesabix_id"]) - continue; - if ($d["parent_id"]) - $wpdb->insert($wpdb->prefix . 'ssbhesabix', array('obj_type' => 'product', 'id_hesabix' => $d["hesabix_id"], 'id_ps' => $d["parent_id"], 'id_ps_attribute' => $d["id"])); - else - $wpdb->insert($wpdb->prefix . 'ssbhesabix', array('obj_type' => 'product', 'id_hesabix' => $d["hesabix_id"], 'id_ps' => $d["id"], 'id_ps_attribute' => '0')); - } - - if ($d["hesabix_id"]) { - if ($d["parent_id"]) { - if (!in_array($d["parent_id"], $id_product_array)) - $id_product_array[] = $d["parent_id"]; - } else { - if (!in_array($d["id"], $id_product_array)) - $id_product_array[] = $d["id"]; - } - } - } - - $this->setItems($id_product_array); - return array("result" => true, "data" => null); - } -//======================================================================================================================== - public function updateProductsInHesabixBasedOnStore($batch, $totalBatch, $total) - { - HesabixLogService::writeLogStr("Update Products In Hesabix Based On Store"); - $result = array(); - $result["error"] = false; - $extraSettingRPP = get_option('ssbhesabix_set_rpp_for_sync_products_into_hesabix'); - - $rpp=500; - if($extraSettingRPP) { - if($extraSettingRPP != '-1' && $extraSettingRPP != '0') { - $rpp=$extraSettingRPP; - } - } - - global $wpdb; - - if ($batch == 1) { - //$total = $wpdb->get_var("SELECT COUNT(*) FROM `" . $wpdb->prefix . "posts` WHERE post_type = 'product' AND post_status IN('publish','private')"); - - $total = $wpdb->get_var( - $wpdb->prepare( - "SELECT COUNT(*) FROM {$wpdb->posts} - WHERE post_type = 'product' AND post_status IN ('publish', 'private')" - ) - ); - $totalBatch = ceil($total / $rpp); - } - - $offset = ($batch - 1) * $rpp; -// $products = $wpdb->get_results("SELECT ID FROM `" . $wpdb->prefix . "posts` -// WHERE post_type = 'product' AND post_status IN('publish','private') ORDER BY 'ID' ASC LIMIT $offset,$rpp"); - - $products = $wpdb->get_results( - $wpdb->prepare( - "SELECT ID FROM {$wpdb->posts} - WHERE post_type = 'product' AND post_status IN ('publish', 'private') - ORDER BY ID ASC - LIMIT %d, %d", - $offset, - $rpp - ) - ); - - $products_id_array = array(); - foreach ($products as $product) - $products_id_array[] = $product->ID; - $this->setItems($products_id_array); - sleep(2); - - $result["batch"] = $batch; - $result["totalBatch"] = $totalBatch; - $result["total"] = $total; - return $result; - } -//======================================================================================================================== - public static function updateProductsInHesabixBasedOnStoreWithFilter($offset=0, $rpp=0) - { - HesabixLogService::writeLogStr("Update Products With Filter In Hesabix Based On Store"); - $result = array(); - $result["error"] = false; - - global $wpdb; - if($offset != 0 && $rpp != 0) { - if(abs($rpp - $offset) <= 200) { - if($rpp > $offset) { -// $products = $wpdb->get_results("SELECT * FROM `" . $wpdb->prefix . "posts` -// WHERE ID BETWEEN $offset AND $rpp AND post_type = 'product' AND post_status IN('publish','private') ORDER BY 'ID' ASC"); - - $products = $wpdb->get_results( - $wpdb->prepare( - "SELECT * FROM {$wpdb->posts} - WHERE ID BETWEEN %d AND %d - AND post_type = 'product' - AND post_status IN ('publish', 'private') - ORDER BY ID ASC", - $offset, - $rpp - ) - ); - - $products_id_array = array(); - foreach ($products as $product) - $products_id_array[] = $product->ID; - $response = (new Ssbhesabix_Admin_Functions)->setItems($products_id_array); - if(!$response) $result['error'] = true; - } else { -// $products = $wpdb->get_results("SELECT * FROM `" . $wpdb->prefix . "posts` -// WHERE ID BETWEEN $rpp AND $offset AND post_type = 'product' AND post_status IN('publish','private') ORDER BY 'ID' ASC"); - - $products = $wpdb->get_results( - $wpdb->prepare( - "SELECT * FROM {$wpdb->posts} - WHERE ID BETWEEN %d AND %d - AND post_type = 'product' - AND post_status IN ('publish', 'private') - ORDER BY ID ASC", - $rpp, - $offset - ) - ); - - $products_id_array = array(); - foreach ($products as $product) - $products_id_array[] = $product->ID; - $response = (new Ssbhesabix_Admin_Functions)->setItems($products_id_array); - if(!$response) $result['error'] = true; - } - } else { - $result['error'] = true; - echo ''; - } - } else { - echo ''; - } - - return $result; - } -//======================================================================================================================== - public function cleanLogFile() - { - HesabixLogService::clearLog(); - return true; - } -//======================================================================================================================== - public static function setItemChanges($item) - { - if (!is_object($item)) return false; - - if ($item->Quantity || !$item->Stock) - $item->Stock = $item->Quantity; - - $wpFaService = new HesabixWpFaService(); - global $wpdb; - - $wpFa = $wpFaService->getWpFaByHesabixId('product', $item->Code); - if (!$wpFa) return false; - - $id_product = $wpFa->idWp; - $id_attribute = $wpFa->idWpAttribute; - - if ($id_product == 0) { - HesabixLogService::log(array("Item with code: $item->Code is not defined in Online store")); - return false; - } - - //$found = $wpdb->get_var("SELECT COUNT(*) FROM `" . $wpdb->prefix . "posts` WHERE ID = $id_product"); - - $found = $wpdb->get_var( - $wpdb->prepare( - "SELECT COUNT(*) FROM {$wpdb->posts} - WHERE ID = %d", - $id_product - ) - ); - - - if (!$found) { - HesabixLogService::writeLogStr("product not found in woocommerce.code: $item->Code, product id: $id_product, variation id: $id_attribute"); - return false; - } - - $product = wc_get_product($id_product); - $variation = $id_attribute != 0 ? wc_get_product($id_attribute) : null; - - -// $product = new WC_Product($id_product); -// $variation = $id_attribute != 0 ? new WC_Product($id_attribute) : null; - - $result = array(); - $result["newPrice"] = null; - $result["newQuantity"] = null; - - $p = $variation ? $variation : $product; - - if (get_option('ssbhesabix_item_update_price') == 'yes') - $result = self::setItemNewPrice($p, $item, $id_attribute, $id_product, $result); - - if (get_option('ssbhesabix_item_update_quantity') == 'yes') - $result = self::setItemNewQuantity($p, $item, $id_product, $id_attribute, $result); - - return $result; - } -//======================================================================================================================== - private static function setItemNewPrice($product, $item, $id_attribute, $id_product, array $result) - { - try { - $option_sale_price = get_option('ssbhesabix_item_update_sale_price', 0); - $woocommerce_currency = get_woocommerce_currency(); - $hesabix_currency = get_option('ssbhesabix_hesabix_default_currency'); - - $old_price = $product->get_regular_price() ? $product->get_regular_price() : $product->get_price(); - $old_price = Ssbhesabix_Admin_Functions::getPriceInHesabixDefaultCurrency($old_price); - - $post_id = $id_attribute && $id_attribute > 0 ? $id_attribute : $id_product; - - if ($item->SellPrice != $old_price) { - $new_price = Ssbhesabix_Admin_Functions::getPriceInWooCommerceDefaultCurrency($item->SellPrice); - update_post_meta($post_id, '_regular_price', $new_price); - update_post_meta($post_id, '_price', $new_price); - - - $sale_price = $product->get_sale_price(); - if ($sale_price && is_numeric($sale_price)) { - $sale_price = Ssbhesabix_Admin_Functions::getPriceInHesabixDefaultCurrency($sale_price); - if (+$option_sale_price === 1) { - update_post_meta($post_id, '_sale_price', null); - } elseif (+$option_sale_price === 2) { - update_post_meta($post_id, '_sale_price', round(($sale_price * $new_price) / $old_price)); - update_post_meta($post_id, '_price', round(($sale_price * $new_price) / $old_price)); - } else { - if($woocommerce_currency == 'IRT' && $hesabix_currency == 'IRR') update_post_meta($post_id, '_price', ($sale_price/10)); - elseif($woocommerce_currency == 'IRR' && $hesabix_currency == 'IRT') update_post_meta($post_id, '_price', ($sale_price*10)); - elseif($woocommerce_currency == 'IRR' && $hesabix_currency == 'IRR') update_post_meta($post_id, '_price', $sale_price); - elseif($woocommerce_currency == 'IRT' && $hesabix_currency == 'IRT') update_post_meta($post_id, '_price', $sale_price); - } - } - - HesabixLogService::log(array("product ID $id_product-$id_attribute Price changed. Old Price: $old_price. New Price: $new_price")); - $result["newPrice"] = $new_price; - } - - return $result; - } catch (Error $error) { - HesabixLogService::writeLogStr("Error in Set Item New Price -> $error"); - } - } -//======================================================================================================================== - private static function setItemNewQuantity($product, $item, $id_product, $id_attribute, array $result) - { - try { - $old_quantity = $product->get_stock_quantity(); - if ($item->Stock != $old_quantity) { - $new_quantity = $item->Stock; - if (!$new_quantity) $new_quantity = 0; - - $new_stock_status = ($new_quantity > 0) ? "instock" : "outofstock"; - - $post_id = ($id_attribute && $id_attribute > 0) ? $id_attribute : $id_product; - -// update_post_meta($post_id, '_stock', $new_quantity); -// wc_update_product_stock_status($post_id, $new_stock_status); - - $product = wc_get_product( $post_id ); - if ( $product ) { - - $product->set_stock_quantity( $new_quantity ); - $product->set_stock_status( $new_stock_status ); - $product->save(); - HesabixLogService::log(array("product ID $id_product-$id_attribute quantity changed. Old quantity: $old_quantity. New quantity: $new_quantity")); - $result["newQuantity"] = $new_quantity; - } - } - - return $result; - } catch (Error $error) { - HesabixLogService::writeLogStr("Error in Set Item New Quantity -> $error"); - } - } -//========================================================================================================================= - public static function syncLastChangeID(): bool { - try { - HesabixLogService::writeLogStr("Sync Last Change ID"); - $hesabixApi = new Ssbhesabix_Api(); - $lastChange = $hesabixApi->getLastChangeId(); - - if ($lastChange && isset($lastChange->LastId)) { - update_option('ssbhesabix_last_log_check_id', $lastChange->LastId - 1); - return true; - } - } catch (Exception $error) { - HesabixLogService::writeLogStr("Error in syncing last change id -> " . $error->getMessage()); - } - - return false; - } -//========================================================================================================================= - public static function SaveProductManuallyToHesabix($woocommerceCode, $attributeId, $hesabixCode): bool { - //check no record exist in hesabix - $isProductExistInHesabix = self::CheckExistenceOfTheProductInHesabix($hesabixCode); - if(!$isProductExistInHesabix) { - $isProductValidInWoocommerce = self::CheckValidityOfTheProductInWoocommerce($woocommerceCode, $attributeId, $hesabixCode); - if($isProductValidInWoocommerce) { - //get product - $product = wc_get_product($woocommerceCode); - if($attributeId != 0) $variation = wc_get_product($attributeId); - - if($attributeId == 0) { - $hesabixItem = ssbhesabixItemService::mapProduct($product, $woocommerceCode); - } else { - $hesabixItem = ssbhesabixItemService::mapProductVariation($product, $variation, $woocommerceCode); - } - - //save product to hesabix and make a new link - $api = new Ssbhesabix_Api(); - $hesabixItem["Code"] = $hesabixCode; - $response = $api->itemSave($hesabixItem); - if($response->Success) { - if($attributeId == 0) $productCode = $woocommerceCode; else $productCode = $attributeId; - HesabixLogService::log(array("Item successfully added to Hesabix. Hesabix code: " . $hesabixCode . " - Product code: " . $productCode)); - - $wpFaService = new HesabixWpFaService(); - $wpFa = $wpFaService->getWpFa('product', $woocommerceCode, $attributeId); - if (!$wpFa) { - $wpFa = new WpFa(); - $wpFa->idHesabix = $hesabixCode; - $wpFa->idWp = $woocommerceCode; - $wpFa->idWpAttribute = $attributeId; - $wpFa->objType = 'product'; - $wpFaService->save($wpFa); - HesabixLogService::log(array("Item successfully added. Hesabix code: " . (string)$hesabixCode . ". Product ID: $woocommerceCode - $attributeId")); - return true; - } - } else { - HesabixLogService::log(array("Error in saving product to hesabix. Hesabix given code: " . $hesabixCode)); - return false; - } - } - } - - return false; - } -//========================================================================================================================= - public static function CheckExistenceOfTheProductInHesabix($hesabixCode): bool { - $api = new Ssbhesabix_Api(); - $response = $api->itemGet($hesabixCode); - if($response->Success) { - HesabixLogService::writeLogStr("کالا با کد(" . $hesabixCode . ") در حسابیکس موجود است."); - return true; - } else if($response->ErrorCode == "112") { - return false; - } else { - HesabixLogService::writeLogStr("Error in getting the existence of the product"); - return true; - } - } -//========================================================================================================================= - public static function CheckValidityOfTheProductInWoocommerce($woocommerceCode, $attributeId, $hesabixCode): bool { - //check not exist in link table - $wpFaService = new HesabixWpFaService(); - $code = $wpFaService->getProductCodeByWpId($woocommerceCode, $attributeId); - if ($code) { - HesabixLogService::writeLogStr("این کد حسابیکسی وارد شده به کالای دیگری متصل است." . $code . " - " . $woocommerceCode . " - " . $attributeId); - return false; - } - - //check woocommerce code exists - global $wpdb; - - if($attributeId != 0) $productId = $attributeId; - else $productId = $woocommerceCode; - - $found = $wpdb->get_var( - $wpdb->prepare( - "SELECT COUNT(*) FROM {$wpdb->posts} - WHERE ID = %d", - $productId - ) - ); - - if($found) { - //product is valid - return true; - } else { - HesabixLogService::writeLogStr("product not found in woocommerce. Given product code: " . $woocommerceCode . "-" . $attributeId ); - return false; - } - } -//========================================================================================================================= - function checkNationalCode($NationalCode): void - { - $identicalDigits = ['1111111111', '2222222222', '3333333333', '4444444444', '5555555555', '6666666666', '7777777777', '8888888888', '9999999999']; - - if(strlen($NationalCode) === 10) { - $summation = 0; - $j = 10; - for($i = 0 ; $i < 9 ; $i++) { - $digit = substr($NationalCode, $i, 1); - $temp = $digit * $j; - $j -= 1; - $summation += $temp; - } - $controlDigit = substr($NationalCode, 9, 1); - $retrieve = $summation % 11; - - if(in_array($NationalCode, $identicalDigits) === false) { - if($retrieve < 2) { - if($controlDigit != $retrieve) { - wc_add_notice(__('please enter a valid national code', 'ssbhesabix'), 'error'); - } - } else { - if($controlDigit != (11 - $retrieve)) { - wc_add_notice(__('please enter a valid national code', 'ssbhesabix'), 'error'); - } - } - } - } else { - wc_add_notice(__('please enter a valid national code', 'ssbhesabix'), 'error'); - } - } -//========================================================================================================================= - public function checkNationalCodeWithPhone($nationalCode, $billingPhone): bool { - $api = new Ssbhesabix_Api(); - - $formattedPhoneNumber = $this->convertPersianPhoneDigitsToEnglish($billingPhone); - $formattedPhoneNumber = $this->formatPhoneNumber($formattedPhoneNumber); - - $response = $api->checkMobileAndNationalCode($nationalCode, $formattedPhoneNumber); - if($response->Success) { - if($response->Result->Status == 1) { - return $response->Result->Data->Matched; - } else { - return false; - } - } else { - HesabixLogService::writeLogStr('Error Occurred in Checking Mobile and NationalCode. ErrorCode: ' . $response->ErrorCode . " - ErrorMessage: " . $response->ErrorMessage); - return false; - } - } -//========================================================================================================================= - function checkWebsite($Website): void - { - if (filter_var($Website, FILTER_VALIDATE_URL)) { - // - } else { - wc_add_notice(__('please enter a valid Website URL', 'ssbhesabix'), 'error'); - } - } -//========================================================================================================================= - public static function enableDebugMode(): void { - update_option('ssbhesabix_debug_mode', 1); - } - - public static function disableDebugMode(): void { - update_option('ssbhesabix_debug_mode', 0); - } -//========================================================================================================================= - function formatPhoneNumber($phoneNumber) { - $phoneNumber = preg_replace('/\D/', '', $phoneNumber); - - if (substr($phoneNumber, 0, 2) == '98') { - $phoneNumber = substr($phoneNumber, 2); - } - - if (substr($phoneNumber, 0, 1) == '9' && strlen($phoneNumber) == 10) { - $phoneNumber = '0' . $phoneNumber; - } - - if (strlen($phoneNumber) == 10 && substr($phoneNumber, 0, 1) == '9') { - $phoneNumber = '0' . $phoneNumber; - } - - return $phoneNumber; - } -//========================================================================================================================= - public function convertPersianPhoneDigitsToEnglish($inputString) : string { - $newNumbers = range(0, 9); - $persianDecimal = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'); - $arabicDecimal = array('٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'); - $arabic = array('٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'); - $persian = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'); - - $string = str_replace($persianDecimal, $newNumbers, $inputString); - $string = str_replace($arabicDecimal, $newNumbers, $string); - $string = str_replace($persian, $newNumbers, $string); - - return str_replace($arabic, $newNumbers, $string); - } -//========================================================================================================================= - public function convertPersianDigitsToEnglish($inputString) : int { - $newNumbers = range(0, 9); - $persianDecimal = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'); - $arabicDecimal = array('٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'); - $arabic = array('٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'); - $persian = array('۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'); - - $string = str_replace($persianDecimal, $newNumbers, $inputString); - $string = str_replace($arabicDecimal, $newNumbers, $string); - $string = str_replace($persian, $newNumbers, $string); - - return str_replace($arabic, $newNumbers, $string); - } -//========================================================================================================================= - function generateGUID() : string { - $characters = '0123456789ABCDEF'; - $guid = ''; - - for ($i = 0; $i < 32; $i++) { - $guid .= $characters[mt_rand(0, 15)]; - if ($i == 7 || $i == 11 || $i == 15 || $i == 19) { - $guid .= '-'; - } - } - - return $guid; - } -//========================================================================================================================= - public function getGUID($id_order): string { - $option = get_option($id_order); - - if ($option === false || $option == 0) { - $GUID = $this->generateGUID(); - $expirationDateTime = new DateTime('now', new DateTimeZone('UTC')); - add_option($id_order, $expirationDateTime->format('Y-m-d H:i:s') . $GUID); - } else { - $expirationDateTime = new DateTime(substr($option, 0, 19), new DateTimeZone('UTC')); - $currentDateTime = new DateTime('now', new DateTimeZone('UTC')); - - $diff = $currentDateTime->diff($expirationDateTime); - - if ($diff->days < 1) { - // GUID is still valid, continue processing - } else { - // GUID expired, reset the option to allow saving a new invoice - $GUID = $this->generateGUID(); - $expirationDateTime = new DateTime('now', new DateTimeZone('UTC')); - update_option($id_order, $expirationDateTime->format('Y-m-d H:i:s') . $GUID); - } - } - - return substr(get_option($id_order), 20); - } -//========================================================================================================================= - public function formatTransactionFee($transactionFee, $amount) { - if($transactionFee && $transactionFee > 0) { - $func = new Ssbhesabix_Admin_Functions(); - $transactionFee = $func->convertPersianDigitsToEnglish($transactionFee); - - if($transactionFee<100 && $transactionFee>0) $transactionFee /= 100; - $transactionFee *= $amount; - if($transactionFee < 1) $transactionFee = 0; - } - return $transactionFee; - } -//========================================================================================================================= - public function convertCityCodeToName($cityCode) { - $citiesArray = [ - 1 => [ - 'title' => 'تهران', - 'cities' => [ - 1 => 'تهران', - 331 => 'اسلام شهر', - 1813 => 'ری', - 3341 => 'لواسان', - 3351 => 'شهریار', - 3371 => 'ورامین', - 3381 => 'پیشوا', - 3391 => 'پاکدشت', - 3751 => 'قدس', - 3761 => 'رباطکریم', - 3971 => 'دماوند', - 3981 => 'فیروزکوه', - 16531 => 'جاجرود (خسروآباد)', - 16551 => 'بومهن', - 16571 => 'شهرصنعتی خرمدشت', - 16581 => 'پردیس', - 18131 => 'باقر شهر', - 18141 => 'جعفرابادباقراف', - 18151 => 'مرقدامام ره', - 18161 => 'کهریزک', - 18171 => 'طورقوزاباد', - 18181 => 'قاسم ابادشوراباد', - 18191 => 'قمصر', - 18331 => 'حسن آباد', - 18341 => 'شمس اباد', - 18351 => 'ابراهیم اباد', - 18361 => 'چرمشهر', - 18371 => 'قلعه محمدعلی خان', - 18381 => 'فرودگاه امام خمینی', - 18391 => 'وهن اباد', - 18441 => 'قلعه نوخالصه', - 18451 => 'گل تپه کبیر', - 18461 => 'محمودابادپیرزاده', - 18471 => 'فرون اباد', - 18631 => 'خاورشهر', - 18641 => 'اسلام اباد', - 18651 => 'لپه زنگ', - 18661 => 'قیامدشت', - 18686 => 'قرچک', - 18791 => 'قوچ حصار', - 18986 => 'خلازیر', - 19338 => 'تجریش', - 31130 => 'نصیرشهر', - 31133 => 'شهرک صنعتی نصیرشهر', - 31136 => 'شهرک قلعه میر', - 31641 => 'صفادشت', - 31686 => 'اندیشه', - 31691 => 'ملارد', - 31694 => 'گرمدره', - 33131 => 'احمدابادمستوفی', - 33141 => 'فیروزبهرام', - 33151 => 'گلدسته', - 33171 => 'صالح آباد', - 33186 => 'شاطره', - 33191 => 'چهاردانگه', - 33361 => 'سعیدآباد', - 33451 => 'فشم', - 33461 => 'لواسان بزرگ', - 33541 => 'باغستان', - 33560 => 'صباشهر', - 33561 => 'شاهدشهر', - 33571 => 'فردوسیه', - 33581 => 'وحیدیه', - 33591 => 'لم اباد', - 33711 => 'قلعه سین', - 33741 => 'عسگرابادعباسی', - 33751 => 'دهماسین', - 33761 => 'باغخواص', - 33771 => 'ایجدان', - 33781 => 'ابباریک', - 33831 => 'جواد آباد', - 33841 => 'خاوه', - 33861 => 'جلیل اباد', - 33871 => 'کریم اباد', - 33881 => 'قلعه خواجه', - 33930 => 'شهرک عباس آباد', - 33931 => 'داوداباد', - 33941 => 'شریف آباد', - 33971 => 'پارچین', - 33981 => 'حصارامیر', - 33991 => 'خاتون اباد', - 37551 => 'نصیرآباد', - 37571 => 'گلستان', - 37581 => 'کلمه', - 37611 => 'پرند', - 37614 => 'شهر صنعتی پرند', - 37631 => 'سلطان اباد', - 37650 => 'حصارک پایین', - 37651 => 'نسیم شهر', - 37652 => 'حصارک بالا', - 37653 => 'سبزدشت', - 37656 => 'احمدآبادجانسپار', - 37661 => 'اسماعیل آباد', - 39720 => 'جابان', - 39731 => 'رودهن', - 39741 => 'آبعلی', - 39751 => 'کیلان', - 39761 => 'آبسرد', - 39771 => 'سربندان', - 39780 => 'مهرآباد', - 39781 => 'مشا', - 39791 => 'مرا', - 39811 => 'هرانده', - 39831 => 'درده', - 39841 => 'حصاربن', - 39851 => 'ارجمند', - 39861 => 'امیریه', - ], - ], - 2 => [ - 'title' => 'گيلان', - 'cities' => [ - 41 => 'رشت', - 431 => 'بندرانزلی', - 441 => 'لاهیجان', - 4331 => 'ابکنار', - 4341 => 'خمام', - 4351 => 'فومن', - 4361 => 'صومعه سرا', - 4371 => 'هشتپر', - 4381 => 'ماسال', - 4391 => 'آستارا', - 4431 => 'سیاهکل', - 4441 => 'آستانه اشرفیه', - 4451 => 'منجیل', - 4461 => 'رودبار', - 4471 => 'لنگرود', - 4481 => 'رودسر', - 4491 => 'کلاچای', - 43331 => 'کپورچال', - 43341 => 'جیرهنده', - 43351 => 'لیچارکی حسن رود', - 43361 => 'سنگر', - 43381 => 'سراوان', - 43391 => 'خشکبیجار', - 43431 => 'لشت نشاء', - 43451 => 'خواچکین', - 43461 => 'کوچصفهان', - 43471 => 'بلسبنه', - 43481 => 'چاپارخانه', - 43491 => 'جیرکویه', - 43513 => 'ماکلوان', - 43531 => 'لولمان', - 43541 => 'شفت', - 43551 => 'ملاسرا', - 43561 => 'چوبر', - 43571 => 'ماسوله', - 43581 => 'گشت', - 43591 => 'احمد سر گوراب', - 43631 => 'مرجقل', - 43641 => 'گوراب زرمیخ', - 43651 => 'طاهرگوراب', - 43661 => 'ضیابر', - 43671 => 'مرکیه', - 43681 => 'هنده خاله', - 43691 => 'نوخاله اکبری', - 43741 => 'شیله وشت', - 43751 => 'جوکندان بزرگ', - 43761 => 'لیسار', - 43771 => 'بازارخطبه سرا', - 43780 => 'چوبر', - 43781 => 'حویق', - 43791 => 'پلاسی', - 43811 => 'بازار جمعه', - 43841 => 'رضوانشهر', - 43861 => 'پره سر', - 43871 => 'پلنگ پاره', - 43891 => 'اسالم', - 43931 => 'شیخ محله', - 43941 => 'ویرمونی', - 43951 => 'سیبلی', - 43961 => 'لوندویل', - 43971 => 'مشند', - 43981 => 'کوته کومه', - 43991 => 'حیران', - 44141 => 'رودبنه', - 44331 => 'پایین محله پاشاکی', - 44341 => 'گرماور', - 44351 => 'لیش', - 44361 => 'بارکوسرا', - 44371 => 'شیرین نسا', - 44381 => 'خرارود', - 44391 => 'دیلمان', - 44431 => 'لسکوکلایه', - 44441 => 'کیسم', - 44451 => 'شیرکوه چهارده', - 44461 => 'دهشال', - 44471 => 'کیاشهر', - 44481 => 'دستک', - 44491 => 'پرگاپشت مهدی خانی', - 44531 => 'لوشان', - 44541 => 'بیورزین', - 44551 => 'جیرنده', - 44561 => 'بره سر', - 44581 => 'ویشان', - 44591 => 'کلیشم', - 44631 => 'علی اباد', - 44641 => 'رستم آباد', - 44651 => 'توتکابن', - 44661 => 'کلشتر', - 44681 => 'اسکولک', - 44691 => 'کوکنه', - 44731 => 'سلوش', - 44741 => 'چاف وچمخاله', - 44751 => 'شلمان', - 44761 => 'کومله', - 44771 => 'دیوشل', - 44781 => 'پروش پایین', - 44791 => 'اطاقور', - 44841 => 'حسن سرا', - 44851 => 'طول لات', - 44861 => 'رانکوه', - 44871 => 'چابکسر', - 44881 => 'جنگ سرا', - 44891 => 'واجارگاه', - 44931 => 'رحیم آباد', - 44941 => 'بلترک', - 44951 => 'املش', - 44971 => 'کجید', - 44981 => 'گرمابدشت', - 44991 => 'شوییل', - 44992 => 'پونل', - ], - ], - 3 => [ - 'title' => 'آذربايجان شرقي', - 'cities' => [ - 51 => 'تبریز', - 531 => 'میانه', - 541 => 'مرند', - 551 => 'مراغه', - 5331 => 'شهرجدیدسهند', - 5351 => 'اسکو', - 5361 => 'سردرود', - 5371 => 'آذر شهر', - 5381 => 'شبستر', - 5391 => 'هریس', - 5431 => 'هادیشهر', - 5441 => 'جلفا', - 5451 => 'اهر', - 5461 => 'کلیبر', - 5471 => 'سراب', - 5491 => 'بستان آباد', - 5541 => 'عجب شیر', - 5551 => 'بناب', - 5561 => 'ملکان', - 5571 => 'هشترود', - 5581 => 'قره آغاج', - 5586 => 'اغچه ریش', - 53331 => 'ترک', - 53351 => 'ترکمانچای', - 53361 => 'خاتون اباد', - 53371 => 'شیخدراباد', - 53381 => 'قره بلاغ', - 53391 => 'آقکند', - 53431 => 'اچاچی', - 53441 => 'گوندوغدی', - 53451 => 'پورسخلو', - 53461 => 'کنگاور', - 53481 => 'قویوجاق', - 53491 => 'ارموداق', - 53531 => 'کهنمو', - 53541 => 'اربط', - 53551 => 'خسرو شهر', - 53561 => 'لاهیجان', - 53571 => 'خاص اباد (خاصبان)', - 53581 => 'ایلخچی', - 53591 => 'سرای (سرای ده)', - 53631 => 'کجوار', - 53641 => 'خلجان', - 53651 => '(ینگی اسپران (سفیدان جد', - 53661 => 'باسمنج', - 53671 => '(شادبادمشایخ (پینه شلوا', - 53681 => 'کندرود', - 53691 => 'مایان سفلی', - 53731 => 'تیمورلو', - 53740 => 'خراجو', - 53741 => 'قدمگاه (بادام یار)', - 53751 => 'ممقان', - 53761 => 'گوگان', - 53771 => 'شیرامین', - 53791 => 'هفت چشمه', - 53811 => 'وایقان', - 53831 => 'امند', - 53840 => 'کوزه کنان', - 53841 => 'خامنه', - 53851 => 'سیس', - 53861 => 'صوفیان', - 53871 => 'شند آباد', - 53881 => 'تسوج', - 53891 => 'شرفخانه', - 53941 => 'مینق', - 53950 => 'کلوانق', - 53951 => 'بخشایش', - 53961 => 'سرند', - 53971 => 'زرنق', - 53981 => 'بیلوردی', - 53991 => 'خواجه', - 54331 => 'گلین قیه', - 54341 => 'هرزندجدید (چای هرزند)', - 54351 => 'بناب جدید', - 54361 => 'زنوز', - 54371 => 'دولت اباد', - 54381 => 'یکان کهریز', - 54391 => 'یامچی', - 54431 => 'شجاع', - 54441 => 'داران', - 54451 => 'سیه رود', - 54461 => 'نوجه مهر', - 54471 => 'کشکسرای', - 54481 => 'خاروانا', - 54491 => 'هوراند', - 54531 => 'چول قشلاقی', - 54541 => 'ورگهان', - 54551 => 'افیل', - 54561 => 'اذغان (ازغان)', - 54571 => 'سیه کلان', - 54581 => 'ورزقان', - 54591 => 'اق براز', - 54631 => 'مولان', - 54641 => 'خمارلو', - 54651 => 'عاشقلو', - 54661 => 'اسکلو (اسگلو)', - 54671 => 'آبش احمد', - 54681 => 'یوزبند', - 54682 => 'شهرک صنعتی کاغذکنان', - 54685 => 'کندوان', - 54686 => 'تیل', - 54691 => 'لاریجان', - 54731 => 'اسبفروشان', - 54741 => 'ابرغان', - 54750 => 'دوزدوزان', - 54751 => 'شربیان', - 54761 => 'مهربان', - 54771 => 'رازلیق', - 54781 => 'اغمیون', - 54791 => 'اردها', - 54931 => 'قره چای حاج علی', - 54941 => 'قره بابا', - 54951 => 'سعیداباد', - 54961 => 'الانق', - 54971 => 'کردکندی', - 54981 => 'تیکمه داش', - 54991 => 'قره چمن', - 55330 => 'ورجوی', - 55341 => 'گل تپه', - 55351 => 'خداجو', - 55361 => 'داش اتان', - 55371 => 'داش بلاغ بازار', - 55381 => 'صومعه', - 55391 => 'علویان', - 55431 => 'شیراز', - 55441 => 'خضرلو', - 55451 => 'ینگجه', - 55461 => 'مهماندار', - 55471 => 'خانیان', - 55481 => 'دانالو', - 55491 => 'رحمانلو', - 55531 => 'زاوشت', - 55541 => 'القو', - 55551 => 'روشت بزرگ', - 55561 => 'خوشه مهر (خواجه امیر)', - 55571 => 'زوارق', - 55581 => '(خانه برق قدیم (شورخانه ب', - 55631 => 'لکلر', - 55641 => 'بایقوت', - 55651 => 'اروق', - 55661 => 'اق منار', - 55671 => 'لیلان', - 55681 => 'طوراغای (طوراغایی)', - 55731 => 'اوشندل', - 55741 => 'علی ابادعلیا', - 55751 => 'ذوالبین', - 55761 => 'نظر کهریزی', - 55771 => 'اتش بیگ', - 55781 => 'سلوک', - 55791 => 'نصیرابادسفلی', - 55831 => 'ارسگنای سفلی', - 55841 => '(سلطان اباد (س انمکزار', - 55851 => 'قلعه حسین اباد', - 55871 => 'ذاکرکندی', - 55881 => 'قوچ احمد', - 55891 => 'اغ زیارت', - ], - ], - 4 => [ - 'title' => 'خوزستان', - 'cities' => [ - 61 => 'اهواز', - 631 => 'آبادان', - 641 => 'خرمشهر', - 6331 => 'اروندکنار', - 6341 => 'ملاثانی', - 6351 => 'بندرماهشهر', - 6361 => 'بهبهان', - 6371 => 'آغاجاری', - 6381 => 'رامهرمز', - 6391 => 'ایذه', - 6431 => 'شادگان', - 6441 => 'سوسنگرد', - 6451 => 'شوشتر', - 6461 => 'دزفول', - 6471 => 'شوش', - 6481 => 'اندیمشک', - 6491 => 'مسجدسلیمان', - 61431 => 'الهائی', - 61481 => 'شیبان', - 61491 => 'ویس', - 63331 => 'فیاضی', - 63341 => 'تنگ یک', - 63351 => 'چوئبده', - 63361 => 'نهرسلیم', - 63381 => 'نهرابطر', - 63431 => 'عین دو', - 63441 => 'حمیدیه', - 63451 => 'ام الطمیر (سیدیوسف)', - 63461 => 'کوت عبدالله', - 63471 => 'قلعه چنعان', - 63481 => 'کریت برومی', - 63491 => 'غیزانیه بزرگ', - 63531 => 'چم کلگه', - 63541 => 'چمران', - 63561 => 'بندرامام خمینی', - 63571 => 'صالح شهر', - 63581 => 'اسیاب', - 63591 => 'هندیجان', - 63640 => 'تشان', - 63641 => 'گروه پدافندهوایی بهبها', - 63651 => 'شاه غالب ده ابراهیم', - 63661 => 'کردستان بزرگ', - 63671 => 'منصوریه', - 63681 => 'سردشت', - 63731 => 'امیدیه', - 63751 => 'میانکوه', - 63771 => 'زهره', - 63831 => 'رودزرد', - 63851 => 'نفت سفید', - 63861 => 'مشراگه', - 63871 => 'رامشیر', - 63881 => 'جایزان', - 63891 => 'دره تونم نمی', - 63931 => 'میداود', - 63941 => 'صیدون', - 63951 => 'باغ ملک', - 63961 => 'قلعه تل', - 63971 => 'چنارستان', - 63981 => 'پشت پیان', - 63991 => 'دهدز', - 64330 => 'خنافره', - 64331 => 'عبودی', - 64341 => 'دارخوین', - 64351 => 'درویشی', - 64361 => 'بوزی سیف', - 64371 => 'مینوشهر', - 64381 => 'حفاری شرقی', - 64431 => 'بروایه یوسف', - 64440 => 'کوت سیدنعیم', - 64441 => 'ابوحمیظه', - 64451 => 'هویزه', - 64461 => 'یزدنو', - 64471 => 'رفیع', - 64481 => 'بستان', - 64491 => 'سیدعباس', - 64510 => 'سرداران', - 64511 => 'شرافت', - 64531 => 'گوریه', - 64541 => 'جنت مکان', - 64551 => 'گتوند', - 64560 => 'ترکالکی', - 64561 => 'سماله', - 64571 => 'شهرک نورمحمدی', - 64581 => 'گاومیش اباد', - 64591 => 'عرب حسن', - 64631 => 'صفی آباد', - 64640 => 'چغامیش', - 64641 => 'حمزه', - 64650 => 'شمس آباد', - 64651 => 'امام', - 64652 => 'سیاه منصور', - 64661 => 'میانرود', - 64681 => 'چلون', - 64691 => 'سالند', - 64730 => 'حر', - 64731 => 'شاوور', - 64741 => 'مزرعه یک', - 64751 => 'خسرجی راضی حمد', - 64761 => 'الوان', - 64771 => 'علمه تیمورابوذرغفاری', - 64781 => 'شهرک بهرام', - 64791 => 'فتح المبین', - 64830 => 'آزادی', - 64831 => 'شهرک انصار', - 64841 => 'خواجوی', - 64850 => 'بیدروبه', - 64851 => 'حسینیه', - 64861 => 'کلگه دره دو', - 64871 => 'تله زنگ پایین', - 64881 => 'چم گلک', - 64931 => 'روستای عنبر', - 64941 => 'لالی', - 64951 => 'دره بوری', - 64961 => 'هفتگل', - 64971 => 'کوشکک', - 64980 => 'آبژدان', - 64981 => 'قلعه خواجه', - 64991 => 'گلگیر', - ], - ], - 5 => [ - 'title' => 'فارس', - 'cities' => [ - 71 => 'شیراز', - 731 => 'کازرون', - 741 => 'جهرم', - 7331 => 'قائمیه', - 7341 => 'زرقان', - 7351 => 'نور آباد', - 7361 => 'اردکان', - 7371 => 'مرودشت', - 7381 => 'اقلید', - 7391 => 'آباده', - 7431 => 'لار', - 7441 => 'گراش', - 7451 => 'استهبان', - 7461 => 'فسا', - 7471 => 'فیروز آباد', - 7481 => 'داراب', - 7491 => 'نی ریز', - 71431 => 'بندامیر', - 71451 => 'خیرابادتوللی', - 71461 => 'داریان', - 71491 => 'کم جان', - 71551 => 'شوریجه', - 71561 => 'مهارلو', - 71571 => 'کوهنجان', - 71581 => 'سلطان آباد', - 71591 => 'تفیهان', - 71641 => 'طسوج', - 71651 => 'اکبراباد', - 71661 => 'مظفری', - 71671 => 'کوشک بیدک', - 71681 => 'فتح اباد', - 71691 => 'ده شیب', - 71741 => 'خانه زنیان', - 71781 => 'پاسگاه چنارراهدار', - 71881 => 'موردراز', - 71991 => 'شهرجدیدصدرا', - 73131 => 'کلاتون', - 73141 => 'کلانی', - 73151 => 'کمارج مرکزی', - 73161 => 'مهبودی علیا', - 73171 => 'وراوی', - 73311 => 'حکیم باشی نصف میان (بالا)', - 73331 => 'کنار تخته', - 73341 => 'خشت', - 73351 => 'انارستان', - 73361 => 'نودان', - 73371 => 'مهرنجان', - 73381 => 'جره', - 73391 => 'بالاده', - 73411 => 'لپوئی', - 73431 => 'کامفیروز', - 73441 => 'خرامه', - 73451 => 'سروستان', - 73461 => 'کوار', - 73471 => 'رامجرد', - 73491 => 'گویم', - 73511 => 'خومه زار', - 73531 => 'بابامنیر', - 73541 => 'اهنگری', - 73551 => 'پرین', - 73560 => 'کوپن', - 73561 => 'حسین ابادرستم', - 73571 => 'مصیری', - 73591 => 'میشان سفلی', - 73611 => 'بهرغان', - 73631 => 'بیضا', - 73641 => 'هماشهر', - 73651 => 'کمهر', - 73661 => 'راشک علیا', - 73671 => 'هرایجان', - 73681 => 'بانش', - 73711 => 'کوشک', - 73731 => 'خانیمن', - 73741 => 'سعادت شهر', - 73751 => 'قادرآباد', - 73761 => 'ارسنجان', - 73771 => 'سیدان', - 73791 => 'کوشکک', - 73810 => 'مزایجان', - 73811 => 'خنجشت', - 73831 => 'امامزاده اسماعیل', - 73840 => 'مادرسلیمان', - 73841 => 'حسن آباد', - 73851 => 'اسپاس', - 73861 => 'سده', - 73881 => 'دژکرد', - 73891 => 'شهرمیان', - 73911 => 'بهمن', - 73931 => 'صغاد', - 73940 => 'حسامی', - 73941 => 'بوانات', - 73942 => 'کره ای', - 73951 => 'صفاشهر', - 73981 => 'سورمق', - 73991 => 'ایزدخواست', - 74110 => 'دوزه', - 74161 => 'بندبست', - 74171 => 'باب انار', - 74311 => 'فیشور', - 74331 => 'اوز', - 74341 => 'لامرد', - 74351 => 'جویم', - 74361 => 'بنارویه', - 74370 => 'خور', - 74371 => 'لطیفی', - 74380 => 'عمادده', - 74381 => 'بیرم', - 74390 => 'اهل', - 74391 => 'اشکنان', - 74410 => 'اسیر', - 74411 => 'کهنه', - 74414 => 'خوزی', - 74431 => 'خنج', - 74441 => 'علامرودشت', - 74450 => 'گله دار', - 74451 => 'مهر', - 74461 => 'رونیز', - 74471 => 'بنوان', - 74481 => 'ایج', - 74491 => 'درب قلعه', - 74541 => 'خاوران', - 74551 => 'قطب آباد', - 74561 => 'دنیان', - 74571 => 'سروو', - 74581 => 'مانیان', - 74591 => 'به جان', - 74611 => 'کوشک قاضی', - 74641 => 'نوبندگان', - 74650 => 'قره بلاغ', - 74651 => 'ششده', - 74661 => 'قاسم ابادسفلی', - 74671 => 'زاهدشهر', - 74681 => 'میانده', - 74691 => 'صحرارود', - 74711 => 'بایگان', - 74714 => 'امام شهر', - 74731 => 'مبارک آباد', - 74741 => 'میمند', - 74751 => 'افزر', - 74760 => 'قیر', - 74761 => 'کارزین', - 74771 => 'فراشبند', - 74780 => 'نوجین', - 74781 => 'دهرم', - 74791 => 'جوکان', - 74811 => 'مادوان', - 74814 => 'دبیران', - 74831 => 'ماه سالاری', - 74841 => 'رستاق', - 74850 => 'شهرپیر', - 74861 => 'حاجی آباد', - 74871 => 'فدامی', - 74880 => 'دوبرجی', - 74881 => 'چمن مروارید', - 74891 => 'جنت شهر', - 74911 => 'لای حنا', - 74931 => 'آباده طشک', - 74941 => 'قطاربنه', - 74971 => 'مشکان', - 74981 => 'قطرویه', - 74991 => 'هرگان', - ], - ], - 6 => [ - 'title' => 'اصفهان', - 'cities' => [ - 81 => 'اصفهان', - 831 => 'شاهین شهر', - 841 => 'خمینی شهر', - 851 => 'نجف آباد', - 861 => 'شهرضا', - 871 => 'کاشان', - 8161 => 'منطقه صنعتی محموداباد', - 8331 => 'مورچه خورت', - 8341 => 'دولت آباد', - 8351 => 'میمه', - 8361 => 'خور', - 8371 => 'کوهپایه', - 8381 => 'اردستان', - 8391 => 'نائین', - 8431 => 'درچه پیاز', - 8441 => 'زواره', - 8451 => 'فلاورجان', - 8461 => 'قهدریجان', - 8471 => 'زرین شهر', - 8481 => 'مبارکه', - 8491 => 'فولادشهر', - 8531 => 'تیران', - 8541 => 'دهق', - 8551 => 'علویجه', - 8561 => 'داران', - 8571 => 'چادگان', - 8591 => 'فریدونشهر', - 8641 => 'دهاقان', - 8651 => 'اسفرجان', - 8661 => 'سمیرم', - 8671 => 'حنا', - 8681 => 'مهرگرد', - 8731 => 'جوشقان استرک', - 8741 => 'آران و بیدگل', - 8751 => 'قمصر', - 8761 => 'نطنز', - 8771 => 'گلپایگان', - 8781 => 'گوگد', - 8791 => 'خوانسار', - 81351 => 'تودشک', - 81391 => 'سگزی', - 81431 => 'بهارستان', - 81561 => 'خوراسگان', - 81594 => 'گورت', - 81671 => 'دستجا', - 81681 => 'زیار', - 81751 => 'نصرآباد', - 81789 => 'ابریشم', - 81799 => 'اصفهان (سپاهان شهر)', - 83341 => 'پادگان اموزشی امام ص', - 83351 => 'پالایشگاه اصفهان', - 83361 => 'کلهرود', - 83371 => 'گرگاب', - 83431 => 'دستگرد', - 83441 => 'گز برخوار', - 83451 => 'خورزوق', - 83461 => 'حبیب آباد', - 83531 => 'موته', - 83541 => 'وزوان', - 83551 => 'لای بید', - 83561 => 'رباطاقاکمال', - 83581 => 'خسرواباد', - 83591 => 'کمشچه', - 83631 => 'جندق', - 83641 => 'فرخی', - 83651 => 'مزیک', - 83661 => 'مهرجان', - 83671 => 'بیاضه', - 83681 => 'چوپانان', - 83691 => 'بلان', - 83731 => 'محمدآباد', - 83741 => 'هرند', - 83751 => 'ورزنه', - 83761 => 'قهجاورستان', - 83771 => 'نیک آباد', - 83781 => 'اژیه', - 83791 => 'حسن اباد', - 83831 => 'کچومثقال', - 83841 => 'ظفرقند', - 83851 => 'نهوج', - 83861 => 'نیسیان', - 83871 => 'ومکان', - 83881 => 'همسار', - 83891 => 'فسخود', - 83931 => 'فوداز', - 83941 => 'اشکستان', - 83951 => 'کجان', - 83961 => 'نیستانک', - 83971 => 'انارک', - 83991 => 'بافران', - 84331 => 'تیرانچی', - 84341 => 'کوشک', - 84371 => 'قلعه امیریه', - 84431 => 'مهاباد', - 84441 => 'درقه', - 84451 => 'شهراب', - 84461 => 'تورزن', - 84471 => 'کریم اباد', - 84481 => 'تلک اباد', - 84491 => 'موغار', - 84531 => 'خوانسارک', - 84541 => 'پیربکران', - 84561 => 'کلیشادوسودرجان', - 84581 => 'کرسگان', - 84591 => 'بهاران شهر', - 84631 => 'سهروفیروزان', - 84651 => 'ایمانشهر', - 84671 => 'زازران', - 84681 => 'شرودان', - 84691 => 'جوجیل', - 84731 => 'ورنامخواست', - 84741 => 'سده لنجان', - 84751 => 'چرمهین', - 84761 => 'باغ بهادران', - 84771 => 'نوگوران', - 84781 => 'چمگردان', - 84791 => 'کرچگان', - 84831 => 'دیزیچه', - 84841 => 'زیباشهر', - 84851 => 'باغ ملک', - 84861 => 'دهسرخ', - 84871 => 'پلی اکریل', - 84881 => 'فولادمبارکه', - 84891 => 'کرکوند', - 84931 => 'زاینده رود', - 84951 => 'چم نور', - 84961 => 'کچوییه', - 84971 => 'اشیان', - 84981 => 'طالخونچه', - 84991 => 'تاسیسات سدنکواباد', - 85331 => 'رضوانشهر', - 85341 => 'ورپشت', - 85351 => 'عسگران', - 85371 => 'عزیزاباد', - 85381 => 'میراباد', - 85391 => 'حاجی اباد', - 85441 => 'خیراباد', - 85451 => 'اشن', - 85471 => 'خونداب', - 85531 => 'حسین اباد', - 85631 => 'غرغن', - 85641 => 'دامنه', - 85651 => 'بوئین و میاندشت', - 85661 => 'زرنه', - 85671 => 'بلطاق', - 85681 => 'کرچ', - 85691 => 'قره بلطاق', - 85711 => 'افوس', - 85731 => 'سازمان عمران زاینده رود', - 85741 => 'مشهدکاوه', - 85751 => 'اسکندری', - 85761 => 'رزوه', - 85771 => 'نهرخلج', - 85781 => 'چاه غلامرضارحیمی', - 85791 => 'اورگان', - 85831 => 'گلدشت', - 85851 => 'جوزدان', - 85861 => 'کهریزسنگ', - 85931 => 'نهضت اباد', - 85941 => 'قلعه سرخ', - 85961 => 'اسلام ابادموگویی', - 85971 => 'مصیر', - 85991 => 'برف انبار', - 86331 => 'قمشلو', - 86341 => 'پوده', - 86351 => 'مهیار', - 86361 => 'پرزان', - 86371 => 'منوچهراباد', - 86391 => 'شهرک صنایع شیمیایی ر', - 86431 => 'همگین', - 86451 => 'گلشن', - 86461 => 'کهرویه', - 86471 => 'قصرچم', - 86531 => 'امین اباد', - 86541 => 'مقصودبیک', - 86551 => 'سولار', - 86561 => 'منظریه', - 86631 => 'گرموک', - 86651 => 'هست', - 86671 => 'ونک', - 86751 => 'کهنگان', - 86771 => 'کمه', - 86781 => 'مورک', - 86791 => 'چهارراه', - 86831 => 'ده نسا سفلی', - 86841 => 'اغداش', - 86851 => 'چشمه رحمان', - 86861 => 'ورق', - 86881 => 'سعادت اباد', - 86891 => 'فتح اباد', - 87181 => 'نیاسر', - 87331 => 'سن سن', - 87351 => 'ده زیره', - 87361 => 'رحق', - 87371 => 'اب شیرین', - 87381 => 'نشلج', - 87391 => 'مشکات', - 87431 => 'سفیدشهر', - 87441 => 'مزرعه صدر', - 87461 => 'نوش آباد', - 87481 => 'ابوزیدآباد', - 87491 => 'کاغذی', - 87541 => 'قهرود', - 87551 => 'جوشقان و کامو', - 87561 => 'برزک', - 87571 => 'اسحق اباد', - 87581 => 'وادقان', - 87591 => 'اذان', - 87631 => 'طرق رود', - 87641 => 'اریسمان', - 87651 => 'ابیانه', - 87661 => 'بادرود', - 87671 => 'خالدآ باد', - 87681 => 'اوره', - 87731 => 'ملازجان', - 87741 => 'سعیداباد', - 87751 => 'مرغ', - 87771 => 'قرغن', - 87781 => 'کوچری', - 87831 => 'کلوچان', - 87841 => 'گلشهر', - 87861 => 'زرنجان', - 87871 => 'وانشان', - 87881 => 'تیکن', - 87931 => 'سنگ سفید', - 87941 => 'رحمت اباد', - 87951 => 'خم پیچ', - 87961 => 'مهراباد', - 87971 => 'تیدجان', - 87981 => 'خشکرود', - 87991 => 'ویست', - ], - ], - 7 => [ - 'title' => 'خراسان رضوي', - 'cities' => [ - 91 => 'مشهد', - 931 => 'نیشابور', - 951 => 'تربت حیدریه', - 961 => 'سبزوار', - 9331 => 'فیروزه', - 9341 => 'درود', - 9351 => 'طرقبه', - 9361 => 'چناران', - 9371 => 'کلات', - 9381 => 'سرخس', - 9391 => 'فریمان', - 9471 => 'قوچان', - 9491 => 'درگز', - 9531 => 'فیض آباد', - 9541 => 'رشتخوار', - 9551 => 'کدکن', - 9561 => 'خواف', - 9571 => 'تربت جام', - 9581 => 'صالح آباد', - 9591 => 'تایباد', - 9631 => 'داورزن', - 9641 => 'جغتای', - 9651 => 'ششتمد', - 9671 => 'کاشمر', - 9681 => 'بردسکن', - 9691 => 'گناباد', - 91671 => 'رضویه', - 93161 => 'همت آباد', - 93331 => 'شوراب', - 93341 => 'گلبوی پایین', - 93351 => 'مبارکه', - 93361 => 'چکنه', - 93371 => 'برزنون', - 93381 => 'فدیشه', - 93391 => 'بار', - 93431 => 'میراباد', - 93441 => 'فرخک', - 93451 => 'خرو', - 93461 => 'قدمگاه', - 93471 => 'اسحق اباد', - 93481 => 'خوجان', - 93491 => 'عشق آباد', - 93541 => 'ملک آباد', - 93551 => 'کورده', - 93561 => 'شاندیز', - 93571 => 'طوس سفلی', - 93581 => 'قرقی سفلی (شهیدکاوه)', - 93591 => 'کنه بیست', - 93631 => 'رادکان', - 93641 => 'سیداباد', - 93651 => 'گلبهار', - 93661 => 'سلوگرد', - 93671 => 'ارداک', - 93681 => 'بقمج', - 93691 => 'گلمکان', - 93741 => 'میامی', - 93751 => 'چاهک', - 93761 => 'شهرزو', - 93771 => 'گوش', - 93781 => 'نریمانی سفلی', - 93791 => 'تقی اباد', - 93831 => 'کچولی', - 93841 => 'شیرتپه', - 93851 => 'پس کمر', - 93861 => 'مزدآوند', - 93871 => 'بزنگان', - 93881 => 'گنبدلی', - 93891 => 'کندک لی', - 93931 => 'کته شمشیرسفلی', - ], - ], - 8 => [ - 'title' => 'قزوين', - 'cities' => [ - 341 => 'قزوین', - 3431 => 'الوند', - 3441 => 'آبیک', - 3451 => 'بوئین زهرا', - 3461 => 'آوج', - 3481 => 'تاکستان', - 3491 => 'محمدیه', - 34131 => 'محمودآبادنمونه', - 34151 => 'بیدستان', - 34161 => 'شریفیه', - 34171 => 'اقبالیه', - 34313 => 'نصرت آباد', - 34331 => 'الولک', - 34341 => 'کاکوهستان', - 34351 => 'فلار', - 34381 => 'مینودشت', - 34391 => 'زوارک', - 34431 => 'صمغ اباد', - 34441 => 'ناصراباد', - 34461 => 'رشتقون', - 34471 => 'قشلاق', - 34481 => 'خاکعلی', - 34491 => 'شهرک صنعتی لیا (قدیم)', - 34531 => 'سگز آباد', - 34541 => 'عصمت اباد', - 34551 => 'خرم اباد', - 34561 => 'اسفرورین', - 34571 => 'شال', - 34581 => 'دانسفهان', - 34631 => 'کلنجین', - 34641 => 'آبگرم', - 34651 => 'استبلخ', - 34671 => 'ارداق', - 34681 => 'نیارج', - 34691 => 'حصارولیعصر', - 34731 => 'ماهین', - 34741 => 'سیردان', - 34761 => 'سیاهپوش', - 34781 => 'نیارک', - 34791 => 'اقابابا', - 34811 => 'نرجه', - 34831 => 'خرمدشت', - 34851 => 'ضیاءآباد', - 34871 => 'حسین اباد', - 34891 => 'رحیم اباد', - 34913 => 'مهرگان', - 34931 => 'معلم کلایه', - 34941 => 'یحیی اباد', - 34951 => 'نیکویه', - 34961 => 'رازمیان', - 34971 => 'کوهین', - ], - ], - 9 => [ - 'title' => 'سمنان', - 'cities' => [ - 351 => 'سمنان', - 361 => 'شاهرود', - 3531 => 'علا', - 3541 => 'ابخوری', - 3551 => 'سرخه', - 3561 => 'مهدیشهر', - 3571 => 'شهمیرزاد', - 3581 => 'گرمسار', - 3591 => 'ایوانکی', - 3631 => 'میامی', - 3641 => 'بسطام', - 3651 => 'مجن', - 3661 => 'بیارجمند', - 3671 => 'دامغان', - 3681 => 'امیریه', - 35331 => 'خیراباد', - 35341 => 'ایستگاه میان دره', - 35381 => 'اهوان', - 35431 => 'جام', - 35441 => 'دوزهیر', - 35451 => 'معدن نمک', - 35531 => 'نظامی', - 35541 => 'اسداباد', - 35551 => 'لاسجرد', - 35561 => 'سیداباد', - 35571 => 'عبدالله ابادپایین', - 35581 => 'بیابانک', - 35591 => 'مومن اباد', - 35631 => 'درجزین', - 35641 => 'دربند', - 35651 => 'گل رودبار', - 35661 => 'ابگرم', - 35671 => 'افتر', - 35731 => 'فولادمحله', - 35741 => 'ده صوفیان', - 35751 => 'هیکو', - 35761 => 'چاشم', - 35831 => 'کردوان', - 35841 => 'مندولک', - 35851 => 'داوراباد', - 35861 => 'آرادان', - 35881 => 'بن کوه', - 35891 => 'کهن آباد', - 35931 => 'حسین ابادکوروس', - 35941 => 'کرک', - 35951 => 'گلستانک', - 35961 => 'لجران', - 36331 => 'جودانه', - 36341 => 'ابراهیم اباد', - 36351 => 'بکران', - 36361 => 'کرداباد', - 36371 => 'نردین', - 36381 => 'سوداغلان', - 36391 => 'فرومد', - 36431 => 'ابرسیج', - 36441 => 'میغان', - 36451 => 'قلعه نوخرقان', - 36461 => 'چهلدخترپادگان', - 36471 => 'کلاته خیج', - 36531 => 'نگارمن', - 36541 => 'دهملا', - 36551 => 'رویان', - 36561 => 'بدشت', - 36571 => 'سطوه', - 36581 => 'طرود', - 36591 => 'مغان', - 36631 => 'گیور', - 36641 => 'دستجرد', - 36651 => 'مسیح اباد', - 36661 => 'احمداباد', - 36671 => 'زمان اباد', - 36681 => 'سلمرود', - 36731 => 'جزن', - 36741 => 'برم', - 36751 => 'محمداباد', - 36761 => 'معصوم اباد', - 36771 => 'فرات', - 36781 => 'علیان', - 36791 => 'عمروان', - 36831 => 'قوشه', - 36841 => 'دروار', - 36851 => 'استانه', - 36861 => 'دیباج', - 36871 => 'طرزه', - 36881 => 'مهماندوست', - 36891 => 'کلاته ملا', - 36931 => 'قدرت اباد', - ], - ], - 10 => [ - 'title' => 'قم', - 'cities' => [ - 371 => 'قم', - 3731 => 'قنوات', - 3741 => 'دستجرد', - 37331 => 'امیرابادگنجی', - 37341 => 'قمرود', - 37351 => 'کهک', - 37361 => 'قلعه چم', - 37431 => 'قاهان', - 37441 => 'جعفریه', - 37451 => 'جنداب', - 37461 => 'سلفچگان', - ], - ], - 11 => [ - 'title' => 'مركزي', - 'cities' => [ - 381 => 'اراک', - 391 => 'ساوه', - 3771 => 'پرندک', - 3781 => 'محلات', - 3791 => 'دلیجان', - 3831 => 'کرهرود', - 3841 => 'خنداب', - 3851 => 'کمیجان', - 3861 => 'شازند', - 3871 => 'آستانه', - 3881 => 'خمین', - 3891 => 'رباطمراد', - 3931 => 'غرق آباد', - 3941 => 'مامونیه', - 3951 => 'تفرش', - 3961 => 'آشتیان', - 3991 => 'شهرجدیدمهاجران', - 37731 => 'سلطان اباد', - 37741 => 'اصفهانک', - 37751 => 'حسین اباد', - 37761 => 'خشکرود', - 37771 => 'حکیم اباد', - 37781 => 'یحیی اباد', - 37791 => 'صدراباد', - 37841 => 'نیمور', - 37851 => 'نخجیروان', - 37861 => 'باقراباد', - 37871 => 'بزیجان', - 37881 => 'عیسی اباد', - 37891 => 'خورهه', - 37961 => 'نراق', - 38341 => 'ساروق', - 38351 => 'داودآباد', - 38361 => 'کارچان', - 38451 => 'جاورسیان', - 38461 => 'ادشته', - 38471 => 'استوه', - 38481 => 'سنجان', - 38491 => 'اناج', - 38531 => 'وفس', - 38541 => 'خسروبیگ', - 38551 => 'میلاجرد', - 38561 => 'سمقاور', - 38571 => 'هزاوه', - 38631 => 'قدمگاه', - 38641 => 'هفته', - 38651 => 'لنجرود', - 38661 => 'توره', - 38671 => 'کزاز', - 38681 => 'کتیران بالا', - 38691 => 'نهرمیان', - 38731 => 'سرسختی بالا', - 38741 => 'لوزدرعلیا', - 38761 => 'هندودر', - 38771 => 'تواندشت علیا', - 38781 => 'مالمیر', - 38791 => 'چهارچریک', - 38841 => 'چهارچشمه', - 38851 => 'لکان', - 38861 => 'قورچی باشی', - 38871 => 'ورچه', - 38881 => 'فرفهان', - 38891 => 'امامزاده ورچه', - 38931 => 'رباطکفسان', - 38941 => 'ریحان علیا', - 38951 => 'جزنق', - 38961 => 'خوراوند', - 38971 => 'میشیجان علیا', - 38981 => 'گلدشت', - 38991 => 'دهنو', - 39331 => 'نوبران', - 39351 => 'یل اباد', - 39361 => 'رازقان', - 39371 => 'الویر', - 39381 => 'دوزج', - 39391 => 'علیشار', - 39431 => 'بالقلو', - 39441 => 'زاویه', - 39451 => 'چمران', - 39461 => 'قاقان', - 39471 => 'سامان', - 39481 => 'دخان', - 39491 => 'مراغه', - 39531 => 'فرمهین', - 39541 => 'شهراب', - 39551 => 'زاغر', - 39561 => 'کهک', - 39571 => 'فشک', - 39581 => 'اهنگران', - 39631 => 'مزرعه نو', - 39641 => 'صالح اباد', - 39651 => 'سیاوشان', - 39661 => 'اهو', - ], - ], - 12 => [ - 'title' => 'زنجان', - 'cities' => [ - 451 => 'زنجان', - 4531 => 'زرین آباد', - 4541 => 'ماهنشان', - 4551 => 'سلطانیه', - 4561 => 'ابهر', - 4571 => 'خرمدره', - 4581 => 'قیدار', - 4591 => 'آب بر', - 45331 => 'همایون', - 45341 => 'بوغداکندی', - 45351 => 'اژدهاتو', - 45371 => 'اسفجین', - 45381 => 'ارمغانخانه', - 45391 => 'قبله بلاغی', - 45431 => 'پری', - 45441 => 'اندابادعلیا', - 45451 => 'قره گل', - 45461 => 'نیک پی', - 45471 => 'دندی', - 45481 => 'سونتو', - 45491 => 'قلتوق', - 45531 => 'گوزلدره', - 45551 => 'سنبل اباد', - 45641 => 'درسجین', - 45651 => 'دولت اباد', - 45661 => 'کینه ورس', - 45731 => 'هیدج', - 45741 => 'صائین قلعه', - 45781 => 'اقبلاغ سفلی', - 45791 => 'سهرورد', - 45831 => 'کرسف', - 45841 => 'سجاس', - 45851 => 'محموداباد', - 45861 => 'باش قشلاق', - 45871 => 'گرماب', - 45881 => 'زرین رود', - 45891 => 'کهلا', - 45931 => 'گیلوان', - 45941 => 'دستجرده', - 45951 => 'سعیداباد', - 45961 => 'چورزق', - 45971 => 'حلب', - 45981 => 'درام', - ], - ], - 13 => [ - 'title' => 'مازندران', - 'cities' => [ - 461 => 'آمل', - 471 => 'بابل', - 481 => 'ساری', - 4631 => 'محمودآباد', - 4641 => 'نور', - 4651 => 'نوشهر', - 4661 => 'چالوس', - 4671 => 'سلمانشهر', - 4681 => 'تنکابن', - 4691 => 'رامسر', - 4731 => 'امیرکلا', - 4741 => 'بابلسر', - 4751 => 'فریدونکنار', - 4761 => 'قائم شهر', - 4771 => 'جویبار', - 4781 => 'زیر آب', - 4791 => 'پل سفید', - 4831 => 'کیاسر', - 4841 => 'نکا', - 4851 => 'بهشهر', - 4861 => 'گلوگاه', - 46181 => 'دابودشت', - 46331 => 'معلم کلا', - 46341 => 'سرخرود', - 46351 => 'وسطی کلا', - 46361 => 'رینه', - 46371 => 'سوا', - 46381 => 'باییجان', - 46391 => 'گزنک', - 46411 => 'ایزدشهر', - 46431 => 'چمستان', - 46441 => 'بنفشه ده', - 46451 => 'رییس کلا', - 46461 => 'اوز', - 46471 => 'بلده', - 46481 => 'تاکر', - 46491 => 'گلندرود', - 46531 => 'چلندر', - 46541 => 'صلاح الدین کلا', - 46551 => 'نارنج بن', - 46561 => 'رویان', - 46571 => 'کجور', - 46581 => 'پول', - 46591 => 'لشکنار', - 46631 => 'هیچرود', - 46641 => 'مرزن آباد', - 46651 => 'کردیچال', - 46661 => 'کلاردشت', - 46671 => 'کلنو', - 46681 => 'دلیر', - 46691 => 'سیاه بیشه', - 46731 => 'کلارآباد', - 46741 => 'عباس آباد', - 46751 => 'سرلنگا', - 46761 => 'کترا', - 46771 => 'گلعلی اباد', - 46781 => 'میان کوه سادات', - 46791 => 'مران سه هزار', - 46831 => 'نشتارود', - 46841 => 'قلعه گردن', - 46851 => 'خرم آباد', - 46861 => 'شیرود', - 46871 => 'سلیمان اباد', - 46881 => 'کشکو', - 46891 => 'لاک تراشان', - 46931 => 'سادات محله', - 46941 => 'کتالم وسادات شهر', - 46961 => 'اغوزکتی', - 46971 => 'جواهرده', - 46981 => 'جنت رودبار', - 46991 => 'تمل', - 47331 => 'خوشرودپی', - 47341 => 'اهنگرکلا', - 47351 => 'گاوانکلا', - 47381 => 'شورکش', - 47391 => 'اینج دان', - 47431 => 'عرب خیل', - 47441 => 'بهنمیر', - 47451 => 'کاسگرمحله', - 47461 => 'کله بست', - 47471 => 'بیشه سر', - 47491 => 'گتاب', - 47541 => 'درازکش', - 47551 => 'گردرودبار', - 47561 => 'مرزی کلا', - 47571 => 'شهیداباد', - 47581 => 'زرگرمحله', - 47631 => 'بالاجنیدلاک پل', - 47641 => 'خطیرکلا', - 47651 => 'حاجی کلاصنم', - 47661 => 'واسکس', - 47681 => 'ریکنده', - 47691 => 'ارطه', - 47731 => 'کیاکلا', - 47741 => 'بالادسته رکن کنار', - 47751 => 'بیزکی', - 47761 => 'کوهی خیل', - 47781 => 'سنگتاب', - 47791 => 'رکابدارکلا', - 47831 => 'شیرکلا', - 47841 => 'آلاشت', - 47851 => 'لفور (لفورک)', - 47861 => 'اتو', - 47871 => 'شیرگاه', - 47881 => 'پالند', - 47891 => 'چرات', - 47931 => 'ده میان', - 47941 => 'خشک دره', - 47951 => 'امافت', - 47961 => 'بالادواب', - 47971 => 'ورسک', - 47981 => 'کتی لته', - 48331 => 'اروست', - 48341 => 'فریم', - 48351 => 'سنگده', - 48361 => 'قادیکلا', - 48371 => 'تاکام', - 48390 => 'پایین هولار', - 48391 => 'بالاهولار', - 48431 => 'اسبوکلا', - 48441 => 'سورک', - 48451 => 'اسلام اباد', - 48461 => 'شهرک صنعتی گهرباران', - 48471 => 'فرح اباد (خزراباد)', - 48481 => 'دارابکلا', - 48491 => 'ماچک پشت', - 48531 => 'خورشید (امامیه)', - 48541 => 'زاغمرز', - 48551 => 'چلمردی', - 48561 => 'رستم کلا', - 48571 => 'پایین زرندین', - 48591 => 'بادابسر', - 48631 => 'تیرتاش', - 48641 => 'خلیل شهر', - 48661 => 'دامداری حسن ابوطالبی', - 48671 => 'بیشه بنه', - 48681 => 'سفیدچاه', - 48691 => 'دامداری حاج عزیزمجریان', - 48841 => 'میان دره', - 48872 => 'بندپی', - ], - ], - 14 => [ - 'title' => 'گلستان', - 'cities' => [ - 491 => 'گرگان', - 4871 => 'بندر گز', - 4881 => 'کردکوی', - 4891 => 'بندرترکمن', - 4931 => 'آق قلا', - 4941 => 'علی آباد', - 4951 => 'رامیان', - 4961 => 'آزاد شهر', - 4971 => 'گنبد کاووس', - 4981 => 'مینو دشت', - 4991 => 'کلاله', - 48731 => 'نوکنده', - 48733 => 'مراوه تپه', - 48961 => 'گمیش تپه', - 48971 => 'سیمین شهر', - 49351 => 'جلین', - 49361 => 'سرخنکلاته', - 49371 => 'تقی اباد', - 49391 => 'انبار آلوم', - 49431 => 'فاضل آباد', - 49471 => 'حاجیکلاته', - 49531 => 'خان ببین', - 49541 => 'دلند', - 49631 => 'نگین شهر', - 49641 => 'نوده خاندوز', - 49680 => 'تاتارعلیا', - 49751 => 'اینچه برون', - 49791 => 'کرند', - 49831 => 'گالیکش', - 49981 => 'عزیزاباد', - ], - ], - 15 => [ - 'title' => 'اردبيل', - 'cities' => [ - 561 => 'اردبیل', - 5631 => 'نمین', - 5641 => 'نیر', - 5651 => 'گرمی', - 5661 => 'مشگین شهر', - 5671 => 'بیله سوار', - 5681 => 'خلخال', - 5691 => 'پارس آباد', - 56331 => 'آبی بیگلو', - 56341 => 'ننه کران', - 56351 => 'عنبران', - 56361 => 'گرده', - 56371 => 'ثمرین', - 56381 => 'اردیموسی', - 56391 => 'سرعین', - 56431 => 'کورائیم', - 56441 => 'اسلام آباد', - 56451 => 'مهماندوست علیا', - 56461 => 'هیر', - 56471 => 'بقراباد', - 56481 => 'بودالالو', - 56491 => 'اراللوی بزرگ', - 56531 => 'دیزج', - 56541 => 'حمزه خانلو', - 56551 => 'زهرا', - 56561 => 'انی علیا', - 56571 => 'قاسم کندی', - 56581 => 'تازه کندانگوت', - 56591 => 'قره اغاج پایین', - 56631 => 'پریخان', - 56641 => 'قصابه', - 56651 => 'فخرآباد', - 56653 => 'لاهرود', - 56661 => 'رضی', - 56671 => 'قوشه سفلی', - 56681 => 'مرادلو', - 56691 => 'گنجوبه', - 56731 => 'گوگ تپه', - 56741 => 'انجیرلو', - 56751 => 'جعفر آباد', - 56761 => 'قشلاق اغداش کلام', - 56771 => 'خورخورسفلی', - 56781 => 'شورگل', - 56791 => 'نظرعلی بلاغی', - 56831 => 'لنبر', - 56841 => 'فیروزاباد', - 56851 => 'گیوی', - 56861 => 'خلفلو', - 56871 => 'هشتجین', - 56881 => 'برندق', - 56891 => 'کلور', - 56931 => 'تازه کندجدید', - 56941 => 'گوشلو', - 56961 => 'اق قباق علیا', - 56971 => 'شهرک غفاری', - 56981 => 'اصلاندوز', - 56991 => 'بران علیا', - ], - ], - 16 => [ - 'title' => 'آذربايجان غربي', - 'cities' => [ - 571 => 'ارومیه', - 573 => 'سیلوه', - 581 => 'خوی', - 591 => 'مهاباد', - 5751 => 'قوشچی', - 5761 => 'نقده', - 5771 => 'اشنویه', - 5781 => 'پیرانشهر', - 5791 => 'جلدیان', - 5831 => 'ایواوغلی', - 5837 => 'دیزج دیز', - 5841 => 'فیرورق', - 5861 => 'ماکو', - 5881 => 'سلماس', - 5891 => 'تازه شهر', - 5931 => 'گوگ تپه', - 5951 => 'بوکان', - 5961 => 'سردشت', - 5971 => 'میاندوآب', - 5981 => 'شاهیندژ', - 5991 => 'تکاب', - 57331 => 'باراندوز', - 57341 => 'دیزج دول', - 57351 => 'میاوق', - 57361 => 'ایبلو', - 57371 => 'دستجرد', - 57381 => 'نوشین', - 57391 => 'طلاتپه', - 57411 => 'سیلوانه', - 57431 => 'راژان', - 57441 => 'هاشم اباد', - 57451 => 'دیزج', - 57461 => 'زیوه', - 57471 => 'تویی', - 57481 => 'موانا', - 57531 => 'قره باغ', - 57541 => 'بهله', - 57551 => 'امام کندی', - 57561 => 'نازلو', - 57571 => 'سرو', - 57581 => 'کانسپی', - 57591 => 'ممکان', - 57641 => 'حسنلو', - 57651 => 'کهریزعجم', - 57661 => 'محمدیار', - 57671 => 'شیخ احمد', - 57681 => 'بیگم قلعه', - 57691 => 'راهدانه', - 57731 => 'شاهوانه', - 57741 => 'نالوس', - 57751 => 'ده شمس بزرگ', - 57761 => 'گلاز', - 57771 => 'لولکان', - 57781 => 'سیاوان', - 57831 => 'کله کین', - 57841 => 'شین اباد', - 57851 => 'چیانه', - 57861 => 'بیکوس', - 57871 => 'هنگ اباد', - 57941 => 'گردکشانه', - 57951 => 'پسوه', - 57961 => 'ریگ اباد', - 57971 => 'احمدغریب', - 58331 => 'سیه باز', - 58341 => 'بیله وار', - 58361 => 'ولدیان', - 58381 => 'قوروق', - 58391 => 'هندوان', - 58431 => 'بدلان', - 58441 => 'بلسورسفلی', - 58450 => 'زرآباد', - 58471 => 'استران', - 58481 => 'قطور', - 58516 => 'قره ضیاءالدین', - 58531 => 'شیرین بلاغ', - 58541 => 'مراکان', - 58551 => 'چورس', - 58561 => 'قورول علیا', - 58571 => 'بسطام', - 58631 => 'قره تپه', - 58641 => 'ریحانلوی علیا', - 58651 => 'زاویه سفلی', - 58661 => 'آواجیق', - 58671 => 'بازرگان', - 58681 => 'قم قشلاق', - 58691 => 'یولاگلدی', - 58716 => 'سیه چشمه', - 58731 => 'قرنقو', - 58751 => 'شوط', - 58761 => 'مرگنلر', - 58771 => 'پلدشت', - 58781 => 'نازک علیا', - 58791 => 'حسن کندی', - 58831 => 'وردان', - 58861 => 'قره قشلاق', - 58871 => 'تمر', - 58881 => 'ابگرم', - 58891 => 'سرنق', - 58931 => 'چهریق علیا', - 58941 => 'داراب', - 58951 => 'دلزی', - 58961 => 'اغ برزه', - 58971 => 'سنجی', - 59341 => 'خاتون باغ', - 59351 => 'حاجی حسن', - 59361 => 'سوگلی تپه', - 59371 => 'گلیجه', - 59381 => 'حاجی کند', - 59431 => 'باغچه', - 59441 => 'خورخوره', - 59450 => 'خلیفان', - 59451 => 'کاولان علیا', - 59461 => 'سیاقول علیا', - 59471 => 'اگریقاش', - 59481 => 'اوزون دره علیا', - 59531 => 'یکشوه', - 59541 => 'جوانمرد', - 59551 => 'اختتر', - 59561 => 'سیمینه', - 59571 => 'رحیم خان', - 59581 => 'گل تپه قورمیش', - 59631 => 'شلماش', - 59641 => 'اسلام اباد', - 59651 => 'بیوران سفلی', - 59671 => 'میرآباد', - 59681 => 'زمزیران', - 59691 => 'ربط', - 59730 => 'کشاورز', - 59731 => 'اقبال', - 59741 => 'ملاشهاب الدین', - 59751 => 'للکلو', - 59761 => 'بگتاش', - 59771 => 'چهار برج', - 59781 => 'گوگ تپه خالصه', - 59791 => 'تک اغاج', - 59831 => 'هاچاسو', - 59841 => 'هولاسو', - 59851 => 'قوزلوی افشار', - 59861 => 'محمودآباد', - 59871 => 'الی چین', - 59881 => 'حیدرباغی', - 59891 => 'حمزه قاسم', - 59931 => 'اوغول بیگ', - 59941 => 'دورباش', - 59951 => 'اقابیگ', - 59961 => 'احمدابادسفلی', - 59981 => 'باروق', - ], - ], - 17 => [ - 'title' => 'همدان', - 'cities' => [ - 651 => 'همدان', - 6531 => 'بهار', - 6541 => 'اسدآباد', - 6551 => 'کبودرآهنگ', - 6561 => 'فامنین', - 6571 => 'ملایر', - 6581 => 'تویسرکان', - 6591 => 'نهاوند', - 65141 => 'مریانج', - 65181 => 'جورقان', - 65331 => 'لالجین', - 65341 => 'دیناراباد', - 65351 => 'همه کسی', - 65361 => 'صالح آباد', - 65371 => 'پرلوک', - 65381 => 'حسین ابادبهارعاشوری', - 65391 => 'مهاجران', - 65431 => 'ویرایی', - 65441 => 'جنت اباد', - 65451 => 'موسی اباد', - 65461 => 'چنارسفلی', - 65471 => 'چنارعلیا', - 65481 => 'آجین', - 65491 => 'طویلان سفلی', - 65531 => 'کوریجان', - 65541 => 'کوهین', - 65551 => 'قهوردسفلی', - 65561 => 'اکنلو', - 65571 => 'شیرین سو', - 65581 => 'گل تپه', - 65591 => 'داق داق اباد', - 65631 => 'قهاوند', - 65641 => 'تجرک', - 65651 => 'کوزره', - 65661 => 'چانگرین', - 65671 => 'دمق', - 65681 => 'رزن', - 65691 => 'قروه درجزین', - 65731 => 'ازناو', - 65741 => 'جوزان', - 65751 => 'زنگنه', - 65761 => 'سامن', - 65771 => 'اورزمان', - 65781 => 'جوکار', - 65791 => 'اسلام اباد', - 65831 => 'جعفریه (قلعه جعفربیک)', - 65841 => 'سرکان', - 65851 => 'میانده', - 65861 => 'فرسفج', - 65871 => 'ولاشجرد', - 65881 => 'اشتران', - 65891 => 'باباپیر', - 65931 => 'جهان اباد', - 65941 => 'باباقاسم', - 65951 => 'بابارستم', - 65960 => 'برزول', - 65961 => 'گیان', - 65971 => 'دهفول', - 65981 => 'فیروزان', - 65991 => 'شهرک صنعتی بوعلی', - 65992 => 'پایگاه نوژه', - 65993 => 'علیصدر', - 65995 => 'ازندریان', - 65998 => 'گنبد', - 66000 => 'پادگان قهرمان', - ], - ], - 18 => [ - 'title' => 'كردستان', - 'cities' => [ - 661 => 'سنندج', - 6631 => 'کامیاران', - 6641 => 'دیواندره', - 6651 => 'بیجار', - 6661 => 'قروه', - 6671 => 'مریوان', - 6681 => 'سقز', - 6691 => 'بانه', - 66171 => 'شویشه', - 66331 => 'شاهینی', - 66341 => 'طای', - 66351 => 'گازرخانی', - 66361 => 'نشورسفلی', - 66371 => 'شیروانه', - 66381 => 'خامسان', - 66391 => 'موچش', - 66431 => 'شریف اباد', - 66441 => 'کوله', - 66451 => 'هزارکانیان', - 66461 => 'زرینه', - 66471 => 'گورباباعلی', - 66481 => 'گاوشله', - 66491 => 'خرکه', - 66531 => 'یاسوکند', - 66541 => 'توپ اغاج', - 66551 => 'اق بلاغ طغامین', - 66561 => 'بابارشانی', - 66571 => 'خسرواباد', - 66591 => 'جعفراباد', - 66631 => 'دلبران', - 66641 => 'دزج', - 66651 => 'کانی گنجی', - 66661 => 'بلبان آباد', - 66671 => 'دهگلان', - 66681 => 'قوریچای', - 66691 => 'سریش آباد', - 66711 => 'کانی دینار', - 66731 => 'نی', - 66741 => 'برده رشه', - 66751 => 'چناره', - 66761 => 'پیرخضران', - 66771 => 'بیساران', - 66781 => 'سروآباد', - 66791 => 'اورامان تخت', - 66831 => 'سرا', - 66841 => 'گل تپه', - 66851 => 'تیلکو', - 66861 => 'صاحب', - 66871 => 'خورخوره', - 66881 => 'کسنزان', - 66891 => 'میرده', - 66931 => 'ننور', - 66941 => 'بوئین سفلی', - 66951 => 'آرمرده', - 66961 => 'بوالحسن', - 66971 => 'کانی سور', - 66981 => 'کوخان', - 66991 => 'شوی', - ], - ], - 19 => [ - 'title' => 'كرمانشاه', - 'cities' => [ - 671 => 'کرمانشاه', - 6731 => 'هرسین', - 6741 => 'کنگاور', - 6751 => 'سنقر', - 6761 => 'اسلام آبادغرب', - 6771 => 'سرپل ذهاب', - 6781 => 'قصرشیرین', - 6791 => 'پاوه', - 67131 => 'رباط', - 67331 => 'هفت اشیان', - 67341 => 'هلشی', - 67351 => 'دوردشت', - 67361 => 'سنقراباد', - 67371 => 'بیستون', - 67381 => 'جعفراباد', - 67391 => 'مرزبانی', - 67431 => 'فش', - 67441 => 'فرامان', - 67451 => 'سلطان اباد', - 67461 => 'صحنه', - 67471 => 'قزوینه', - 67481 => 'دهلقین', - 67491 => 'درکه', - 67531 => 'باوله', - 67541 => 'گردکانه علیا', - 67551 => 'اگاه علیا', - 67561 => 'سطر', - 67571 => 'کیوه نان', - 67580 => 'میان راهان', - 67581 => 'کرکسار', - 67591 => 'کندوله', - 67631 => 'زاوله علیا', - 67641 => 'حمیل', - 67651 => 'ریجاب', - 67661 => 'کرندغرب', - 67671 => 'گهواره', - 67681 => 'کوزران', - 67691 => 'قلعه شیان', - 67731 => 'حسن اباد', - 67741 => 'سراب ذهاب', - 67751 => 'ترک ویس', - 67761 => 'ازگله', - 67771 => 'تازه آباد', - 67781 => 'نساردیره', - 67791 => 'سرمست', - 67831 => 'تپه رش', - 67841 => 'خسروی', - 67861 => 'سومار', - 67871 => 'گیلانغرب', - 67891 => 'قیلان', - 67911 => 'شاهو', - 67931 => 'باینگان', - 67940 => 'بانوره', - 67941 => 'نوسود', - 67951 => 'نودشه', - 67961 => 'روانسر', - 67971 => 'دولت اباد', - 67981 => 'جوانرود', - 67991 => 'میراباد', - ], - ], - 20 => [ - 'title' => 'لرستان', - 'cities' => [ - 681 => 'خرم آباد', - 691 => 'بروجرد', - 6831 => 'نورآباد', - 6841 => 'کوهدشت', - 6851 => 'پلدختر', - 6861 => 'الیگودرز', - 6871 => 'ازنا', - 6881 => 'دورود', - 6891 => 'الشتر', - 68141 => 'ماسور', - 68181 => 'بیرانوند', - 68331 => 'برخوردار', - 68341 => 'فرهاداباد', - 68351 => 'دم باغ', - 68361 => 'کهریزوروشت', - 68371 => 'چشمه کیزاب علیا', - 68381 => 'هفت چشمه', - 68391 => 'تقی اباد', - 68431 => 'خوشناموند', - 68441 => 'اشتره گل گل', - 68451 => 'چقابل', - 68461 => 'سوری', - 68471 => 'کونانی', - 68481 => 'گراب', - 68491 => 'درب گنبد', - 68531 => 'پاعلم (پل تنگ)', - 68541 => 'واشیان نصیرتپه', - 68551 => 'چمشک زیرتنگ', - 68561 => 'افرینه', - 68571 => 'معمولان', - 68580 => 'ویسیان', - 68581 => 'میان تاگان', - 68591 => 'پل شوراب پایین', - 68631 => 'شاهپوراباد', - 68641 => 'چمن سلطان', - 68651 => 'کیزاندره', - 68661 => 'قلعه بزنوید', - 68671 => 'شول آباد', - 68681 => 'حیه', - 68691 => 'مرگ سر', - 68731 => 'مومن آباد', - 68741 => 'رازان', - 68751 => 'سیاه گوشی (پل هرو)', - 68761 => 'زاغه', - 68771 => 'سرابدوره', - 68781 => 'چاه ذوالفقار', - 68791 => 'چم پلک', - 68831 => 'ژان', - 68841 => 'کاغه', - 68851 => 'چالانچولان', - 68861 => 'سپید دشت', - 68871 => 'چم سنگر', - 68881 => 'ایستگاه تنگ هفت', - 68891 => 'مکینه حکومتی', - 68931 => 'سراب سیاهپوش', - 68951 => 'ده رحم', - 68961 => 'فیروز آباد', - 68971 => 'اشترینان', - 68981 => 'بندیزه', - 68991 => 'دره گرگ', - ], - ], - 21 => [ - 'title' => 'بوشهر', - 'cities' => [ - 751 => 'بوشهر', - 7531 => 'بندرگناوه', - 7541 => 'خورموج', - 7551 => 'اهرم', - 7561 => 'برازجان', - 75111 => 'نخل تقی', - 75331 => 'بندر ریگ', - 75341 => 'چهارروستایی', - 75351 => 'شول', - 75361 => 'بندر دیلم', - 75371 => 'امام حسن', - 75381 => 'چغادک', - 75390 => 'سیراف', - 75391 => 'عسلویه', - 75431 => 'بادوله', - 75441 => 'شنبه', - 75451 => 'کاکی', - 75461 => 'خارک', - 75471 => 'دلوار', - 75481 => 'بنه گز', - 75491 => 'اباد', - 75531 => 'بردخون', - 75540 => 'بردستان', - 75541 => 'بندردیر', - 75551 => 'آبدان', - 75560 => 'انارستان', - 75561 => 'ریز', - 75570 => 'بنک', - 75571 => 'بندرکنگان', - 75581 => 'جم', - 75591 => 'ابگرمک', - 75631 => 'دالکی', - 75641 => 'شبانکاره', - 75651 => 'آبپخش', - 75661 => 'سعدآباد', - 75671 => 'وحدتیه', - 75681 => 'تنگ ارم', - 75691 => 'کلمه', - ], - ], - 22 => [ - 'title' => 'كرمان', - 'cities' => [ - 761 => 'کرمان', - 771 => 'رفسنجان', - 781 => 'سیرجان', - 7631 => 'ماهان', - 7641 => 'گلباف', - 7651 => 'راور', - 7661 => 'بم', - 7671 => 'بروات', - 7681 => 'راین', - 7691 => 'محمدآباد', - 7731 => 'سرچشمه', - 7741 => 'انار', - 7751 => 'شهربابک', - 7761 => 'زرند', - 7771 => 'کیانشهر', - 7781 => 'کوهبنان', - 7791 => 'چترود', - 7831 => 'پاریز', - 7841 => 'بردسیر', - 7851 => 'بافت', - 7861 => 'جیرفت', - 7871 => 'عنبرآباد', - 7881 => 'کهنوج', - 7891 => 'منوجان', - 76331 => 'ده بالا', - 76361 => 'جوپار', - 76371 => 'باغین', - 76381 => 'اختیارآباد', - 76391 => 'زنگی آباد', - 76431 => 'جوشان', - 76451 => 'اندوهجرد', - 76461 => 'شهداد', - 76471 => 'کشیت', - 76541 => 'فیض اباد', - 76641 => 'دریجان', - 76731 => 'نرماشیر', - 76741 => 'فهرج', - 76771 => 'برج معاز', - 76791 => 'نظام شهر', - 76831 => 'خانه خاتون', - 76841 => 'ابارق', - 76861 => 'گروه', - 76871 => 'گزک', - 76891 => 'محی آباد', - 76941 => 'تهرود', - 76951 => 'میرابادارجمند', - 77331 => 'داوران', - 77341 => 'خنامان', - 77351 => 'کبوترخان', - 77361 => 'هرمزاباد', - 77371 => 'کشکوئیه', - 77381 => 'گلشن', - 77391 => 'صفائیه', - 77431 => 'امین شهر', - 77461 => 'بهرمان', - 77471 => 'جوادیه الهیه نوق', - 77511 => 'خاتون آباد', - 77541 => 'محمدابادبرفه', - 77551 => 'خورسند', - 77561 => 'خبر', - 77571 => 'کمسرخ', - 77581 => 'جوزم', - 77591 => 'دهج', - 77631 => 'دشت خاک', - 77651 => 'حتکن', - 77661 => 'ریحان', - 77671 => 'جرجافک', - 77691 => 'یزدان شهر', - 77731 => 'شعبجره', - 77751 => 'سیریز', - 77761 => 'خانوک', - 77861 => 'جور', - 77931 => 'هوتک', - 77951 => 'کاظم آباد', - 77961 => 'هجدک', - 77971 => 'حرجند', - 78151 => 'نجف شهر', - 78331 => 'بلورد', - 78341 => 'ملک اباد', - 78361 => 'عماداباد', - 78371 => 'زیدآباد', - 78380 => 'هماشهر', - 78431 => 'نگار', - 78441 => 'گلزار', - 78451 => 'لاله زار', - 78461 => 'قلعه عسکر', - 78471 => 'مومن اباد', - 78481 => 'چناربرین', - 78491 => 'کمال اباد', - 78541 => 'امیراباد', - 78551 => 'بزنجان', - 78561 => 'رابر', - 78571 => 'پتکان', - 78591 => 'ارزوئیه', - 78631 => 'جبالبارز', - 78661 => 'درب بهشت', - 78691 => 'رضی ابادبالا', - 78731 => 'میجان علیا', - 78761 => 'مردهک', - 78771 => 'دوساری', - 78781 => 'حسین ابادجدید', - 78791 => 'بلوک', - 78831 => 'رودبار', - 78841 => 'قلعه گنج', - 78851 => 'نودژ', - 78871 => 'فاریاب', - 78941 => 'سرخ قلعه', - 78971 => 'خیراباد', - ], - ], - 23 => [ - 'title' => 'هرمزگان', - 'cities' => [ - 791 => 'بندرعباس', - 7931 => 'خمیر', - 7941 => 'کیش', - 7951 => 'قشم', - 7961 => 'بستک', - 7971 => 'بندرلنگه', - 7981 => 'میناب', - 7991 => 'دهبارز', - 79331 => 'پشته ایسین', - 79341 => 'پل شرقی', - 79351 => 'فین', - 79361 => 'سیاهو', - 79370 => 'سرگز', - 79371 => 'فارغان', - 79381 => 'باغات', - 79391 => 'حاجی آباد', - 79431 => 'ابگرم خورگو', - 79441 => 'قلعه قاضی', - 79450 => 'تخت', - 79451 => 'حسن لنگی پایین', - 79460 => 'گروک', - 79461 => 'سیریک', - 79471 => 'گونمردی', - 79491 => 'گوهرت', - 79531 => 'درگهان', - 79541 => 'سوزا', - 79551 => 'هرمز', - 79561 => 'جزیره لارک شهری', - 79571 => 'هنگام جدید', - 79581 => 'جزیره سیری', - 79591 => 'ابوموسی', - 79611 => 'جناح', - 79631 => 'پدل', - 79641 => 'کنگ', - 79651 => 'دژگان', - 79661 => 'رویدر', - 79671 => 'دهنگ', - 79691 => 'کمشک', - 79711 => 'کوشکنار', - 79731 => 'گزیر', - 79741 => 'بندرمغویه', - 79751 => 'چارک', - 79761 => 'دشتی', - 79771 => 'پارسیان', - 79781 => 'جزیره لاوان', - 79791 => 'بندرجاسک', - 79831 => 'بندر', - 79841 => 'سندرک', - 79851 => 'درپهن', - 79861 => 'کلورجکدان', - 79871 => 'گوهران', - 79881 => 'سردشت', - 79911 => 'بیکاه', - 79931 => 'جغین', - 79941 => 'زیارت علی', - 79951 => 'ماشنگی', - 79961 => 'گوربند', - 79971 => 'تیاب', - 79981 => 'بندزرک', - 79991 => 'هشتبندی', - ], - ], - 24 => [ - 'title' => 'چهارمحال و بختياري', - 'cities' => [ - 881 => 'شهر کرد', - 8831 => 'فرخ شهر', - 8834 => 'دزک', - 8841 => 'هفشجان', - 8844 => 'هارونی', - 8851 => 'سامان', - 8861 => 'فارسان', - 8871 => 'بروجن', - 8881 => 'اردل', - 8891 => 'لردگان', - 88139 => 'کیان', - 88331 => 'طاقانک', - 88351 => 'خراجی', - 88361 => 'دستناء', - 88371 => 'شلمزار', - 88381 => 'گهرو', - 88431 => 'سورشجان', - 88451 => 'مرغملک', - 88461 => 'سودجان', - 88561 => 'نافچ', - 88571 => 'وردنجان', - 88581 => 'بن', - 88591 => 'پردنجان', - 88631 => 'باباحیدر', - 88651 => 'چلگرد', - 88661 => 'شهریاری', - 88671 => 'جونقان', - 88731 => 'نقنه', - 88741 => 'فرادنبه', - 88751 => 'سفید دشت', - 88761 => 'بلداجی', - 88771 => 'اورگان', - 88781 => 'گندمان', - 88791 => 'امام قیس', - 88831 => 'ناغان', - 88841 => 'گل سفید', - 88861 => 'چوله دان', - 88881 => 'دشتک', - 88941 => 'آلونی', - 88951 => 'مال خلیفه', - 88961 => 'چمن بید', - 88971 => 'سردشت', - 88991 => 'منج', - ], - ], - 25 => [ - 'title' => 'يزد', - 'cities' => [ - 891 => 'یزد', - 8931 => 'ابرکوه', - 8951 => 'اردکان', - 8961 => 'میبد', - 8971 => 'بافق', - 8981 => 'مهریز', - 8991 => 'تفت', - 89331 => 'فراغه', - 89351 => 'مهردشت', - 89361 => 'اسفنداباد', - 89416 => 'اشکذر', - 89418 => 'زارچ', - 89431 => 'شاهدیه', - 89441 => 'فهرج', - 89451 => 'خضر آباد', - 89481 => 'ندوشن', - 89491 => 'حمیدیا', - 89531 => 'احمد آباد', - 89551 => 'عقدا', - 89571 => 'انارستان', - 89581 => 'زرین', - 89631 => 'بفروئیه', - 89731 => 'اسفیج', - 89751 => 'مبارکه', - 89761 => 'بهاباد', - 89771 => 'کوشک', - 89781 => 'بنستان', - 89831 => 'تنگ چنار (چنار)', - 89851 => 'ارنان', - 89861 => 'بهادران', - 89871 => 'مروست', - 89881 => 'هرات', - 89891 => 'فتح اباد', - 89931 => 'ناحیه صنعتی پیشکوه', - 89941 => 'نصراباد', - 89951 => 'علی اباد', - 89961 => 'نیر', - 89981 => 'ناحیه صنعتی گاریزات', - 89991 => 'دهشیر', - ], - ], - 26 => [ - 'title' => 'سيستان و بلوچستان', - 'cities' => [ - 981 => 'زاهدان', - 991 => 'ایرانشهر', - 9831 => 'نصرت آباد', - 9841 => 'میرجاوه', - 9861 => 'زابل', - 9871 => 'زهک', - 9875 => 'خواجه احمد', - 9891 => 'خاش', - 9931 => 'سرباز', - 9941 => 'بمپور', - 9951 => 'سراوان', - 9961 => 'سوران', - 9971 => 'چابهار', - 9981 => 'کنارک', - 9991 => 'نیکشهر', - ], - ], - 27 => [ - 'title' => 'ايلام', - 'cities' => [ - 6931 => 'ایلام', - 6941 => 'ایوان', - 6951 => 'سرآبله', - 6961 => 'دره شهر', - 6971 => 'آبدانان', - 6981 => 'دهلران', - 6991 => 'مهران', - 69331 => 'چنارباشی', - 69341 => 'بیشه دراز', - 69351 => 'چشمه کبود', - 69361 => 'چوار', - 69371 => 'بانویزه', - 69381 => 'چمن سیدمحمد', - 69391 => 'هفت چشمه', - 69441 => 'شورابه ملک', - 69451 => 'کلان', - 69471 => 'زرنه', - 69511 => 'شباب', - 69531 => 'توحید', - 69541 => 'بلاوه تره سفلی', - 69551 => 'لومار', - 69561 => 'آسمان آباد', - 69571 => 'سراب کارزان', - 69581 => 'شهرک سرتنگ', - 69591 => 'علی اباد', - 69631 => 'ماژین', - 69641 => 'ارمو', - 69661 => 'چشمه شیرین', - 69671 => 'بدره', - 69681 => 'شهرک ولیعصر', - 69731 => 'گنداب', - 69741 => 'ژیور', - 69751 => 'سراب باغ', - 69761 => 'مورموری', - 69771 => 'سیاه گل', - 69781 => 'اب انار', - 69831 => 'چم هندی', - 69841 => 'موسیان', - 69851 => 'گولاب', - 69861 => 'میمه', - 69871 => 'پهله', - 69881 => 'عین خوش', - 69891 => 'دشت عباس', - 69931 => 'شهرک اسلامیه', - 69951 => 'صالح آباد', - 69970 => 'دلگشا', - 69971 => 'ارکواز', - 69972 => 'مهر', - 69981 => 'دول کبودخوشادول', - 69991 => 'پاریاب', - ], - ], - 28 => [ - 'title' => 'كهگيلويه و بويراحمد', - 'cities' => [ - 7571 => 'دهدشت', - 7581 => 'دوگنبدان', - 7591 => 'یاسوج', - 75731 => 'سوق', - 75741 => 'لنده', - 75751 => 'لیکک', - 75761 => 'چرام', - 75771 => 'دیشموک', - 75781 => 'قلعه رییسی', - 75791 => 'قلعه دختر', - 75831 => 'باباکلان', - 75841 => 'مظفراباد', - 75851 => 'دیل', - 75861 => 'شاه بهرام', - 75871 => 'چاه تلخاب علیا', - 75881 => 'باشت', - 75891 => 'سربیشه', - 75911 => 'مادوان', - 75941 => 'چیتاب', - 75951 => 'گراب سفلی', - 75961 => 'مارگون', - 75971 => 'میمند', - 75981 => 'پاتاوه', - 75991 => 'سی سخت', - ], - ], - 29 => [ - 'title' => 'خراسان شمالي', - 'cities' => [ - 941 => 'بجنورد', - 9431 => 'گرمه', - 9441 => 'جاجرم', - 9451 => 'آشخانه', - 9461 => 'شیروان', - 9481 => 'فاروج', - 9661 => 'اسفراین', - ], - ], - 30 => [ - 'title' => 'خراسان جنوبي', - 'cities' => [ - 971 => 'بیرجند', - 9741 => 'سربیشه', - 9751 => 'نهبندان', - 9761 => 'قاین', - 9771 => 'فردوس', - 9781 => 'بشرویه', - 9791 => 'طبس', - ], - ], - 31 => [ - 'title' => 'البرز', - 'cities' => [ - 31 => 'کرج', - 3331 => 'نظرآباد', - 3361 => 'هشتگرد', - 31541 => 'ادران', - 31551 => 'آسارا', - 31638 => 'گرمدره', - 31656 => 'فردیس', - 31776 => 'مشکین دشت', - 31778 => 'محمدشهر', - 31836 => 'کرج (مهرشهر)', - 31849 => 'ماهدشت', - 31871 => 'اشتهارد', - 31991 => 'کمالشهر', - 33351 => 'تنکمان', - 33611 => 'گلسار', - 33618 => 'شهر جدید هشتگرد', - 33651 => 'کوهسار', - 33661 => 'چهارباغ', - 33691 => 'طالقان', - ], - ], - ]; - foreach($citiesArray as $province) { - foreach ($province['cities'] as $code => $cityName) { - if ($code == $cityCode) { - return $cityName; - } - } - } - return false; - } -//========================================================================================================================= -} \ No newline at end of file diff --git a/admin/partials/ssbhesabix-admin-setting.php b/admin/partials/ssbhesabix-admin-setting.php deleted file mode 100644 index 4d430dd..0000000 --- a/admin/partials/ssbhesabix-admin-setting.php +++ /dev/null @@ -1,2339 +0,0 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - */ -class Ssbhesabix_Setting { - - /** - * Hook in methods - * @since 1.0.0 - * @access static - */ -//========================================================================================================================== - public static function init() { - add_action( 'ssbhesabix_home_setting', array( __CLASS__, 'ssbhesabix_home_setting' ) ); - - add_action( 'ssbhesabix_catalog_setting', array( __CLASS__, 'ssbhesabix_catalog_setting' ) ); - add_action( 'ssbhesabix_catalog_setting_save_field', array( - __CLASS__, - 'ssbhesabix_catalog_setting_save_field' - ) ); - - add_action( 'ssbhesabix_customers_setting', array( __CLASS__, 'ssbhesabix_customers_setting' ) ); - add_action( 'ssbhesabix_customers_setting_save_field', array( - __CLASS__, - 'ssbhesabix_customers_setting_save_field' - ) ); - - add_action( 'ssbhesabix_invoice_setting', array( __CLASS__, 'ssbhesabix_invoice_setting' ) ); - add_action( 'ssbhesabix_invoice_setting_save_field', array( - __CLASS__, - 'ssbhesabix_invoice_setting_save_field' - ) ); - - add_action( 'ssbhesabix_payment_setting', array( __CLASS__, 'ssbhesabix_payment_setting' ) ); - add_action( 'ssbhesabix_payment_setting_save_field', array( - __CLASS__, - 'ssbhesabix_payment_setting_save_field' - ) ); - - add_action( 'ssbhesabix_api_setting', array( __CLASS__, 'ssbhesabix_api_setting' ) ); - add_action( 'ssbhesabix_api_setting_save_field', array( __CLASS__, 'ssbhesabix_api_setting_save_field' ) ); - - add_action( 'ssbhesabix_export_setting', array( __CLASS__, 'ssbhesabix_export_setting' ) ); - - add_action( 'ssbhesabix_sync_setting', array( __CLASS__, 'ssbhesabix_sync_setting' ) ); - - add_action( 'ssbhesabix_log_setting', array( __CLASS__, 'ssbhesabix_log_setting' ) ); - - add_action( 'ssbhesabix_extra_setting', array( __CLASS__, 'ssbhesabix_extra_setting' ) ); - add_action( 'ssbhesabix_extra_setting_save_field', array( - __CLASS__, - 'ssbhesabix_extra_setting_save_field' - ) ); - } -//========================================================================================================================== - public static function ssbhesabix_home_setting() { - ?> -

-

-

- -
- هشدارها -
-
    -
  • * - افزونه حسابیکس از کد کالاها و مشتریان و از شماره فاکتور جهت شناسایی آنها استفاده می کند، - بنابراین پس از ثبت کالاها و مشتریان در حسابیکس کد آنها را در حسابیکس تغییر ندهید، و همچنین پس از ثبت - فاکتور، - شماره فاکتور را در حسابیکس نباید تغییر دهید. -
  • -
  • - * با حذف افزونه از وردپرس، جدول ارتباط بین افزونه و حسابیکس نیز از دیتابیس وردپرس حذف می شود - و کلیه ارتباطات از بین می رود. -
  • -
-
-
- نکات -
-
    -
  • * - پیشنهاد می شود قبل از شروع کار با افزونه، حتما ویدیو خودآموز افزونه را مشاهده نمایید. -
  • -
-
- -
-
-

- - -
-
-

-
- نصب افزونه -
00:00 -
-
- اتصال افزونه به حسابیکس -
01:15 -
-
- تنظیمات افزونه -
04:06 -
-
- تعریف محصول و لینک کردن محصول به حسابیکس -
08:40 -
-
- خروجی محصولات به حسابیکس -
22:58 -
-
- خروجی موجودی اول دوره محصولات به حسابیکس -
24:22 -
-
- خروجی مشتریان -
24:55 -
-
- ورود محصولات از حسابیکس به فروشگاه -
25:25 -
-
- همسان سازی قیمت و موجودی محصولات -
26:32 -
-
- همسان سازی سفارشات -
27:25 -
-
- بروزرسانی محصولات در حسابیکس بر اساس فروشگاه -
29:18 -
-
- سفارشات و ثبت فاکتور در حسابیکس -
30:05 -
-
- پشتیبان گیری از جدول افزونه در دیتابیس -
35:20 -
-
- لاگ رویدادها و خطاها -
41:42 -
-
- حذف محصولات -
50:46 -
-
- محصول پیش نویس -
52:23 -
-
-
- - __('Enable or Disable Debug Mode', 'ssbhesabix'), - 'id' => 'ssbhesabix_debug_mode_checkbox', - 'default' => 'no', - 'type' => 'checkbox', - ); - - return $fields; - } -//============================================================================================== - public static function ssbhesabix_extra_setting() { - ?> -
-
    -
  • - این صفحه برای تنظیمات پیشرفته افزونه می باشد -
  • -
-
- -

- - -
- - - - Plugin Version - Server PHP Version - Plugin PHP Version Tested Up To - - - - - ' . $plugin_version . ' - ' . $server_php_version . ' - ' . $plugin_php_version . ' - - - ' - - . ''; - ?> -
- init( $ssbhesabi_setting_fields ); ?> -
- - - : 500 -
-
-
- - - : 200 -
-
-
- - - : 100 -
-
-
- - - : 500 -
-
-
- - - : 500 -
-
-

- -

-
-

بروزرسانی ID آخرین تغییر

-

این گزینه تغییرات را به آخرین ID بروزرسانی می کند.

- -
-
-
-

افزودن دستی محصول به حسابیکس

-

در فیلد کد ووکامرس، کد محصول بدون لینک را که می خواهید در حسابیکس ذخیره کنید، وارد نمایید.

-

در فیلد کد حسابیکس، کد حسابداری را وارد نمایید به طوری که محصولی با این کد حسابداری وجود نداشته باشد تا محصول ووکامرس انتخابی با این کد در حسابیکس اضافه شود.

-

در صورتی که محصول ساده است به جای کد متغیر عدد صفر را قرار دهید.

- - - - - - - - - - - -
-
- syncLastChangeID(); - } - - if(isset($_POST['ssbhesabix_save_product_manually_to_hesabix'])) { - $func = new Ssbhesabix_Admin_Functions(); - if(empty($_POST['attribute_code'])) { - $_POST['attribute_code'] = 0; - } - if (empty($_POST['woocommerce_code'])) { - echo ""; - } else { - if(isset($_POST['hesabix_code']) && isset($_POST['woocommerce_code']) && isset($_POST['attribute_code'])) { - $result = $func->SaveProductManuallyToHesabix($_POST['woocommerce_code'], $_POST['attribute_code'], $_POST['hesabix_code']); - if($result) { - echo ''; - } else { - echo ''; - } - } - } - } - - if(isset($_POST["ssbhesabix_integration"])) { - if(isset($_POST['ssbhesabix_set_rpp_for_sync_products_into_hesabix'])) update_option('ssbhesabix_set_rpp_for_sync_products_into_hesabix', $_POST['ssbhesabix_set_rpp_for_sync_products_into_hesabix']); - if(isset($_POST['ssbhesabix_set_rpp_for_sync_products_into_woocommerce'])) update_option('ssbhesabix_set_rpp_for_sync_products_into_woocommerce', $_POST['ssbhesabix_set_rpp_for_sync_products_into_woocommerce']); - if(isset($_POST['ssbhesabix_set_rpp_for_import_products'])) update_option('ssbhesabix_set_rpp_for_import_products', $_POST['ssbhesabix_set_rpp_for_import_products']); - if(isset($_POST['ssbhesabix_set_rpp_for_export_products'])) update_option('ssbhesabix_set_rpp_for_export_products', $_POST['ssbhesabix_set_rpp_for_export_products']); - if(isset($_POST['ssbhesabix_set_rpp_for_export_opening_products'])) update_option('ssbhesabix_set_rpp_for_export_opening_products', $_POST['ssbhesabix_set_rpp_for_export_opening_products']); - header('refresh:0'); - } - ?> -
-
-

مشاهده آیتم های جدول ارتباط

- - - - - - - - - - - - -
- getWpFaSearch($woocommerce_search_code, $woocommerce_attribute_search_code, $hesabix_search_code, $obj_type_search); - - ?> -
- - - - - - - - - - - - - - - - - - - - - -
IDنوع آیتمکد حسابیکسکد ووکامرسکد متغیر ووکامرس
id;?>objType;?>idHesabix;?>idWp;?>idWpAttribute;?>
-
- - save_fields( $ssbhesabi_setting_fields ); - } -//============================================================================================== - public static function ssbhesabix_catalog_setting_fields() { - $warehouses = Ssbhesabix_Setting::ssbhesabix_get_warehouses(); - - $fields[] = array( - 'title' => __( 'Catalog Settings', 'ssbhesabix' ), - 'type' => 'title', - 'desc' => '', - 'id' => 'catalog_options' - ); - - $fields[] = array( - 'title' => __( 'Update Price', 'ssbhesabix' ), - 'desc' => __( 'Update Price after change in Hesabix', 'ssbhesabix' ), - 'id' => 'ssbhesabix_item_update_price', - 'default' => 'no', - 'type' => 'checkbox' - ); - - $fields[] = array( - 'title' => __( 'Update Quantity', 'ssbhesabix' ), - 'desc' => __( 'Update Quantity after change in Hesabix', 'ssbhesabix' ), - 'id' => 'ssbhesabix_item_update_quantity', - 'default' => 'no', - 'type' => 'checkbox' - ); - - $fields[] = array( - 'title' => __( "Update product's quantity based on", 'ssbhesabix' ), - 'id' => 'ssbhesabix_item_update_quantity_based_on', - 'type' => 'select', - 'options' => $warehouses, - ); - - $fields[] = array( - 'title' => "", - 'desc' => __( 'Remove The Titles for Attributes When Saving Product To Hesabix', 'ssbhesabix' ), - 'id' => 'ssbhesabix_remove_attributes_titles', - 'default' => 'no', - 'type' => 'checkbox' - ); - - $fields[] = array( - 'title' => "", - 'desc' => __( 'Do not update purchase and sales titles in hesabix', 'ssbhesabix' ), - 'id' => 'ssbhesabix_do_not_update_titles_in_hesabix', - 'default' => 'no', - 'type' => 'checkbox' - ); - - $fields[] = array( - 'title' => "", - 'desc' => __( 'Do not submit product in Hesabix automatically by saving product in woocommerce', 'ssbhesabix' ), - 'id' => 'ssbhesabix_do_not_submit_product_automatically', - 'default' => 'no', - 'type' => 'checkbox' - ); - - $fields[] = array( - 'title' => "", - 'desc' => __( 'Do not update product price in Hesabix by editing product in woocommerce', 'ssbhesabix' ), - 'id' => 'ssbhesabix_do_not_update_product_price_in_hesabix', - 'default' => 'no', - 'type' => 'checkbox' - ); - - $fields[] = array( - 'title' => "", - 'desc' => __( 'Do not update product barcode in Hesabix by saving product in woocommerce', 'ssbhesabix' ), - 'id' => 'ssbhesabix_do_not_update_product_barcode_in_hesabix', - 'default' => 'no', - 'type' => 'checkbox' - ); - - $fields[] = array( - 'title' => "", - 'desc' => __( 'Do not update product category in Hesabix by saving product in woocommerce', 'ssbhesabix' ), - 'id' => 'ssbhesabix_do_not_update_product_category_in_hesabix', - 'default' => 'no', - 'type' => 'checkbox' - ); - - $fields[] = array( - 'title' => "", - 'desc' => __( 'Do not update product code in Hesabix by saving product in woocommerce', 'ssbhesabix' ), - 'id' => 'ssbhesabix_do_not_update_product_product_code_in_hesabix', - 'default' => 'no', - 'type' => 'checkbox' - ); - - $fields[] = array( - 'title' => "", - 'desc' => __( 'Show Hesabix ID in Products Page', 'ssbhesabix' ), - 'id' => 'ssbhesabix_show_product_code_in_products_page', - 'default' => 'no', - 'type' => 'checkbox' - ); - - $fields[] = array( - 'title' => "", - 'desc' => __( 'Show Hesabix Code in Woocommerce Excel Export', 'ssbhesabix' ), - 'id' => 'ssbhesabix_show_hesabix_code_in_excel_export', - 'default' => 'no', - 'type' => 'checkbox' - ); - - $fields[] = array( - 'title' => "", - 'desc' => __( 'Set Special Sale as Discount in invoice', 'ssbhesabix' ), - 'id' => 'ssbhesabix_set_special_sale_as_discount', - 'default' => 'no', - 'type' => 'checkbox' - ); - - $options_to_update_sale_price = array(); - $options_to_update_sale_price[0] = __( "The Sale price does not change", 'ssbhesabix' ); - $options_to_update_sale_price[1] = __( "The Sale price gets removed", 'ssbhesabix' ); - $options_to_update_sale_price[2] = __( "The sale price get changes in proportion to the regular price", 'ssbhesabix' ); - - $fields[] = array( - 'title' => __( "Update sale price", 'ssbhesabix' ), - 'id' => 'ssbhesabix_item_update_sale_price', - 'type' => 'select', - 'options' => $options_to_update_sale_price, - ); - - $fields[] = array( 'type' => 'sectionend', 'id' => 'catalog_options' ); - - return $fields; - } -//==================================================================================================== - public static function ssbhesabix_catalog_setting() { - $ssbhesabi_setting_fields = self::ssbhesabix_catalog_setting_fields(); - $Html_output = new Ssbhesabix_Html_output(); - ?> -
- init( $ssbhesabi_setting_fields ); ?> -

- -

-
- save_fields( $ssbhesabi_setting_fields ); - } -//============================================================================================= - public static function ssbhesabix_customers_setting_fields() { - - $fields[] = array( - 'title' => __( 'Customers Settings', 'ssbhesabix' ), - 'type' => 'title', - 'desc' => '', - 'id' => 'customer_options' - ); - - $fields[] = array( - 'title' => __( 'Update Customer Address', 'ssbhesabix' ), - 'desc' => __( 'Choose when update Customer address in Hesabix.', 'ssbhesabix' ), - 'id' => 'ssbhesabix_contact_address_status', - 'type' => 'select', - 'options' => array( - '1' => __( 'Use first customer address', 'ssbhesabix' ), - '2' => __( 'update address with Invoice address', 'ssbhesabix' ), - '3' => __( 'update address with Delivery address', 'ssbhesabix' ) - ), - ); - - $fields[] = array( - 'title' => __( 'Customer\'s Group', 'ssbhesabix' ), - 'desc' => __( 'Enter a Customer\'s Group in Hesabix', 'ssbhesabix' ), - 'id' => 'ssbhesabix_contact_node_family', - 'type' => 'text', - 'default' => 'مشتریان فروشگاه آنلاین' - ); - - $fields[] = array( - 'title' => __( 'Save Customer\'s group', 'ssbhesabix' ), - 'desc' => __( 'Automatically save Customer\'s group in hesabix', 'ssbhesabix' ), - 'id' => 'ssbhesabix_contact_automatic_save_node_family', - 'default' => 'yes', - 'type' => 'checkbox' - ); - $fields[] = array( - 'title' => __( 'Customer\'s detail auto save and update', 'ssbhesabix' ), - 'desc' => __( 'Save and update Customer\'s detail automatically in hesabix', 'ssbhesabix' ), - 'id' => 'ssbhesabix_contact_automatically_save_in_hesabix', - 'type' => 'checkbox', - 'default' => 'yes' - ); - - $fields[] = array( 'type' => 'sectionend', 'id' => 'customer_options' ); - - return $fields; - } -//============================================================================================= - public static function ssbhesabix_customers_setting() { - - $ssbhesabi_setting_fields = self::ssbhesabix_customers_setting_fields(); - - $add_fields = get_option( 'ssbhesabix_contact_add_additional_checkout_fields_hesabix', 1 ); - $nationalCodeCheck = get_option( 'ssbhesabix_contact_NationalCode_checkbox_hesabix' ) == 'yes'; - $economicCodeCheck = get_option( 'ssbhesabix_contact_EconomicCode_checkbox_hesabix' ) == 'yes'; - $registrationNumberCheck = get_option( 'ssbhesabix_contact_RegistrationNumber_checkbox_hesabix') == 'yes'; - $websiteCheck = get_option( 'ssbhesabix_contact_Website_checkbox_hesabix') == 'yes'; - - $nationalCodeRequired = get_option( 'ssbhesabix_contact_NationalCode_isRequired_hesabix' ) == 'yes'; - $economicCodeRequired = get_option( 'ssbhesabix_contact_EconomicCode_isRequired_hesabix' ) == 'yes'; - $registrationNumberRequired = get_option( 'ssbhesabix_contact_RegistrationNumber_isRequired_hesabix') == 'yes'; - $websiteRequired = get_option( 'ssbhesabix_contact_Website_isRequired_hesabix') == 'yes'; - - $nationalCodeMetaName = get_option( 'ssbhesabix_contact_NationalCode_text_hesabix', null ) ; - $economicCodeMetaName = get_option( 'ssbhesabix_contact_EconomicCode_text_hesabix', null ) ; - $registrationNumberMetaName = get_option( 'ssbhesabix_contact_RegistrationNumber_text_hesabix', null ); - $websiteMetaName = get_option( 'ssbhesabix_contact_Website_text_hesabix', null ) ; - - $Html_output = new Ssbhesabix_Html_output(); - ?> -
- init( $ssbhesabi_setting_fields ); ?> - -
-
- -
-
-
- > - -
- -
- > - -
-
- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class="form-control" value="yes"> class="form-control" value="yes">
class="form-control" value="yes"> class="form-control" value="yes">
class="form-control" value="yes"> class="form-control" value="yes">
class="form-control" value="yes"> class="form-control" value="yes">
-
-
- -

- -

-
- save_fields( $ssbhesabi_setting_fields ); - // .... - } - -//============================================================================================= - public static function ssbhesabix_invoice_setting_fields() { - $projects = Ssbhesabix_Setting::ssbhesabix_get_projects(); - $salesmen = Ssbhesabix_Setting::ssbhesabix_get_salesmen(); - - $fields[] = array( - 'title' => __( 'Invoice Settings', 'ssbhesabix' ), - 'type' => 'title', - 'desc' => '', - 'id' => 'invoice_options' - ); - - $fields[] = array( - 'title' => __( 'Add invoice in which status', 'ssbhesabix' ), - 'id' => 'ssbhesabix_invoice_status', - 'type' => 'multiselect', - 'options' => array( - 'pending' => __( 'Pending payment', 'ssbhesabix' ), - 'processing' => __( 'Processing', 'ssbhesabix' ), - 'on-hold' => __( 'On hold', 'ssbhesabix' ), - 'completed' => __( 'Completed', 'ssbhesabix' ), - 'cancelled' => __( 'Cancelled', 'ssbhesabix' ), - 'refunded' => __( 'Refunded', 'ssbhesabix' ), - 'failed' => __( 'Failed', 'ssbhesabix' ), - 'checkout-draft' => __( 'Draft', 'ssbhesabix' ), - ), - ); - - $fields[] = array( - 'title' => __( 'Return sale invoice status', 'ssbhesabix' ), - 'id' => 'ssbhesabix_invoice_return_status', - 'type' => 'multiselect', - 'options' => array( - 'pending' => __( 'Pending payment', 'ssbhesabix' ), - 'processing' => __( 'Processing', 'ssbhesabix' ), - 'on-hold' => __( 'On hold', 'ssbhesabix' ), - 'completed' => __( 'Completed', 'ssbhesabix' ), - 'cancelled' => __( 'Cancelled', 'ssbhesabix' ), - 'refunded' => __( 'Refunded', 'ssbhesabix' ), - 'failed' => __( 'Failed', 'ssbhesabix' ), - 'checkout-draft' => __( 'Draft', 'ssbhesabix' ), - ), - ); - - $fields[] = array( - 'title' => __( "Invoice's Project", 'ssbhesabix' ), - 'id' => 'ssbhesabix_invoice_project', - 'type' => 'select', - 'options' => $projects, - ); - - $fields[] = array( - 'title' => __( "Invoice's Salesman", 'ssbhesabix' ), - 'id' => 'ssbhesabix_invoice_salesman', - 'type' => 'select', - 'options' => $salesmen, - ); - - $fields[] = array( - 'title' => __( "Invoice Salesman Percentage", 'ssbhesabix' ), - 'id' => 'ssbhesabix_invoice_salesman_percentage', - 'type' => 'text', - 'placeholder' => __("Invoice Salesman Percentage", 'ssbhesabix'), - ); - - $fields[] = array( - 'title' => '', - 'desc' => __('Save invoice in draft mode in Hesabix', 'ssbhesabix'), - 'id' => 'ssbhesabix_invoice_draft_save_in_hesabix', - 'type' => 'checkbox', - 'default' => 'no' - ); - - $fields[] = array( - 'title' => __('Save Freight', 'ssbhesabix'), - 'id' => 'ssbhesabix_invoice_freight', - 'type' => 'radio', - 'options' => [ - 0 => __("Save as Freight", 'ssbhesabix'), - 1 => __("Save as a Service", 'ssbhesabix') - ], - ); - - $fields[] = array( - 'title' => __('Service Code For Freight', 'ssbhesabix'), - 'id' => 'ssbhesabix_invoice_freight_code', - 'type' => 'text', - 'placeholder' => __('Enter Freight Code', 'ssbhesabix'), - ); - - if(is_plugin_active( 'dokan-lite/dokan.php' )){ - $fields[] = array( - 'title' => __( "Submit invoice base on Dokan orders", 'ssbhesabix' ), - 'id' => 'ssbhesabix_invoice_dokan', - 'type' => 'radio', - 'options' => [0 => __( "Inactive", 'ssbhesabix' ), - 1 => __( "Submit parent order", 'ssbhesabix' ), - 2 => __( "Submit children orders", 'ssbhesabix' )], - 'default' => 0 - ); - } - - $fields[] = array('type' => 'sectionend', 'id' => 'invoice_options'); - - return $fields; - } -//============================================================================================= - public static function ssbhesabix_invoice_setting() { - $ssbhesabi_setting_fields = self::ssbhesabix_invoice_setting_fields(); - $Html_output = new Ssbhesabix_Html_output(); - ?> - -
- توجه
- در اینجا تعیین کنید که فاکتور سفارش در چه مرحله ای در حسابیکس ثبت شود. - و چه زمان برای یک سفارش فاکتور برگشت از فروش ثبت شود. -
- در صورت انتخاب ذخیره هزینه حمل و نقل به عنوان یک خدمت، ابتدا باید یک خدمت در حسابیکس تعریف کنید و کد مربوط به آن را در فیلد کد خدمت حمل و نقل وارد و ذخیره نمایید. -
- فیلد "ذخیره هزینه به عنوان خدمت" برای سامانه مودیان مالیاتی می باشد. -
- توجه کنید که مقدار این فیلد به درستی وارد شده باشد تا در ثبت فاکتور مشکلی ایجاد نشود. -
-
- init( $ssbhesabi_setting_fields ); ?> -

- -

- alert("کد خدمت حمل و نقل تعریف نشده است")'; - } - ?> -
- save_fields( $ssbhesabi_setting_fields ); - } -//============================================================================================= - public static function ssbhesabix_payment_setting_fields() { - $banks = Ssbhesabix_Setting::ssbhesabix_get_banks(); - $cashes = Ssbhesabix_Setting::ssbhesabix_get_cashes(); - $payInputValue = array_merge($banks,$cashes); - - $payment_gateways = new WC_Payment_Gateways; - $available_payment_gateways = $payment_gateways->get_available_payment_gateways(); - - $fields[] = array( - 'title' => __( 'Payment methods Settings', 'ssbhesabix' ), - 'type' => 'title', - 'desc' => '', - 'id' => 'payment_options' - ); - - $fields[] = array( - 'title' => __( 'Add payment in which status', 'ssbhesabix' ), - 'id' => 'ssbhesabix_payment_status', - 'type' => 'multiselect', - 'options' => array( - 'pending' => __( 'Pending payment', 'ssbhesabix' ), - 'processing' => __( 'Processing', 'ssbhesabix' ), - 'on-hold' => __( 'On hold', 'ssbhesabix' ), - 'completed' => __( 'Completed', 'ssbhesabix' ), - 'cancelled' => __( 'Cancelled', 'ssbhesabix' ), - 'refunded' => __( 'Refunded', 'ssbhesabix' ), - 'failed' => __( 'Failed', 'ssbhesabix' ), - 'checkout-draft' => __( 'Draft', 'ssbhesabix' ), - ), - ); - - foreach ( $available_payment_gateways as $gateway ) { - $fields[] = array( - 'title' => $gateway->title, - 'id' => 'ssbhesabix_payment_method_' . $gateway->id, - 'type' => 'select', - 'options' => $payInputValue - ); - } - - foreach ( $available_payment_gateways as $gateway ) { - $fields[] = array( - 'title' => 'درصد کارمزد تراکنش برای ' . $gateway->title, - 'id' => 'ssbhesabix_payment_transaction_fee_' . $gateway->id, - 'class' => 'payment-transaction-fee', - 'type' => 'text', - 'placeholder' => 'وارد نمایید', - 'default' => '0', - ); - } - - $plugins = get_plugins(); - foreach ($plugins as $plugin_file => $plugin_info) { - if ($plugin_file === 'snapppay-woocommerce-gateway /index.php') { - if(is_plugin_active('snapppay-woocommerce-gateway /index.php')) { - $fields[] = array( - 'title' => 'پرداخت اسنپ پی', - 'id' => 'ssbhesabix_payment_method_snapppay', - 'type' => 'select', - 'options' => $payInputValue - ); - - $fields[] = array( - 'title' => 'درصد کارمزد تراکنش برای پرداخت اسنپ پی', - 'id' => 'ssbhesabix_payment_transaction_fee_snapppay', - 'type' => 'text', - 'placeholder' => 'وارد نمایید', - 'default' => '0', - ); - } - } - } - - $fields[] = array( - 'title' => __('Default Payment Gateway By Using this Option, all Invoices Will Have this Payment Gateway as Their Payment Gateway', 'ssbhesabix'), - 'id' => 'ssbhesabix_payment_option', - 'type' => 'radio', - 'options' => [ - 'yes' => __("Save Default Bank as the Payment Gateway", "ssbhesabix"), - 'no' => __("Save Other Payment Methods as the Payment Gateway", "ssbhesabix"), - ], - 'default' => 'no' - ); - - $fields[] = array( - 'title' => __( "Default Invoice Transaction Fee Percentage", 'ssbhesabix' ), - 'id' => 'ssbhesabix_invoice_transaction_fee', - 'type' => 'text', - 'class' => 'payment-transaction-fee', - 'placeholder' => __("Default Invoice Transaction Fee Percentage", 'ssbhesabix'), - 'default' => '0' - ); - - $fields[] = array( - 'title' => __( "Submit Cash in Transit", 'ssbhesabix' ), - 'id' => 'ssbhesabix_cash_in_transit', - 'desc' => __( "Submit Invoice Receipt Cash in Transit", 'ssbhesabix' ), - 'type' => 'checkbox', - 'default' => 'no' - ); - - $fields[] = array( - 'title' => __('Default Bank Code', 'ssbhesabix'), - 'id' => 'ssbhesabix_default_payment_method_code', - 'type' => 'text', - 'placeholder' => __('Enter Bank Code', 'ssbhesabix') - ); - - $fields[] = array( - 'title' => __('Default Bank Name', 'ssbhesabix'), - 'id' => 'ssbhesabix_default_payment_method_name', - 'type' => 'text', - 'placeholder' => __('Enter Bank Name', 'ssbhesabix') - ); - - $fields[] = array( 'type' => 'sectionend', 'id' => 'payment_options' ); - - return $fields; - } -//============================================================================================= - public static function ssbhesabix_payment_setting() { - $ssbhesabi_setting_fields = self::ssbhesabix_payment_setting_fields(); - $Html_output = new Ssbhesabix_Html_output(); - ?> - -
- توجه
- در اینجا تعیین کنید که رسید دریافت وجه فاکتور در چه وضعیتی ثبت شود - و در هر روش پرداخت، رسید در چه بانکی و یا صندوقی ثبت شود. -
- بانک پیش فرض، جهت کاربرانی می باشد که به هر دلیلی روش های پرداخت وکامرس در اینجا نمایش داده نمی شود. در این صورت با انتخاب بانک و ثبت کد آن، تمامی دریافت ها در آن بانک ثبت خواهد شد -
- درصد کارمزد تراکنش برای هر روش پرداخت می تواند تعریف شود(بین 1 تا 100). -
- درصد کارمزد تراکنش پیش فرض زمانی اعمال می شود که درصد یک روش پرداخت یا تعریف نشده باشد و یا صفر باشد. -
-
- init( $ssbhesabi_setting_fields ); ?> -

- -

- alert("کد بانک پیش فرض تعریف نشده است")'; - } - - if(get_option("ssbhesabix_cash_in_transit") == "yes" || get_option("ssbhesabix_cash_in_transit") == "1") { - $func = new Ssbhesabix_Admin_Functions(); - $cashInTransitFullPath = $func->getCashInTransitFullPath(); - if(!$cashInTransitFullPath) { - HesabixLogService::writeLogStr("Cash in Transit is not Defined in Hesabix ---- وجوه در راه در حسابیکس یافت نشد"); - echo ' - '; - } - } - ?> -
- save_fields( $ssbhesabi_setting_fields ); - } -//============================================================================================= - public static function ssbhesabix_api_setting_fields() { - $fields[] = array( - 'title' => __( 'API Settings', 'ssbhesabix' ), - 'type' => 'title', - 'desc' => '', - 'id' => 'api_options' - ); - - $fields[] = array( - 'title' => __( 'API Key', 'ssbhesabix' ), - 'desc' => __( 'Find API key in Setting->Financial Settings->API Menu', 'ssbhesabix' ), - 'id' => 'ssbhesabix_account_api', - 'type' => 'text', - ); - - $fields[] = array( - 'title' => __( 'API Address', 'ssbhesabix' ), - 'id' => 'ssbhesabix_api_address', - 'type' => 'select', - 'options' => array( - "0" => "hesabix.ir", - "1" => "next.hesabix.ir" - ) - ); - $fields[] = array( 'type' => 'sectionend', 'id' => 'api_options' ); - - return $fields; - } -//============================================================================================= - public static function ssbhesabix_api_setting() { - $businessInfo = self::getSubscriptionInfo(); - $isBusinessInfo = false; - if ( $businessInfo["expireDate"] != '' && $businessInfo["expireDate"] != null ) { - $isBusinessInfo = true; - $expireDate = strtotime( $businessInfo["expireDate"] ); - $expireDateStr = date( "Y/m/d", $expireDate ); - } - - $ssbhesabi_setting_fields = self::ssbhesabix_api_setting_fields(); - $Html_output = new Ssbhesabix_Html_output(); - ?> -
- توجه
-
    -
  • - برای اتصال به API حسابیکس و فعال شدن این افزونه باید در اینجا - کلید API و توکن ورود به کسب و کار خود را وارد کنید. -
  • -
  • - اگر برای اتصال به API حسابیکس از توکن ورود استفاده کنید - نیازی به وارد کردن ایمیل و رمز عبور نیست. -
  • -
  • - برای پیدا کردن توکن ورود و کلید API، در حسابیکس به قسمت تنظیمات، تنظیمات API مراجعه کنید. -
  • -
  • - اگر می خواهید کسب و کار دیگری را به افزونه متصل کنید، ابتدا باید یک بار افزونه را - حذف و مجدد نصب کنید تا جدول ارتباطات کسب و کار قبلی با افزونه حذف گردد. -
  • -
-
-
- اطلاعات کسب و کار -
-
نام کسب و کار:
-
-
طرح:
-
-
-
-
اعتبار سند:
-
-
تاریخ انقضا:
-
-
-
- -
- هشدار
- برای اتصال یک کسب و کار دیگر به افزونه، ابتدا باید یک بار افزونه را حذف و مجدد - نصب کنید تا جدول ارتباطات افزونه با کسب و کار قبل حذف گردد. -
- -
- init( $ssbhesabi_setting_fields ); ?> -

- -

-
- save_fields( $ssbhesabi_setting_fields ); - - Ssbhesabix_Setting::ssbhesabix_set_webhook(); - } -//============================================================================================= - public static function ssbhesabix_export_setting() { - // Export - Bulk product export offers - $productExportResult = ( isset( $_GET['productExportResult'] ) ) ? wc_clean( $_GET['productExportResult'] ) : null; - $productImportResult = ( isset( $_GET['productImportResult'] ) ) ? wc_clean( $_GET['productImportResult'] ) : null; - $error = ( isset( $_GET['error'] ) ) ? wc_clean( $_GET['error'] ) : null; - - if ( ! is_null( $productExportResult ) && $productExportResult === 'true' ) { - $processed = ( isset( $_GET['processed'] ) ) ? wc_clean( $_GET['processed'] ) : null; - if ( $processed == 0 ) { - echo '
'; - echo '

' . __( 'No products were exported, All products were exported or there are no product', 'ssbhesabix' ); - echo '

'; - } else { - echo '
'; - echo '

' . sprintf( __( 'Export products completed. %s products added/updated.', 'ssbhesabix' ), $processed ); - echo '

'; - } - } elseif ( $productExportResult === 'false' ) { - if ( ! is_null( $error ) && $error === '-1' ) { - echo '
'; - echo '

' . __( 'Export products fail. Hesabix has already contained products.', 'ssbhesabix' ); - echo '

'; - } else { - echo '
'; - echo '

' . __( 'Export products fail. Please check the log file.', 'ssbhesabix' ); - echo '

'; - } - } - - if ( ! is_null( $productImportResult ) && $productImportResult === 'true' ) { - $processed = ( isset( $_GET['processed'] ) ) ? wc_clean( $_GET['processed'] ) : null; - if ( $processed == 0 ) { - echo '
'; - echo '

' . __( 'No products were imported, All products were imported or there are no product', 'ssbhesabix' ); - echo '

'; - } else { - echo '
'; - echo '

' . sprintf( __( 'Import products completed. %s products added/updated.', 'ssbhesabix' ), $processed ); - echo '

'; - } - } elseif ( $productImportResult === 'false' ) { - echo '
'; - echo '

' . __( 'Import products fail. Please check the log file.', 'ssbhesabix' ); - echo '

'; - } - - // Export - Product opening quantity export offers - $productOpeningQuantityExportResult = ( isset( $_GET['productOpeningQuantityExportResult'] ) ) ? wc_clean( $_GET['productOpeningQuantityExportResult'] ) : null; - if ( ! is_null( $productOpeningQuantityExportResult ) && $productOpeningQuantityExportResult === 'true' ) { - echo '
'; - echo '

' . __( 'Export product opening quantity completed.', 'ssbhesabix' ); - echo '

'; - } elseif ( ! is_null( $productOpeningQuantityExportResult ) && $productOpeningQuantityExportResult === 'false' ) { - $shareholderError = ( isset( $_GET['shareholderError'] ) ) ? wc_clean( $_GET['shareholderError'] ) : null; - $noProduct = ( isset( $_GET['noProduct'] ) ) ? wc_clean( $_GET['noProduct'] ) : null; - if ( $shareholderError == 'true' ) { - echo '
'; - echo '

' . __( 'Export product opening quantity fail. No Shareholder exists, Please define Shareholder in Hesabix', 'ssbhesabix' ); - echo '

'; - } elseif ( $noProduct == 'true' ) { - echo '
'; - echo '

' . __( 'No product available for Export product opening quantity.', 'ssbhesabix' ); - echo '

'; - } else { - echo '
'; - echo '

' . __( 'Export product opening quantity fail. Please check the log file.', 'ssbhesabix' ); - echo '

'; - } - } - - // Export - Bulk customer export offers - $customerExportResult = ( isset( $_GET['customerExportResult'] ) ) ? wc_clean( $_GET['customerExportResult'] ) : null; - - if ( ! is_null( $customerExportResult ) && $customerExportResult === 'true' ) { - $processed = ( isset( $_GET['processed'] ) ) ? wc_clean( $_GET['processed'] ) : null; - if ( $processed == 0 ) { - echo '
'; - echo '

' . __( 'No customers were exported, All customers were exported or there are no customer', 'ssbhesabix' ); - echo '

'; - } else { - echo '
'; - echo '

' . sprintf( __( 'Export customers completed. %s customers added.', 'ssbhesabix' ), $processed ); - echo '

'; - } - } elseif ( ! is_null( $customerExportResult ) && $customerExportResult === 'false' ) { - if ( ! is_null( $error ) && $error === '-1' ) { - echo '
'; - echo '

' . __( 'Export customers fail. Hesabix has already contained customers.', 'ssbhesabix' ); - echo '

'; - } else { - echo '
'; - echo '

' . __( 'Export customers fail. Please check the log file.', 'ssbhesabix' ); - echo '

'; - } - } - - ?> -
-

-
-
-
-
-
- -
- -
-
-

-
-
-
-
- -
    -
  • با انجام این عملیات محصولات لینک نشده از فروشگاه وارد حسابیکس می شوند.
  • -
  • اگر محصولات از قبل هم در فروشگاه تعریف شده اند و هم در حسابیکس و به هم لینک نشده اند باید از - گزینه - همسان سازی دستی محصولات استفاده کنید. -
  • -
  • با انجام این عملیات موجودی محصولات وارد حسابیکس نمی شود و برای وارد کردن موجودی محصولات - فروشگاه - در حسابیکس، باید از گزینه استخراج موجودی اول دوره استفاده کنید. -
  • -
-
-
-
- -
-
-
- -
- -
-
-

-
-
-
-
- -
    -
  • با انجام این عملیات موجودی کنونی محصولات در فروشگاه بعنوان موجودی اول دوره محصولات در حسابیکس - ثبت می شوند. -
  • -
  • بطور کلی فقط یک بار باید از این گزینه استفاده کنید، - که این کار باید پس از خروج محصولات به حسابیکس و یا پس از همسان سازی دستی تمام محصولات - انجام شود. -
  • -
-
-
-
- -
-
-
- -
- -
-
-

-
-
-
-
- -
    -
  • با انجام این عملیات مشتریان لینک نشده از فروشگاه وارد حسابیکس می شوند.
  • -
  • - اگر یک مشتری بیش از یک بار وارد حسابیکس شده است می توانید از گزینه ادغام تراکنش ها در حسابیکس - استفاده کنید. -
  • -
-
-
-
- -
-
-
- -
- -
-
-

- -

-
-
-
-
- -
    -
  • با انجام این عملیات محصولات لینک نشده از حسابیکس وارد فروشگاه می شوند.
  • -
  • اگر محصولات از قبل هم در فروشگاه تعریف شده اند و هم در حسابیکس و به هم لینک نشده اند باید از - گزینه - همسان سازی دستی محصولات استفاده کنید. -
  • -
  • محصولات در وضعیت خصوصی وارد فروشگاه می شوند و سپس هر زمان مایل بودید می توانید وضعیت را به - منتشر شده تغییر دهید. -
  • -
  • تمامی محصولات بعنوان محصول ساده (و نه متغیر) وارد فروشگاه می شوند.
  • -
-
-
-
- '; - echo '

' . __( 'Sync completed, All hesabix changes synced successfully.', 'ssbhesabix' ); - echo '

'; - } - - // Sync - Bulk product sync offers - $productSyncResult = ( isset( $_GET['productSyncResult'] ) ) ? wc_clean( $_GET['productSyncResult'] ) : null; - if ( ! is_null( $productSyncResult ) && $productSyncResult == 'true' ) { - echo '
'; - echo '

' . __( 'Sync completed, All products price/quantity synced successfully.', 'ssbhesabix' ); - echo '

'; - } elseif ( ! is_null( $productSyncResult ) && ! $productSyncResult == 'false' ) { - echo '
'; - echo '

' . __( 'Sync products fail. Please check the log file.', 'ssbhesabix' ); - echo '

'; - } - - // Sync - Bulk invoice sync offers - $orderSyncResult = ( isset( $_GET['orderSyncResult'] ) ) ? wc_clean( $_GET['orderSyncResult'] ) : null; - - if ( ! is_null( $orderSyncResult ) && $orderSyncResult === 'true' ) { - $processed = ( isset( $_GET['processed'] ) ) ? wc_clean( $_GET['processed'] ) : null; - echo '
'; - echo '

' . sprintf( __( 'Order sync completed. %s order added.', 'ssbhesabix' ), $processed ); - echo '

'; - } elseif ( ! is_null( $orderSyncResult ) && $orderSyncResult === 'false' ) { - $fiscal = ( isset( $_GET['fiscal'] ) ) ? wc_clean( $_GET['fiscal'] ) : false; - - if ( $fiscal === 'true' ) { - echo '
'; - echo '

' . __( 'The date entered is not within the fiscal year.', 'ssbhesabix' ); - echo '

'; - } else { - echo '
'; - echo '

' . __( 'Cannot sync orders. Please enter valid Date format.', 'ssbhesabix' ); - echo '

'; - } - } - - // Sync - Bulk product update - $productUpdateResult = ( isset( $_GET['$productUpdateResult'] ) ) ? wc_clean( $_GET['$productUpdateResult'] ) : null; - if ( ! is_null( $productUpdateResult ) && $productUpdateResult == 'true' ) { - echo '
'; - echo '

' . __( 'Update completed successfully.', 'ssbhesabix' ); - echo '

'; - } elseif ( ! is_null( $productUpdateResult ) && ! $productUpdateResult == 'false' ) { - echo '
'; - echo '

' . __( 'Update failed. Please check the log file.', 'ssbhesabix' ); - echo '

'; - } - - // Sync - Bulk product with filter update in Hesabix - $productUpdateWithFilterResult = ( isset( $_GET['$productUpdateWithFilterResult'] ) ) ? wc_clean( $_GET['$productUpdateWithFilterResult'] ) : null; - if ( ! is_null( $productUpdateWithFilterResult ) && $productUpdateWithFilterResult == 'true' ) { - echo '
'; - echo '

' . __( 'Update completed successfully.', 'ssbhesabix' ); - echo '

'; - } elseif ( ! is_null( $productUpdateWithFilterResult ) && ! $productUpdateWithFilterResult == 'false' ) { - echo '
'; - echo '

' . __( 'Update failed. Please check the log file.', 'ssbhesabix' ); - echo '

'; - } - ?> - -
-

' . $storeProductsCount . '' ?>

-

' . $hesabixProductsCount . '' ?>

-

' . $linkedProductsCount . '' ?>

-
- -
-

-
- -
-
-
-
- -
- -
-
-

-
- -
    -
  • با انجام این عملیات کالاها، مشتریان و سفارشاتی که تا کنون در حسابیکس ثبت نشده اند در حسابیکس - ثبت می شوند. -
  • -
  • توجه کنید که بصورت نرمال با فعالسازی افزونه و تکمیل تنظیمات API - این همسان سازی بصورت خودکار انجام می شود و این گزینه صرفاْ برای مواقعی است که به دلایل فنی - مثل قطع اتصال فروشگاه با حسابیکس و یا خطا و باگ این همسان سازی صورت نگرفته است. -
  • -
-
-
-
- -
-
-
- -
- - - - - -
-
-

-
-
-
-
- -
    -
  • با انجام این عملیات موجودی و قیمت محصولات در فروشگاه، بر اساس قیمت و موجودی آنها در حسابیکس - تنظیم می شود. -
  • -
  • این عملیات بر اساس تنظیمات صورت گرفته در تب محصولات انجام می شود.
  • -
-
-
-
- -
-
-
- -
- - تا - - - -
-
-

-
-
-
-
-
-
- -
    -
  • با انجام این عملیات سفارشات فروشگاه که در حسابیکس ثبت نشده اند از تاریخ انتخاب شده بررسی و در - حسابیکس ثبت می شوند. -
  • -
  • توجه کنید که بصورت نرمال با فعالسازی افزونه و تکمیل تنظیمات API - این همسان سازی بصورت خودکار انجام می شود و این گزینه صرفاْ برای مواقعی است که به دلایل فنی - مثل قطع اتصال فروشگاه با حسابیکس و یا خطا و باگ این همسان سازی صورت نگرفته است. -
  • -
-
-
-
- -
-
-
- -
- -
-
-

-
-
-
-
- -
    -
  • با انجام این عملیات ویژگی محصولات مثل نام و قیمت در حسابیکس، بر اساس فروشگاه بروزرسانی می - شود. -
  • -
  • در این عملیات موجودی کالا در حسابیکس تغییری نمی کند و بروز رسانی نمی شود.
  • -
-
-
-
- -
-
-
- -
- -

- -

- -
-
-

-
- -
    -
  • با انجام این عملیات ویژگی محصولات مثل نام و قیمت در حسابیکس، بر اساس فروشگاه در بازه ID مشخص شده بروزرسانی می - شود. -
  • -
  • در این عملیات موجودی کالا در حسابیکس تغییری نمی کند و بروز رسانی نمی شود.
  • -
  • بازه ID نباید بیشتر از 200 عدد باشد.
  • -
-
-
-
- - $storeProductsCount, - "hesabixProductsCount" => $hesabixProductsCount, - "linkedProductsCount" => $linkedProductsCount - ); - } -//============================================================================================= - public static function getProductCountsInHesabix() { - $hesabix = new Ssbhesabix_Api(); - - $filters = array( array( "Property" => "khadamat", "Operator" => "=", "Value" => 0 ) ); - - $response = $hesabix->itemGetItems( array('Filters' => $filters ) ); - if ( $response->Success ) { - return $response->data->FilteredCount; - } else { - return 0; - } - } -//============================================================================================= -// public static function getLinkedProductsCount() { -// global $wpdb; -// -// return $wpdb->get_var( "SELECT COUNT(*) FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `obj_type` = 'product'" ); -// } - - - public static function getLinkedProductsCount() { - global $wpdb; - - return $wpdb->get_var( - $wpdb->prepare( - "SELECT COUNT(*) FROM {$wpdb->prefix}ssbhesabix WHERE obj_type = 'product'" - ) - ); - } -//============================================================================================= -// public static function getProductCountsInStore() { -// global $wpdb; -// -// return $wpdb->get_var( "SELECT COUNT(*) FROM `" . $wpdb->prefix . "posts` WHERE `post_type` IN ('product','product_variation') AND `post_status` IN ('publish', 'private', 'draft') " ); -// } - - public static function getProductCountsInStore() { - global $wpdb; - - return $wpdb->get_var( - $wpdb->prepare( - "SELECT COUNT(*) - FROM {$wpdb->prefix}posts - WHERE post_type IN ('product', 'product_variation') - AND post_status IN ('publish', 'private', 'draft')" - ) - ); - } - -//============================================================================================= - public static function getSubscriptionInfo() { - $businessName = ''; - $credit = ''; - $expireDate = ''; - $plan = ''; - - $hesabix = new Ssbhesabix_Api(); - $response = $hesabix->settingGetSubscriptionInfo(); - if ( $response->Success ) { - $businessName = $response->Result->Name; - $credit = $response->Result->Credit; - $expireDate = $response->Result->ExpireDate; - $plan = $response->Result->Subscription; - } - - return array( - "businessName" => $businessName, - "credit" => $credit, - "expireDate" => $expireDate, - "plan" => $plan - ); - } -//============================================================================================= - public static function ssbhesabix_set_webhook() { - $url = get_site_url() . '/index.php?ssbhesabix_webhook=1&token=' . substr( wp_hash( AUTH_KEY . 'ssbhesabix/webhook' ), 0, 10 ); - - $hookPassword = get_option( 'ssbhesabix_webhook_password' ); - - $ssbhesabix_api = new Ssbhesabix_Api(); - $response = $ssbhesabix_api->settingSetChangeHook( $url, $hookPassword ); - - if ( is_object( $response ) ) { - if ( $response->Success ) { - update_option( 'ssbhesabix_live_mode', 1 ); - update_option( 'ssbhesabix_account_bid', $response->bid ); - update_option( 'ssbhesabix_account_year', $response->year ); - - //set the last log ID if is not set - $lastChanges = get_option( 'ssbhesabix_last_log_check_id' ); - if ( ! $lastChanges ) { - $lastChanges = 0; - } - $changes = $ssbhesabix_api->settingGetChanges( $lastChanges ); - if ( $changes->Success ) { - if ( get_option( 'ssbhesabix_last_log_check_id' ) == 0 ) { - $lastChange = end( $changes->Result ); - update_option( 'ssbhesabix_last_log_check_id', $lastChange->Id ); - } - } else { - echo '
'; - echo '

' . __( 'Cannot check the last change ID. Error Message: ', 'ssbhesabix' ) . $changes->ErrorMessage . '

'; - echo '
'; - - HesabixLogService::log( array("Cannot check the last change ID. Error Message: $changes->ErrorMessage. Error Code: $changes->ErrorCode") ); - } - - - //check if date in fiscalYear - if ( Ssbhesabix_Admin_Functions::isDateInFiscalYear( date( 'Y-m-d H:i:s' ) ) === 0 ) { - echo '
'; - echo '

' . __( 'The fiscal year has passed or not arrived. Please check the fiscal year settings in Hesabix.', 'ssbhesabix' ) . '

'; - echo '
'; - - update_option( 'ssbhesabix_live_mode', 0 ); - } - - //check the Hesabix default currency - $default_currency = $ssbhesabix_api->settingGetCurrency(); - if ( $default_currency->Success ) { - - $woocommerce_currency = get_woocommerce_currency(); - $hesabix_currency = $default_currency->Result->moneyName; - if ( $hesabix_currency == $woocommerce_currency || ( $hesabix_currency == 'IRR' && $woocommerce_currency == 'IRT' ) || ( $hesabix_currency == 'IRT' && $woocommerce_currency == 'IRR' ) ) { - update_option( 'ssbhesabix_hesabix_default_currency', $hesabix_currency ); - } else { - update_option( 'ssbhesabix_hesabix_default_currency', 0 ); - update_option( 'ssbhesabix_live_mode', 0 ); - - echo '
'; - echo '

' . __( 'Hesabix and WooCommerce default currency must be same.', 'ssbhesabix' ); - echo '

'; - } - } else { - echo '
'; - echo '

' . __( 'Cannot check the Hesabix default currency. Error Message: ', 'ssbhesabix' ) . $default_currency->ErrorMessage . '

'; - echo '
'; - - HesabixLogService::log( array( "Cannot check the Hesabix default currency. Error Message: $default_currency->ErrorMessage. Error Code: $default_currency->ErrorCode" ) ); - } - - if ( get_option( 'ssbhesabix_live_mode' ) ) { - echo '
'; - echo '

' . __( 'API Setting updated. Test Successfully', 'ssbhesabix' ) . '

'; - echo '
'; - } - - //add gift wrapping service - $wpFaService = new HesabixWpFaService(); - $wpFa = $wpFaService->getWpFa('gift_wrapping', 0); - if(!$wpFa) { - $gift_wrapping = $ssbhesabix_api->itemSave(array( - 'name' => 'خدمات بسته بندی هدیه', - 'khadamat' => 1, - 'Tag' => json_encode(array('id_product' => 0, 'id_attribute' => 0)) - )); - - if($gift_wrapping->Success) { - $wpFa = new WpFa(); - $wpFa->idPs = 0; - $wpFa->idPsAttribute = 0; - $wpFa->idHesabix = $gift_wrapping->code; - $wpFa->objType = 'gift_wrapping'; - $wpFaService->save($wpFa); - $msg = 'Hesabix Gift wrapping service added successfully. Service Code: ' . $gift_wrapping->Result->Code; - HesabixLogService::writeLogStr($msg); - } else { - $msg = 'Cannot set Gift wrapping service code. Error Message: ' . $gift_wrapping->ErrorMessage . ', Error Code: ' . $gift_wrapping->ErrorCode; - HesabixLogService::writeLogStr($msg); - } - } - } else { - update_option( 'ssbhesabix_live_mode', 0 ); - - if ( $response->ErrorCode === 108 ) { - echo '
'; - echo '

' . __( 'Cannot connect to Hesabix. Business expired.', 'ssbhesabix' ) . $response->ErrorMessage . '

'; - echo '
'; - update_option( 'ssbhesabix_business_expired', 1 ); - } else { - echo '
'; - echo '

' . __( 'Cannot set Hesabix webHook. Error Message:', 'ssbhesabix' ) . $response->ErrorMessage . '

'; - echo '
'; - update_option( 'ssbhesabix_business_expired', 0 ); - } - - HesabixLogService::log( array("Cannot set Hesabix webHook. Error Message: $response->ErrorMessage. Error Code: $response->ErrorCode") ); - } - } else { - update_option( 'ssbhesabix_live_mode', 0 ); - - echo '
'; - echo '

' . __( 'Cannot connect to Hesabix servers. Please check your Internet connection', 'ssbhesabix' ) . '

'; - echo '
'; - - HesabixLogService::log( array("Cannot connect to hesabix servers. Check your internet connection" ) ); - } - - return $response; - } -//============================================================================================= - public static function ssbhesabix_get_banks() { - $ssbhesabix_api = new Ssbhesabix_Api(); - $banks = $ssbhesabix_api->settingGetBanks(); - - if ( is_object( $banks ) && $banks->Success ) { - $available_banks = array(); - $available_banks[ - 1 ] = __( 'Choose', 'ssbhesabix' ); - foreach ( $banks->Result as $bank ) { - if ( $bank->Currency == get_woocommerce_currency() || ( get_woocommerce_currency() == 'IRT' && $bank->Currency == 'IRR' ) || ( get_woocommerce_currency() == 'IRR' && $bank->Currency == 'IRT' ) ) { - $available_banks[ 'bank'.$bank->Code ] = $bank->Name . ' - ' . $bank->Branch . ' - ' . $bank->AccountNumber; - } - } - - if ( empty( $available_banks ) ) { - $available_banks[0] = __( 'Define at least one bank in Hesabix', 'ssbhesabix' ); - } - - return $available_banks; - } else { - update_option( 'ssbhesabix_live_mode', 0 ); - - echo '
'; - echo '

' . __( 'Cannot get Banks detail.', 'ssbhesabix' ) . '

'; - echo '
'; - - HesabixLogService::log( array("Cannot get banking information. Error Code: $banks->ErrorCode. Error Message: $banks->ErrorMessage." ) ); - - return array( '0' => __( 'Cannot get Banks detail.', 'ssbhesabix' ) ); - } - } -//============================================================================================= - public static function ssbhesabix_get_cashes() { - $ssbhesabix_api = new Ssbhesabix_Api(); - $cashes = $ssbhesabix_api->settingGetCashes(); - - if ( is_object( $cashes ) && $cashes->Success ) { - $available_cashes = array(); - foreach ( $cashes->Result as $cash ) { - if ( $cash->Currency == get_woocommerce_currency() || ( get_woocommerce_currency() == 'IRT' && $cash->Currency == 'IRR' ) || ( get_woocommerce_currency() == 'IRR' && $cash->Currency == 'IRT' ) ) { - $available_cashes[ 'cash'.$cash->Code ] = $cash->Name; - } - } - return $available_cashes; - } - } -//============================================================================================= - public static function ssbhesabix_get_projects() { - $ssbhesabix_api = new Ssbhesabix_Api(); - $projects = $ssbhesabix_api->settingGetProjects(); - - if ( is_object( $projects ) && $projects->Success ) { - $available_projects = array(); - $available_projects[ - 1 ] = __( 'Choose', 'ssbhesabix' ); - foreach ( $projects->data as $project ) { - $available_projects[ $project->id ] = $project->name; - } - - return $available_projects; - } else { - update_option( 'ssbhesabix_live_mode', 0 ); - echo '
'; - echo '

' . __( 'Cannot get Projects detail.', 'ssbhesabix' ) . '

'; - echo '
'; - HesabixLogService::log( array("Cannot get projects information. Error Code:$projects->ErrorCode. Error Message: $projects->ErrorMessage.") ); - - return array( '0' => __( 'Cannot get projects detail.', 'ssbhesabix' ) ); - } - } -//============================================================================================= - public static function ssbhesabix_get_salesmen() { - $ssbhesabix_api = new Ssbhesabix_Api(); - $salesmen = $ssbhesabix_api->settingGetSalesmen(); - - if ( is_object( $salesmen ) && $salesmen->Success ) { - $available_salesmen = array(); - $available_salesmen[ - 1 ] = __( 'Choose', 'ssbhesabix' ); - foreach ( $salesmen->result as $salesman ) { - $available_salesmen[ $salesman->code ] = $salesman->nikename; - } - - return $available_salesmen; - } else { - update_option( 'ssbhesabix_live_mode', 0 ); - echo '
'; - echo '

' . __( 'Cannot get Salesmen detail.', 'ssbhesabix' ) . '

'; - echo '
'; - HesabixLogService::log( array("Cannot get salesmen information. Error Code: $salesmen->ErrorCode Error Message: .$salesmen->ErrorMessage.") ); - - return array( '0' => __( 'Cannot get salesmen detail.', 'ssbhesabix' ) ); - } - } -//============================================================================================= - public static function ssbhesabix_log_setting() { - $cleanLogResult = ( isset( $_GET['cleanLogResult'] ) ) ? wc_clean( $_GET['cleanLogResult'] ) : null; - - if ( ! is_null( $cleanLogResult ) && $cleanLogResult === 'true' ) { - echo '
'; - echo '

' . __( 'The log file was cleared.', 'ssbhesabix' ) . '

'; - echo '
'; - } elseif ( $cleanLogResult === 'false' ) { - echo '
'; - echo '

' . __( 'Log file not found.', 'ssbhesabix' ) . '

'; - echo '
'; - } - - self::ssbhesabix_tab_log_html(); - } -//============================================================================================= - public static function ssbhesabix_tab_log_html() { - ?> -
-
- توجه فرمایید با زدن دکمه پاک کردن کل لاگ ها، تمامی فایل های لاگ ذخیره شده پاک می شوند. -
- در صورت نیاز به پاک کردن فایل لاگ جاری می توانید از دکمه پاک کردن لاگ جاری، زمانی که فایل لاگ مدنظر انتخاب شده است، استفاده کنید. -
- فهرست تاریخچه لاگ ها، لاگ های موجود در سیستم در بازه 10 روز گذشته را نمایش می دهد. -
-

-
-
- -
-
-
- -
-
-
-
-
- -
- "> - - -
-
-
-
- -
-
- "> - -
-
-
-
-
-
-
-
-
-
- -
- - -
-
-
-
-
-
-
-
-
- -
- - - -
-
-
-
-
- 1000 ) { - - $fileSizeInMb = ( ( filesize( WP_CONTENT_DIR . '/ssbhesabix-' . date("20y-m-d") . '.txt' ) / 1000 ) / 1000 ); - $fileSizeInMb = round( $fileSizeInMb, 2 ); - - - $str = __( 'The log file size is large, clean log file.', 'ssbhesabix' ); - - echo '
' . - '

' . $str . ' (' . $fileSizeInMb . 'MB)' . '

' - . '
'; - - } else if ( file_exists( WP_CONTENT_DIR . '/ssbhesabix-' . date("20y-m-d") . '.txt' ) ) { - - $URL = WP_CONTENT_DIR . '/ssbhesabix-' . date("20y-m-d") . '.txt'; - $logFileContent = HesabixLogService::readLog($URL); - } - - echo '
'. - '
-

' . __("Log History", "ssbhesabix") . '

-
-
    '; - for($i = 0 ; $i < 10 ; $i++) { - if( file_exists( WP_CONTENT_DIR . '/ssbhesabix-' . date("20y-m-d", strtotime(-$i."day")) . '.txt' ) ) { - echo '
  • '; - } - } - echo ' -
-
-
'; - echo ''; - echo '
'; -//--------------------------------------- - if(isset($_POST["changeLogFile"])) { - echo - ''; - - $URL = WP_CONTENT_DIR . '/ssbhesabix-' . $_POST["changeLogFile"] . '.txt'; - $logFileContent = HesabixLogService::readLog($URL); - - echo '
'. - '
-

' . __("Log History", "ssbhesabix") . '

-
-
    '; - for($i = 0 ; $i < 10 ; $i++) { - if( file_exists( WP_CONTENT_DIR . '/ssbhesabix-' . date("20y-m-d", strtotime(-$i."day")) . '.txt' ) ) { - echo '
  • '; - } - } - echo ' -
-
-
'; - echo ''; - echo '
'; - } -//--------------------------------------- - if(isset($_POST["deleteLogFiles"])) { - $prefix = WP_CONTENT_DIR . '/ssbhesabix-'; - - $files = glob($prefix . '*'); - if ($files) { - foreach ($files as $file) { - if (is_file($file)) { - if (unlink($file)) { - header("refresh:0"); - } else { - HesabixLogService::writeLogStr("Unable to delete the file"); - } - } - } - } else { - HesabixLogService::writeLogStr("No files found"); - } - } -//--------------------------------------- - if(isset($_POST["ssbhesabix-log-clean-submit"])) { - if($_POST["currentLogFileDate"]) { - $file = WP_CONTENT_DIR . '/ssbhesabix-' . $_POST["currentLogFileDate"] . '.txt'; - } else { - $file = WP_CONTENT_DIR . '/ssbhesabix-' . date("20y-m-d") . '.txt'; - } - if (is_file($file)) { - if (unlink($file)) { - HesabixLogService::writeLogStr("Selected Log File Deleted"); - header("refresh:0"); - } else { - HesabixLogService::writeLogStr("Unable to delete the file"); - } - } - } -//--------------------------------------- - if(isset($_POST["ssbhesabix-delete-logs-between-two-dates"])) { - $startDate = $_POST["ssbhesabix_delete_log_date_from"]; - $endDate = $_POST["ssbhesabix_delete_log_date_to"]; - - $directory = WP_CONTENT_DIR . '/ssbhesabix-'; - $files = glob($directory . '*'); - if($files) { - foreach ($files as $file) { - if(is_file($file)) { - $fileDate = substr($file, strlen($directory), 10); - $dateObj = DateTime::createFromFormat('Y-m-d', $fileDate); - $startObj = DateTime::createFromFormat('Y-m-d', $startDate); - $endObj = DateTime::createFromFormat('Y-m-d', $endDate); - - if ($dateObj >= $startObj && $dateObj <= $endObj) { - HesabixLogService::writeLogStr("Log Files deleted"); - unlink($file); - } - } - } - } - header("refresh:0"); - } -//--------------------------------------- - if(isset($_POST["ssbhesabix-find-log-submit"])) { - echo - ''; - - $URL = WP_CONTENT_DIR . '/ssbhesabix-' . $_POST["ssbhesabix_find_log_date"] . '.txt'; - if ( file_exists( WP_CONTENT_DIR . '/ssbhesabix-' . $_POST["ssbhesabix_find_log_date"] . '.txt' ) && - ( filesize( WP_CONTENT_DIR . '/ssbhesabix-' . $_POST["ssbhesabix_find_log_date"] . '.txt' ) / 1000 ) < 1000 ) { - $logFileContent = HesabixLogService::readLog($URL); - } - - - echo '
'. - '
-

' . __("Log History", "ssbhesabix") . '

-
-
    '; - for($i = 0 ; $i < 10 ; $i++) { - if( file_exists( WP_CONTENT_DIR . '/ssbhesabix-' . date("20y-m-d", strtotime(-$i."day")) . '.txt' ) ) { - echo '
  • '; - } - } - echo ' -
-
-
'; - echo ''; - echo '
'; - } - ?> -
- settingGetWarehouses(); - - if ( is_object( $warehouses->data ) ) { - $available_warehouses = array(); - $available_warehouses[ - 1 ] = __( 'Accounting quantity (Total inventory)', 'ssbhesabix' ); - - return $available_warehouses; - } - - if ( is_object( $warehouses ) && $warehouses->Success ) { - $available_warehouses = array(); - $available_warehouses[ - 1 ] = __( 'Accounting quantity (Total inventory)', 'ssbhesabix' ); - foreach ( $warehouses->data as $warehouse ) { - $available_warehouses[ $warehouse->code ] = $warehouse->name; - } - - return $available_warehouses; - } else { - update_option( 'ssbhesabix_live_mode', 0 ); - echo '
'; - echo '

' . __( 'Cannot get warehouses.', 'ssbhesabix' ) . '

'; - echo '
'; - HesabixLogService::log( array("Cannot get warehouses. Error Code: $warehouses->ErrorCode. Error Message: .$warehouses->ErrorMessage.") ); - - return array( '0' => __( 'Cannot get warehouses.', 'ssbhesabix' ) ); - } - } - -} - -Ssbhesabix_Setting::init(); diff --git a/admin/services/HesabixLogService.php b/admin/services/HesabixLogService.php index 0efb931..b3d933f 100644 --- a/admin/services/HesabixLogService.php +++ b/admin/services/HesabixLogService.php @@ -1,12 +1,20 @@ format('[Y-m-d H:i:s] '); $str = $date . $str; @@ -16,7 +24,7 @@ class HesabixLogService public static function writeLogObj($obj) { - $fileName = WP_CONTENT_DIR . '/ssbhesabix-' . date("20y-m-d") . '.txt'; + $fileName = WP_CONTENT_DIR . '/hesabix-' . date("20y-m-d") . '.txt'; ob_start(); var_dump($obj); file_put_contents($fileName, PHP_EOL . ob_get_flush(), FILE_APPEND); @@ -24,10 +32,10 @@ class HesabixLogService public static function log($params) { - $fileName = WP_CONTENT_DIR . '/ssbhesabix-' . date("20y-m-d") . '.txt'; + $fileName = WP_CONTENT_DIR . '/hesabix-' . date("20y-m-d") . '.txt'; $log = ''; - $dateTime = new DateTimeImmutable( 'now', wp_timezone() ); + $dateTime = new DateTimeImmutable('now', wp_timezone()); $date = $dateTime->format('[Y-m-d H:i:s] '); foreach ($params as $message) { @@ -51,7 +59,7 @@ class HesabixLogService public static function clearLog() { - $fileName = WP_CONTENT_DIR . '/ssbhesabix-' . date("20y-m-d") . '.txt'; + $fileName = WP_CONTENT_DIR . '/hesabix-' . date("20y-m-d") . '.txt'; if (file_exists($fileName)) { file_put_contents($fileName, ""); } @@ -59,6 +67,6 @@ class HesabixLogService public static function getLogFilePath() { - return WP_CONTENT_DIR . '/ssbhesabix-' . date("20y-m-d") . '.txt'; + return WP_CONTENT_DIR . '/hesabix-' . date("20y-m-d") . '.txt'; } } \ No newline at end of file diff --git a/admin/services/HesabixWpFaService.php b/admin/services/HesabixWpFaService.php index b39f873..07df003 100644 --- a/admin/services/HesabixWpFaService.php +++ b/admin/services/HesabixWpFaService.php @@ -1,6 +1,14 @@ id = $id; @@ -20,25 +32,28 @@ class WpFa $instance->idHesabix = $idHesabix; $instance->idWp = $idWp; $instance->idWpAttribute = $idWpAttribute; + $instance->uidHesabix = $uidHesabix; return $instance; } } class HesabixWpFaService { - public function __construct() {} - - public function getWpFa($objType, $idWp, $idWpAttribute = 0) + public function __construct() { - if (!isset($objType) || !isset($idWp)) return false; + } + + public function getWpFaByWpId($objType, $idWp, $idWpAttribute = 0) + { + if (!isset($objType) || !isset($idWp)) + return false; global $wpdb; - //$row = $wpdb->get_row("SELECT * FROM " . $wpdb->prefix . "ssbhesabix WHERE `id_ps` = $idWp AND `id_ps_attribute` = $idWpAttribute AND `obj_type` = '$objType'"); $row = $wpdb->get_row( $wpdb->prepare( "SELECT * - FROM {$wpdb->prefix}ssbhesabix + FROM {$wpdb->prefix}hesabix WHERE `id_ps` = %d AND `id_ps_attribute` = %d AND `obj_type` = %s", @@ -49,11 +64,39 @@ class HesabixWpFaService ); - if (isset($row)) return $this->mapWpFa($row); + if (isset($row)) + return $this->mapWpFa($row); return null; } -//========================================================================================================= + + public function getWpFaByHesabixCode($objType, $codehx, $idWpAttribute = 0) + { + if (!isset($objType) || !isset($codehx)) + return false; + + global $wpdb; + + $row = $wpdb->get_row( + $wpdb->prepare( + "SELECT * + FROM {$wpdb->prefix}hesabix + WHERE `id_hesabix` = %d + AND `id_ps_attribute` = %d + AND `obj_type` = %s", + $codehx, + $idWpAttribute, + $objType + ) + ); + + + if (isset($row)) + return $this->mapWpFa($row); + + return null; + } + public function getWpFaSearch($woocommerce_search_code = '', $woocommerce_attribute_search_code = '', $hesabix_search_code = '', $obj_type_search = '') { global $wpdb; @@ -81,7 +124,7 @@ class HesabixWpFaService $params[] = $obj_type_search; } - $sql = "SELECT * FROM {$wpdb->prefix}ssbhesabix"; + $sql = "SELECT * FROM {$wpdb->prefix}hesabix"; if (!empty($conditions)) { $sql .= " WHERE " . implode(" AND ", $conditions); } @@ -99,18 +142,18 @@ class HesabixWpFaService return $wpFaObjects; } -//========================================================================================================= + public function getWpFaByHesabixId($objType, $hesabixId) { - if (!isset($objType) || !isset($hesabixId)) return false; + if (!isset($objType) || !isset($hesabixId)) + return false; global $wpdb; - //$row = $wpdb->get_row("SELECT * FROM " . $wpdb->prefix . "ssbhesabix WHERE `id_hesabix` = $hesabixId AND `obj_type` = '$objType'"); $row = $wpdb->get_row( $wpdb->prepare( "SELECT * - FROM {$wpdb->prefix}ssbhesabix + FROM {$wpdb->prefix}hesabix WHERE `id_hesabix` = %d AND `obj_type` = %s", $hesabixId, @@ -122,19 +165,18 @@ class HesabixWpFaService return $this->mapWpFa($row); return null; } -//========================================================================================================= + public function getWpFaId($objType, $idWp, $idWpAttribute = 0) { if (!isset($objType) || !isset($idWp)) return false; global $wpdb; - //$row = $wpdb->get_row("SELECT `id` FROM " . $wpdb->prefix . "ssbhesabix WHERE `id_ps` = $idWp AND `id_ps_attribute` = $idWpAttribute AND `obj_type` = '$objType'"); $row = $wpdb->get_row( $wpdb->prepare( "SELECT `id` - FROM {$wpdb->prefix}ssbhesabix + FROM {$wpdb->prefix}hesabix WHERE `id_ps` = %d AND `id_ps_attribute` = %d AND `obj_type` = %s", @@ -145,23 +187,22 @@ class HesabixWpFaService ); if (is_object($row)) - return (int)$row->id; + return (int) $row->id; else return false; } -//========================================================================================================= + public function getWpFaIdByHesabixId($objType, $hesabixId) { if (!isset($objType) || !isset($hesabixId)) return false; global $wpdb; - //$row = $wpdb->get_row("SELECT `id` FROM " . $wpdb->prefix . "ssbhesabix WHERE `id_hesabix` = $hesabixId AND `obj_type` = '$objType'"); $row = $wpdb->get_row( $wpdb->prepare( "SELECT `id` - FROM {$wpdb->prefix}ssbhesabix + FROM {$wpdb->prefix}hesabix WHERE `id_hesabix` = %d AND `obj_type` = %s", $hesabixId, @@ -171,47 +212,103 @@ class HesabixWpFaService if (isset($row)) - return (int)$row->id; + return (int) $row->id; return null; } -//========================================================================================================= + public function getProductCodeByWpId($id_product, $id_attribute = 0) { - $obj = $this->getWpFa('product', $id_product, $id_attribute); + $obj = $this->getWpFaByWpId('product', $id_product, $id_attribute); - if ($obj != null) return $obj->idHesabix; + if ($obj != null) + return $obj->idHesabix; return null; } -//========================================================================================================= + + public function getProductUidByWpId($id_product, $id_attribute = 0) + { + $obj = $this->getWpFaByWpId('product', $id_product, $id_attribute); + + if ($obj != null) + return $obj->uidHesabix; + + return null; + } + + public function getProductUidByCode($code) + { + $obj = $this->getWpFaByHesabixCode('product', $code); + + if ($obj != null) + return $obj->uidHesabix; + + $api = new Hesabix_Api(); + $response = $api->apiRequest('api/commodity/info/' . $code); + if ($response->code == $code) { + return $response->id; + } + + return null; + } + public function getCustomerCodeByWpId($id_customer) { - $obj = $this->getWpFa('customer', $id_customer); + $obj = $this->getWpFaByWpId('customer', $id_customer); - if ($obj != null) return $obj->idHesabix; + if ($obj != null) + return $obj->idHesabix; return null; } -//========================================================================================================= + + public function getCustomerUidByWpId($id_customer) + { + $obj = $this->getWpFaByWpId('customer', $id_customer); + + if ($obj != null) + return $obj->uidHesabix; + + return null; + } + + public function getCustomerUidByCode($code_customer) + { + $obj = $this->getWpFaByHesabixCode('customer', $code_customer); + + if ($obj != null) + return $obj->uidHesabix; + + return null; + } + public function getInvoiceCodeByWpId($id_order) { - $obj = $this->getWpFa('order', $id_order); + $obj = $this->getWpFaByWpId('order', $id_order); - if ($obj != null) return $obj->idHesabix; + if ($obj != null) + return $obj->idHesabix; return null; } -//========================================================================================================= + + public function getInvoiceUidByWpId($id_order) + { + $obj = $this->getWpFaByWpId('order', $id_order); + + if ($obj != null) + return $obj->uidHesabix; + + return null; + } + public function getProductAndCombinations($idWp) { global $wpdb; - //$sql = "SELECT * FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `obj_type` = 'product' AND `id_ps` = '$idWp'"; - //$result = $wpdb->get_results($sql); - $sql = $wpdb->prepare( "SELECT * - FROM {$wpdb->prefix}ssbhesabix + FROM {$wpdb->prefix}hesabix WHERE `obj_type` = 'product' AND `id_ps` = %d", $idWp @@ -228,85 +325,93 @@ class HesabixWpFaService } return null; } -//========================================================================================================= + public function mapWpFa($sqlObj): WpFa { $wpFa = new WpFa(); $wpFa->id = $sqlObj->id; $wpFa->idHesabix = $sqlObj->id_hesabix; + $wpFa->uidHesabix = $sqlObj->uid_hesabix; $wpFa->idWp = $sqlObj->id_ps; $wpFa->idWpAttribute = $sqlObj->id_ps_attribute; $wpFa->objType = $sqlObj->obj_type; return $wpFa; } -//========================================================================================================= + public function saveProduct($item): bool { - $json = json_decode($item->Tag); + $hesabix_code = 0; + $id_product = 0; + $id_attribute = 0; + if (isset($item->code)) + $hesabix_code = (int) $item->code; + if (isset($item->id)) + $hesabix_uid = (int) $item->id; + if (isset($item->tags)) { + $json = $item->tags; + if (isset($json->id_product)) + $id_product = (int) $json->id_product; + if (isset($json->id_attribute)) + $id_attribute = (int) $json->id_attribute; + } + $wpFaService = new HesabixWpFaService(); - $wpFa = $wpFaService->getWpFaByHesabixId('product', $item->Code); + $wpFa = $wpFaService->getWpFaByHesabixId('product', $hesabix_code); if (!$wpFa) { - $wpFa = WpFa::newWpFa(0, 'product', (int)$item->Code, (int)$json->id_product, (int)$json->id_attribute); + $wpFa = WpFa::newWpFa(0, 'product', $hesabix_code, $id_product, $id_attribute, $hesabix_uid); $wpFaService->save($wpFa); - HesabixLogService::log(array("Item successfully added. Item code: " . (string)$item->Code . ". Product ID: $json->id_product-$json->id_attribute")); + HesabixLogService::log(array("Item successfully added. Item code: $hesabix_code. Product ID: $id_product-$id_attribute")); } else { - $wpFa->idHesabix = (int)$item->Code; + $wpFa->idHesabix = $hesabix_code; + $wpFa->uidHesabix = $hesabix_uid; $wpFaService->update($wpFa); - HesabixLogService::log(array("Item successfully updated. Item code: " . (string)$item->Code . ". Product ID: $json->id_product-$json->id_attribute")); + HesabixLogService::log(array("Item successfully updated. Item code: $hesabix_code. Product ID: $id_product-$id_attribute")); } return true; } -//========================================================================================================= + public function saveCustomer($customer): bool { - $json = json_decode($customer->Tag); - if ((int)$json->id_customer == 0) return true; + $json = json_decode($customer->tags); + if ((int) $json->id_customer == 0) + return true; - $id = $this->getWpFaId('customer', (int)$json->id_customer); + $id = $this->getWpFaId('customer', (int) $json->id_customer); global $wpdb; if (!$id) { -// $wpdb->insert($wpdb->prefix . 'ssbhesabix', array( -// 'id_hesabix' => (int)$customer->Code, -// 'obj_type' => 'customer', -// 'id_ps' => (int)$json->id_customer -// )); $wpdb->insert( - $wpdb->prefix . 'ssbhesabix', + $wpdb->prefix . 'hesabix', array( - 'id_hesabix' => (int)$customer->Code, + 'id_hesabix' => (int) $customer->code, + 'uid_hesabix' => (int) $customer->id, 'obj_type' => 'customer', - 'id_ps' => (int)$json->id_customer + 'id_ps' => (int) $json->id_customer ), array( + '%d', '%d', '%s', '%d' ) ); - - - HesabixLogService::writeLogStr("Customer successfully added. Customer code: " . (string)$customer->Code . ". Customer ID: $json->id_customer"); + HesabixLogService::writeLogStr("Customer successfully added. Customer code: " . (string) $customer->code . ". Customer ID: $json->id_customer"); } else { -// $wpdb->update($wpdb->prefix . 'ssbhesabix', array( -// 'id_hesabix' => (int)$customer->Code, -// 'obj_type' => 'customer', -// 'id_ps' => (int)$json->id_customer, -// ), array('id' => $id)); - $wpdb->update( - $wpdb->prefix . 'ssbhesabix', + $wpdb->prefix . 'hesabix', array( - 'id_hesabix' => (int)$customer->Code, + 'id_hesabix' => (int) $customer->code, + 'uid_hesabix' => (int) $customer->id, 'obj_type' => 'customer', - 'id_ps' => (int)$json->id_customer, + 'id_ps' => (int) $json->id_customer, ), array('id' => $id), array( + '%d', '%d', '%s', '%d' @@ -314,165 +419,128 @@ class HesabixWpFaService array('%d') ); - HesabixLogService::writeLogStr("Customer successfully updated. Customer code: " . (string)$customer->Code . ". Customer ID: $json->id_customer"); + HesabixLogService::writeLogStr("Customer successfully updated. Customer code: " . (string) $customer->code . ". Customer ID: $json->id_customer"); } return true; } -//========================================================================================================= + public function saveInvoice($invoice, $orderType) { $json = json_decode($invoice->Tag); - $id = $this->getPsFaId('order', (int)$json->id_order); + $id = $this->getPsFaId('order', (int) $json->id_order); - $invoiceNumber = (int)$invoice->Number; + $invoiceNumber = (int) $invoice->Number; $objType = $orderType == 0 ? 'order' : 'returnOrder'; if (!$id) { -// Db::getInstance()->insert('ps_hesabix', array( -// 'id_hesabix' => $invoiceNumber, -// 'obj_type' => $objType, -// 'id_ps' => (int)$json->id_order, -// )); - Db::getInstance()->insert('ps_hesabix', array( 'id_hesabix' => $invoiceNumber, 'obj_type' => $objType, - 'id_ps' => (int)$json->id_order, + 'id_ps' => (int) $json->id_order, )); if ($objType == 'order') - LogService::writeLogStr("Invoice successfully added. invoice number: " . (string)$invoice->Number . ", order id: " . $json->id_order); + LogService::writeLogStr("Invoice successfully added. invoice number: " . (string) $invoice->Number . ", order id: " . $json->id_order); else - LogService::writeLogStr("Return Invoice successfully added. Customer code: " . (string)$invoice->Number . ", order id: " . $json->id_order); + LogService::writeLogStr("Return Invoice successfully added. Customer code: " . (string) $invoice->Number . ", order id: " . $json->id_order); } else { -// Db::getInstance()->update('ps_hesabix', array( -// 'id_hesabix' => $invoiceNumber, -// 'obj_type' => $objType, -// 'id_ps' => (int)$json->id_order, -// ), array('id' => $id), 0, true, true); - - Db::getInstance()->update('ps_hesabix', array( 'id_hesabix' => $invoiceNumber, 'obj_type' => $objType, - 'id_ps' => (int)$json->id_order, + 'id_ps' => (int) $json->id_order, ), array('id' => $id), 0, true, true); - //check if it is order or return order + if ($objType == 'order') - LogService::writeLogStr("Invoice successfully updated. invoice number: " . (string)$invoice->Number . ", order id: " . $json->id_order); + LogService::writeLogStr("Invoice successfully updated. invoice number: " . (string) $invoice->Number . ", order id: " . $json->id_order); else - LogService::writeLogStr("Return Invoice successfully updated. Customer code: " . (string)$invoice->Number . ", order id: " . $json->id_order); + LogService::writeLogStr("Return Invoice successfully updated. Customer code: " . (string) $invoice->Number . ", order id: " . $json->id_order); } return true; } -//========================================================================================================= + public function save(WpFa $wpFa) { global $wpdb; -// $wpdb->insert($wpdb->prefix . 'ssbhesabix', array( -// 'id_hesabix' => $wpFa->idHesabix, -// 'obj_type' => $wpFa->objType, -// 'id_ps' => (int)$wpFa->idWp, -// 'id_ps_attribute' => (int)$wpFa->idWpAttribute, -// )); $wpdb->insert( - $wpdb->prefix . 'ssbhesabix', + $wpdb->prefix . 'hesabix', array( 'id_hesabix' => $wpFa->idHesabix, 'obj_type' => $wpFa->objType, - 'id_ps' => (int)$wpFa->idWp, - 'id_ps_attribute' => (int)$wpFa->idWpAttribute, + 'id_ps' => (int) $wpFa->idWp, + 'id_ps_attribute' => (int) $wpFa->idWpAttribute, + 'uid_hesabix' => (int) $wpFa->uidHesabix, ), array( '%s', '%s', '%d', - '%d' + '%d', + '%s' ) ); } -//========================================================================================================= -// public function update(WpFa $wpFa) -// { -// global $wpdb; -// $wpdb->update($wpdb->prefix . 'ssbhesabix', array( -// 'id_hesabix' => $wpFa->idHesabix, -// 'obj_type' => $wpFa->objType, -// 'id_ps' => (int)$wpFa->idWp, -// 'id_ps_attribute' => (int)$wpFa->idWpAttribute, -// ), array('id' => $wpFa->id)); -// } + public function update(WpFa $wpFa) { global $wpdb; $idHesabix = isset($wpFa->idHesabix) ? sanitize_text_field($wpFa->idHesabix) : ''; + $uidHesabix = isset($wpFa->uidHesabix) ? sanitize_text_field($wpFa->uidHesabix) : ''; $objType = isset($wpFa->objType) ? sanitize_text_field($wpFa->objType) : ''; - $idWp = isset($wpFa->idWp) ? (int)$wpFa->idWp : 0; - $idWpAttribute = isset($wpFa->idWpAttribute) ? (int)$wpFa->idWpAttribute : 0; + $idWp = isset($wpFa->idWp) ? (int) $wpFa->idWp : 0; + $idWpAttribute = isset($wpFa->idWpAttribute) ? (int) $wpFa->idWpAttribute : 0; $wpdb->update( - $wpdb->prefix . 'ssbhesabix', + $wpdb->prefix . 'hesabix', array( 'id_hesabix' => $idHesabix, 'obj_type' => $objType, 'id_ps' => $idWp, 'id_ps_attribute' => $idWpAttribute, + 'uid_hesabix' => $uidHesabix, ), array('id' => $wpFa->id), array( '%s', '%s', '%d', - '%d' + '%d', + '%s' ), array('%d') ); } -//========================================================================================================= -// public function delete(WpFa $wpFa) -// { -// global $wpdb; -// $wpdb->delete($wpdb->prefix . 'ssbhesabix', array('id' => $wpFa->id)); -// } public function delete(WpFa $wpFa) { global $wpdb; - $id = isset($wpFa->id) ? (int)$wpFa->id : 0; + $id = isset($wpFa->id) ? (int) $wpFa->id : 0; $wpdb->delete( - $wpdb->prefix . 'ssbhesabix', + $wpdb->prefix . 'hesabix', array('id' => $id), array('%d') ); } -//========================================================================================================= -// public function deleteAll($productId) -// { -// global $wpdb; -// $wpdb->delete($wpdb->prefix . 'ssbhesabix', array('id_ps' => $productId)); -// } + public function deleteAll($productId) { global $wpdb; - $productId = isset($productId) ? (int)$productId : 0; + $productId = isset($productId) ? (int) $productId : 0; $wpdb->delete( - $wpdb->prefix . 'ssbhesabix', + $wpdb->prefix . 'hesabix', array('id_ps' => $productId), array('%d') ); } - -//========================================================================================================= } \ No newline at end of file diff --git a/admin/services/hesabixCustomerService.php b/admin/services/hesabixCustomerService.php new file mode 100644 index 0000000..2179760 --- /dev/null +++ b/admin/services/hesabixCustomerService.php @@ -0,0 +1,235 @@ +get_first_name() ?: $customer->get_billing_first_name(); + $lastName = $customer->get_last_name() ?: $customer->get_billing_last_name(); + $name = trim($firstName . ' ' . $lastName); + if (empty($name)) $name = __('Not Defined', 'hesabix'); + + $checkout_fields = HesabixCustomerService::getAdditionalCheckoutFileds($id_order); + $NationalCode = $checkout_fields['NationalCode'] ?? ''; + $EconomicCode = $checkout_fields['EconomicCode'] ?? ''; + $RegistrationNumber = $checkout_fields['RegistrationNumber'] ?? ''; + $Website = $checkout_fields['Website'] ?? ''; + $nodeFamily = get_option('hesabix_contact_automatic_save_node_family') === 'yes' + ? __('Persons:', 'hesabix') . get_option('hesabix_contact_node_family') : null; + + if ($type === 'shipping') { + $country_code = $order->get_shipping_country(); + $state_code = $order->get_shipping_state(); + $fullAddress = $order->get_shipping_address_1() . '-' . $order->get_shipping_address_2(); + $city = $order->get_shipping_city(); + $postalCode = $order->get_shipping_postcode(); + } else { + $country_code = $order->get_billing_country(); + $state_code = $order->get_billing_state(); + $fullAddress = $order->get_billing_address_1() . '-' . $order->get_billing_address_2(); + $city = $order->get_billing_city(); + $postalCode = $order->get_billing_postcode(); + } + + if (strlen($fullAddress) < 5) { + $fullAddress = $customer->get_billing_address_1() . '-' . $customer->get_billing_address_2(); + } + if (empty($postalCode)) { + $postalCode = $customer->get_billing_postcode(); + } + + if (preg_match('/^\d+$/', $city)) { + $func = new Hesabix_Admin_Functions(); + $city = $func->convertCityCodeToName($city); + } + + $country_name = self::$countries[$country_code] ?? ''; + $state_name = self::$states[$country_code][$state_code] ?? ''; + + $hesabixCustomer = [ + 'nikename' => $name, + 'name' => Hesabix_Validation::contactFirstNameValidation($firstName) . Hesabix_Validation::contactLastNameValidation($lastName), + 'des' => __('Customer ID in OnlineStore: ', 'hesabix') . $id_customer, + 'tel' => (strlen(preg_replace('/\D/', '', $customer->get_billing_phone())) === 11) + ? Hesabix_Validation::contactPhoneValidation($customer->get_billing_phone()) + : '', + 'mobile' => '', + 'mobile2' => '', + 'address' => Hesabix_Validation::contactAddressValidation($fullAddress), + 'company' => '', + 'shenasemeli' => $NationalCode, + 'codeeghtesadi'=> $EconomicCode, + 'sabt' => $RegistrationNumber, + 'keshvar' => Hesabix_Validation::contactCountryValidation($country_name), + 'ostan' => Hesabix_Validation::contactStateValidation($state_name), + 'shahr' => Hesabix_Validation::contactCityValidation($city), + 'postalcode' => Hesabix_Validation::contactPostalCodeValidation($postalCode), + 'email' => Hesabix_Validation::contactEmailValidation($customer->get_email()), + 'website' => $Website, + 'fax' => '', + 'code' => (int) $code ?: 0, + 'types' => [ + [ 'label' => __('Customer', 'hesabix'), 'code' => 'customer', 'checked' => true ], + [ 'label' => __('Marketer', 'hesabix'), 'code' => 'marketer', 'checked' => false ], + [ 'label' => __('Employee', 'hesabix'), 'code' => 'emplyee', 'checked' => false ], + [ 'label' => __('Supplier', 'hesabix'),'code' => 'supplier', 'checked' => false ], + [ 'label' => __('Colleague', 'hesabix'), 'code' => 'colleague', 'checked' => false ], + [ 'label' => __('Salesman', 'hesabix'), 'code' => 'salesman', 'checked' => false ], + ], + 'accounts' => [], + 'prelabel' => null, + 'speedAccess' => false, + 'tags' => json_encode([ + 'id_customer' => $id_customer + ]) + ]; + + return self::correctCustomerData($hesabixCustomer); + } + public static function mapGuestCustomer($code, $id_order): array + { + $order = new WC_Order($id_order); + + $name = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(); + if (empty($order->get_billing_first_name()) && empty($order->get_billing_last_name())) { + $name = __('Guest Customer', 'hesabix'); + } + $nodeFamily = get_option('hesabix_contact_automatic_save_node_family') == 'yes'? __('Persons:', 'hesabix') . get_option('hesabix_contact_node_family') :null; + + $checkout_fields = hesabixCustomerService::getAdditionalCheckoutFileds($id_order); + $NationalCode = $checkout_fields['NationalCode']; + $EconomicCode = $checkout_fields['EconomicCode']; + $RegistrationNumber = $checkout_fields['RegistrationNumber']; + $Website = $checkout_fields['Website']; + + WC()->countries->countries[ $order->shipping_country ]; + $country_name = WC()->countries->countries[ $order->get_billing_country() ]; + $states = WC()->countries->get_states( $order->get_billing_country() ); + $state_name = $states[ $order->get_billing_state() ]; + if(!$state_name) $state_name = WC()->countries->states[$order->billing_country][$order->billing_state]; + if(!$state_name) $state_name = $order->get_billing_state(); + + $city = $order->get_billing_city(); + if(preg_match('/^[0-9]+$/', $city)) { + $func = new Hesabix_Admin_Functions(); + $city = $func->convertCityCodeToName($order->get_billing_city()); + } + + $fullAddress = $order->get_billing_address_1() . '-' . $order->get_billing_address_2(); + + $hesabixCustomer = array( + 'Code' => $code, + 'Name' => $name, + 'FirstName' => Hesabix_Validation::contactFirstNameValidation($order->get_billing_first_name()), + 'LastName' => Hesabix_Validation::contactLastNameValidation($order->get_billing_last_name()), + 'ContactType' => 1, + 'NationalCode' => $NationalCode, + 'EconomicCode' => $EconomicCode, + 'RegistrationNumber' => $RegistrationNumber, + 'Website' => $Website, + 'NodeFamily' => $nodeFamily, + 'Address' => Hesabix_Validation::contactAddressValidation($fullAddress), + 'City' => Hesabix_Validation::contactCityValidation($city), + 'State' => Hesabix_Validation::contactStateValidation($state_name), + 'Country' => Hesabix_Validation::contactCountryValidation($country_name), + 'PostalCode' => Hesabix_Validation::contactPostalCodeValidation($order->get_billing_postcode()), + 'Phone' => Hesabix_Validation::contactPhoneValidation($order->get_billing_phone()), + 'Email' => Hesabix_Validation::contactEmailValidation($order->get_billing_email()), + 'Tag' => json_encode(array('id_customer' => 0)), + 'Note' => __('Customer registered as a GuestCustomer.', 'hesabix'), + ); + + return self::correctCustomerData($hesabixCustomer); + } + + private static function getMobileFromPhone($phone) { + if(preg_match("/^09\d{9}$/", $phone)) + return $phone; + else if(preg_match("/^9\d{9}$/", $phone)) + return '0' . $phone; + else if(preg_match("/^989\d{9}$/", $phone)) + return str_replace('98', '0' ,$phone); + else return ''; + } + + private static function correctCustomerData($hesabixCustomer) { + if($hesabixCustomer["Phone"] == '') + unset($hesabixCustomer["Phone"]); + else { + $mobile = self::getMobileFromPhone($hesabixCustomer["Phone"]); + + if($mobile) $hesabixCustomer["Mobile"] = $mobile; + } + + if($hesabixCustomer["Email"] == '') unset($hesabixCustomer["Email"]); + if($hesabixCustomer["Address"] == '') unset($hesabixCustomer["Address"]); + if($hesabixCustomer["PostalCode"] == '') unset($hesabixCustomer["PostalCode"]); + if($hesabixCustomer["City"] == '') unset($hesabixCustomer["City"]); + if($hesabixCustomer["State"] == '') unset($hesabixCustomer["State"]); + if($hesabixCustomer["Country"] == '') unset($hesabixCustomer["Country"]); + + return $hesabixCustomer; + } + + private static function getCountriesAndStates() + { + if (!isset(self::$countries)) { + $countries_obj = new WC_Countries(); + self::$countries = $countries_obj->get_countries(); + self::$states = $countries_obj->get_states(); + } + } + + private static function getAdditionalCheckoutFileds($id_order) { + $NationalCode = '_billing_hesabix_nationalcode'; + $EconomicCode = '_billing_hesabix_economiccode'; + $RegistrationNumber = '_billing_hesabix_registerationnumber'; + $Website = '_billing_hesabix_website'; + $NationalCode_isActive = get_option('hesabix_contact_NationalCode_checkbox_hesabix'); + $EconomicCode_isActive = get_option('hesabix_contact_EconomicCode_checkbox_hesabix'); + $RegistrationNumber_isActive = get_option('hesabix_contact_RegistrationNumber_checkbox_hesabix'); + $Website_isActive = get_option('hesabix_contact_Website_checkbox_hesabix'); + $add_additional_fileds = get_option('hesabix_contact_add_additional_checkout_fields_hesabix'); + $fields = array(); + + if($add_additional_fileds == '1') { + $fields['NationalCode'] = get_post_meta( $id_order, $NationalCode, true) ?? null; + $fields['EconomicCode'] = get_post_meta( $id_order, $EconomicCode, true) ?? null; + $fields['RegistrationNumber'] = get_post_meta( $id_order, $RegistrationNumber, true) ?? null; + $fields['Website'] = get_post_meta( $id_order, $Website, true) ?? null; + } elseif($add_additional_fileds == '2') { + $NationalCode = get_option('hesabix_contact_NationalCode_text_hesabix'); + $EconomicCode = get_option('hesabix_contact_EconomicCode_text_hesabix'); + $RegistrationNumber = get_option('hesabix_contact_RegistrationNumber_text_hesabix'); + $Website = get_option('hesabix_contact_Website_text_hesabix'); + + if($NationalCode_isActive == 'yes' && $NationalCode) + $fields['NationalCode'] = get_post_meta( $id_order, $NationalCode, true) ?? null; + + if($EconomicCode_isActive == 'yes' && $EconomicCode) + $fields['EconomicCode'] = get_post_meta( $id_order, $EconomicCode, true) ?? null; + + if($RegistrationNumber_isActive == 'yes' && $RegistrationNumber) + $fields['RegistrationNumber'] = get_post_meta( $id_order, $RegistrationNumber, true) ?? null; + + if($Website_isActive == 'yes' && $Website) + $fields['Website'] = get_post_meta( $id_order, $Website, true) ?? null; + } + return $fields; + } +} diff --git a/admin/services/hesabixItemService.php b/admin/services/hesabixItemService.php new file mode 100644 index 0000000..6ca79aa --- /dev/null +++ b/admin/services/hesabixItemService.php @@ -0,0 +1,140 @@ +get_category_ids(); + $code = $new ? null : $wpFaService->getProductCodeByWpId($id); + $price = $product->get_regular_price() ? $product->get_regular_price() : $product->get_price(); + + $hesabixItem = array( + 'code' => $code, + 'name' => Hesabix_Validation::itemNameValidation($product->get_title()), + 'khadamat' => $product->is_virtual() == 1 ? 1 : 0, + 'Tag' => json_encode(array('id_product' => $id, 'id_attribute' => 0)) + ); + + if (get_option("hesabix_do_not_update_titles_in_hesabix", "no") === "no") { + $hesabixItem['PurchasesTitle'] = Hesabix_Validation::itemNameValidation($product->get_title()); + $hesabixItem['SalesTitle'] = Hesabix_Validation::itemNameValidation($product->get_title()); + } + + if (!$code || get_option("hesabix_do_not_update_product_price_in_hesabix", "no") === "no") + $hesabixItem["priceSell"] = self::getPriceInHesabixDefaultCurrency($price); + if (get_option("hesabix_do_not_update_product_barcode_in_hesabix", "no") === "no") + $hesabixItem["barcodes"] = Hesabix_Validation::itemBarcodeValidation($product->get_sku()); + if (get_option("hesabix_do_not_update_product_category_in_hesabix", "no") === "no") + if ($categories) + $hesabixItem["NodeFamily"] = self::getCategoryPath($categories[0]); + if (get_option("hesabix_do_not_update_product_product_code_in_hesabix", "no") === "no") + $hesabixItem["ProductCode"] = $id; + + return $hesabixItem; + } + + public static function mapProductVariation($product, $variation, $id_product, $new = true) + { + $wpFaService = new HesabixWpFaService(); + + $id_attribute = $variation->get_id(); + $categories = $product->get_category_ids(); + $code = $new ? null : $wpFaService->getProductCodeByWpId($id_product, $id_attribute); + + $productName = $product->get_title(); + $variationName = $variation->get_attribute_summary(); + + if (get_option("hesabix_remove_attributes_titles") == "yes" || get_option("hesabix_remove_attributes_titles") == "1") { + $values = self::getAttributesValues($variationName); + $fullName = Hesabix_Validation::itemNameValidation($productName . ' - ' . implode(", ", $values)); + } else { + $fullName = Hesabix_Validation::itemNameValidation($productName . ' - ' . $variationName); + } + + $price = $variation->get_regular_price() ? $variation->get_regular_price() : $variation->get_price(); + + $hesabixItem = array( + 'code' => $code, + 'name' => $fullName, + 'khadamat' => $variation->is_virtual() == 1 ? 1 : 0, + 'Tag' => json_encode(array( + 'id_product' => $id_product, + 'id_attribute' => $id_attribute + )), + ); + + if (get_option("hesabix_do_not_update_titles_in_hesabix", "no") === "no") { + $hesabixItem['PurchasesTitle'] = $fullName; + $hesabixItem['SalesTitle'] = $fullName; + } + + if (!$code || get_option("hesabix_do_not_update_product_price_in_hesabix", "no") === "no") + $hesabixItem["SellPrice"] = self::getPriceInHesabixDefaultCurrency($price); + if (get_option("hesabix_do_not_update_product_barcode_in_hesabix", "no") === "no") + $hesabixItem["Barcode"] = Hesabix_Validation::itemBarcodeValidation($variation->get_sku()); + if (get_option("hesabix_do_not_update_product_category_in_hesabix", "no") === "no") + $hesabixItem["NodeFamily"] = self::getCategoryPath($categories[0]); + if (get_option("hesabix_do_not_update_product_product_code_in_hesabix", "no") === "no") + $hesabixItem["ProductCode"] = $id_attribute; + + return $hesabixItem; + } + + public static function getAttributesValues($variationName) + { + $pairs = explode(",", $variationName); + + $values = array(); + foreach ($pairs as $pair) { + list($title, $value) = explode(":", $pair); + $values[] = trim($value); + } + return $values; + } + + public static function getPriceInHesabixDefaultCurrency($price) + { + if (!isset($price)) + return false; + + $woocommerce_currency = get_woocommerce_currency(); + $hesabix_currency = get_option('hesabix_hesabix_default_currency'); + + if (!is_numeric($price)) + $price = intval($price); + + if ($hesabix_currency == 'IRR' && $woocommerce_currency == 'IRT') + $price *= 10; + + if ($hesabix_currency == 'IRT' && $woocommerce_currency == 'IRR') + $price /= 10; + + return $price; + } + + public static function getCategoryPath($id_category) + { + if (!isset($id_category)) + return ''; + + $path = get_term_parents_list($id_category, 'product_cat', array( + 'format' => 'name', + 'separator' => ':', + 'link' => false, + 'inclusive' => true, + )); + + return substr('products: ' . $path, 0, -1); + } + +} \ No newline at end of file diff --git a/admin/services/ssbhesabixCustomerService.php b/admin/services/ssbhesabixCustomerService.php deleted file mode 100644 index fb40ba8..0000000 --- a/admin/services/ssbhesabixCustomerService.php +++ /dev/null @@ -1,276 +0,0 @@ -get_first_name() ? $customer->get_first_name() : $customer->get_billing_first_name(); - $lastName = $customer->get_last_name() ? $customer->get_last_name() : $customer->get_billing_last_name(); - $name = $firstName . ' ' . $lastName; - $nodeFamily = get_option('ssbhesabix_contact_automatic_save_node_family') == 'yes'? 'اشخاص :' . get_option('ssbhesabix_contact_node_family') : null; - - //checkout fields - $checkout_fields = ssbhesabixCustomerService::getAdditionalCheckoutFileds($id_order); - $NationalCode = $checkout_fields['NationalCode']; - $EconomicCode = $checkout_fields['EconomicCode']; - $RegistrationNumber = $checkout_fields['RegistrationNumber']; - $Website = $checkout_fields['Website']; - - if($NationalCode === false) $NationalCode = ''; - if($EconomicCode === false) $EconomicCode = ''; - if($RegistrationNumber === false) $RegistrationNumber = ''; - if($Website === false) $Website = ''; - - if (empty($name) || $name === ' ') $name = __('Not Defined', 'ssbhesabix'); - - $hesabixCustomer = array(); - - switch ($type) { - case 'first': - // - case 'billing': - $country_name = self::$countries[$order->get_billing_country()]; - $state_name = self::$states[$order->get_billing_country()][$order->get_billing_state()]; - $fullAddress = $order->get_billing_address_1() . '-' . $order->get_billing_address_2(); - $postalCode = $order->get_billing_postcode(); - if(strlen($fullAddress) < 5) { - $fullAddress = $customer->get_billing_address_1() . '-' . $customer->get_billing_address_2(); - } - if(empty($country_name)) - $country_name = self::$countries[$customer->get_billing_country()]; - if(empty($state_name)) - $state_name = self::$states[$customer->get_billing_country()][$customer->get_billing_state()]; - if(empty($postalCode)) - $postalCode = $customer->get_billing_postcode(); - - $city = $order->get_billing_city(); - if(preg_match('/^[0-9]+$/', $city)) { - $func = new Ssbhesabix_Admin_Functions(); - $city = $func->convertCityCodeToName($order->get_billing_city()); - } - - $hesabixCustomer = array( - 'code' => $code, - 'nikename' => $name, - 'name' => Ssbhesabix_Validation::contactFirstNameValidation($firstName) . Ssbhesabix_Validation::contactLastNameValidation($lastName), - 'ContactType' => 1, - 'NodeFamily' => $nodeFamily, - 'shenasemeli' => $NationalCode, - 'codeeghtesadi' => $EconomicCode, - 'RegistrationNumber' => $RegistrationNumber, - 'website' => $Website, - 'address' => Ssbhesabix_Validation::contactAddressValidation($fullAddress), - 'shahr' => Ssbhesabix_Validation::contactCityValidation($city), - 'ostan' => Ssbhesabix_Validation::contactStateValidation($state_name), - 'keshvar' => Ssbhesabix_Validation::contactCountryValidation($country_name), - 'postalcode' => Ssbhesabix_Validation::contactPostalCodeValidation($postalCode), - 'tel' => Ssbhesabix_Validation::contactPhoneValidation($customer->get_billing_phone()), - 'emal' => Ssbhesabix_Validation::contactEmailValidation($customer->get_email()), - 'Tag' => json_encode(array('id_customer' => $id_customer)), - 'des' => __('Customer ID in OnlineStore: ', 'ssbhesabix') . $id_customer, - 'types' => [ - [ - 'checked'=>true, - 'code'=>'customer' - ] - ] - ); - break; - case 'shipping': - $country_name = self::$countries[$order->get_shipping_country()]; - $state_name = self::$states[$order->get_shipping_country()][$order->get_shipping_state()]; - $fullAddress = $order->get_shipping_address_1() . ' - ' . $order->get_shipping_address_2(); - $postalCode = $order->get_shipping_postcode(); - - if(strlen($fullAddress) < 5) - $fullAddress = $customer->get_billing_address_1() . '-' . $customer->get_billing_address_2(); - if(empty($country_name)) - $country_name = self::$countries[$customer->get_billing_country()]; - if(empty($state_name)) - $state_name = self::$states[$customer->get_billing_country()][$customer->get_billing_state()]; - if(empty($postalCode)) - $postalCode = $customer->get_shipping_postcode(); - - $city = $order->get_shipping_city(); - if(preg_match('/^[0-9]+$/', $city)) { - $func = new Ssbhesabix_Admin_Functions(); - $city = $func->convertCityCodeToName($order->get_shipping_city()); - } - - $hesabixCustomer = array( - 'code' => $code, - 'nikename' => $name, - 'name' => Ssbhesabix_Validation::contactFirstNameValidation($firstName) . Ssbhesabix_Validation::contactLastNameValidation($lastName), - 'ContactType' => 1, - 'NodeFamily' => $nodeFamily, - 'shenasemeli' => $NationalCode, - 'codeeghtesadi' => $EconomicCode, - 'RegistrationNumber' => $RegistrationNumber, - 'website' => $Website, - 'address' => Ssbhesabix_Validation::contactAddressValidation($fullAddress), - 'shahr' => Ssbhesabix_Validation::contactCityValidation($city), - 'ostan' => Ssbhesabix_Validation::contactStateValidation($state_name), - 'keshvar' => Ssbhesabix_Validation::contactCountryValidation($country_name), - 'postalcode' => Ssbhesabix_Validation::contactPostalCodeValidation($postalCode), - 'tel' => Ssbhesabix_Validation::contactPhoneValidation($customer->get_billing_phone()), - 'email' => Ssbhesabix_Validation::contactEmailValidation($customer->get_email()), - 'Tag' => json_encode(array('id_customer' => $id_customer)), - 'des' => __('Customer ID in OnlineStore: ', 'ssbhesabix') . $id_customer, - 'types' => [ - [ - 'checked'=>true, - 'code'=>'customer' - ] - ] - ); - break; - } - - return self::correctCustomerData($hesabixCustomer); - } -//=========================================================================================================== - public static function mapGuestCustomer($code, $id_order): array - { - $order = new WC_Order($id_order); - - $name = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(); - if (empty($order->get_billing_first_name()) && empty($order->get_billing_last_name())) { - $name = __('Guest Customer', 'ssbhesabix'); - } - $nodeFamily = get_option('ssbhesabix_contact_automatic_save_node_family') == 'yes'? 'اشخاص :' . get_option('ssbhesabix_contact_node_family') :null; - - //checkout fields - $checkout_fields = ssbhesabixCustomerService::getAdditionalCheckoutFileds($id_order); - $NationalCode = $checkout_fields['NationalCode']; - $EconomicCode = $checkout_fields['EconomicCode']; - $RegistrationNumber = $checkout_fields['RegistrationNumber']; - $Website = $checkout_fields['Website']; - -// $country_name = self::$countries[$order->get_billing_country()]; -// $state_name = self::$states[$order->get_billing_state()]; - - - WC()->countries->countries[ $order->shipping_country ]; - $country_name = WC()->countries->countries[ $order->get_billing_country() ]; - $states = WC()->countries->get_states( $order->get_billing_country() ); - $state_name = $states[ $order->get_billing_state() ]; - if(!$state_name) $state_name = WC()->countries->states[$order->billing_country][$order->billing_state]; - if(!$state_name) $state_name = $order->get_billing_state(); - - $city = $order->get_billing_city(); - if(preg_match('/^[0-9]+$/', $city)) { - $func = new Ssbhesabix_Admin_Functions(); - $city = $func->convertCityCodeToName($order->get_billing_city()); - } - - $fullAddress = $order->get_billing_address_1() . '-' . $order->get_billing_address_2(); - - $hesabixCustomer = array( - 'Code' => $code, - 'Name' => $name, - 'FirstName' => Ssbhesabix_Validation::contactFirstNameValidation($order->get_billing_first_name()), - 'LastName' => Ssbhesabix_Validation::contactLastNameValidation($order->get_billing_last_name()), - 'ContactType' => 1, - 'NationalCode' => $NationalCode, - 'EconomicCode' => $EconomicCode, - 'RegistrationNumber' => $RegistrationNumber, - 'Website' => $Website, - 'NodeFamily' => $nodeFamily, - 'Address' => Ssbhesabix_Validation::contactAddressValidation($fullAddress), - 'City' => Ssbhesabix_Validation::contactCityValidation($city), - 'State' => Ssbhesabix_Validation::contactStateValidation($state_name), - 'Country' => Ssbhesabix_Validation::contactCountryValidation($country_name), - 'PostalCode' => Ssbhesabix_Validation::contactPostalCodeValidation($order->get_billing_postcode()), - 'Phone' => Ssbhesabix_Validation::contactPhoneValidation($order->get_billing_phone()), - 'Email' => Ssbhesabix_Validation::contactEmailValidation($order->get_billing_email()), - 'Tag' => json_encode(array('id_customer' => 0)), - 'Note' => __('Customer registered as a GuestCustomer.', 'ssbhesabix'), - ); - - return self::correctCustomerData($hesabixCustomer); - } -//=========================================================================================================== - private static function getMobileFromPhone($phone) { - if(preg_match("/^09\d{9}$/", $phone)) - return $phone; - else if(preg_match("/^9\d{9}$/", $phone)) - return '0' . $phone; - else if(preg_match("/^989\d{9}$/", $phone)) - return str_replace('98', '0' ,$phone); - else return ''; - } -//=========================================================================================================== - private static function correctCustomerData($hesabixCustomer) { - if($hesabixCustomer["Phone"] == '') - unset($hesabixCustomer["Phone"]); - else { - $mobile = self::getMobileFromPhone($hesabixCustomer["Phone"]); - - if($mobile) $hesabixCustomer["Mobile"] = $mobile; - } - - if($hesabixCustomer["Email"] == '') unset($hesabixCustomer["Email"]); - if($hesabixCustomer["Address"] == '') unset($hesabixCustomer["Address"]); - if($hesabixCustomer["PostalCode"] == '') unset($hesabixCustomer["PostalCode"]); - if($hesabixCustomer["City"] == '') unset($hesabixCustomer["City"]); - if($hesabixCustomer["State"] == '') unset($hesabixCustomer["State"]); - if($hesabixCustomer["Country"] == '') unset($hesabixCustomer["Country"]); - - return $hesabixCustomer; - } -//=========================================================================================================== - private static function getCountriesAndStates() - { - if (!isset(self::$countries)) { - $countries_obj = new WC_Countries(); - self::$countries = $countries_obj->get_countries(); - self::$states = $countries_obj->get_states(); - } - } -//=========================================================================================================== - private static function getAdditionalCheckoutFileds($id_order) { - $NationalCode = '_billing_hesabix_nationalcode'; - $EconomicCode = '_billing_hesabix_economiccode'; - $RegistrationNumber = '_billing_hesabix_registerationnumber'; - $Website = '_billing_hesabix_website'; - $NationalCode_isActive = get_option('ssbhesabix_contact_NationalCode_checkbox_hesabix'); - $EconomicCode_isActive = get_option('ssbhesabix_contact_EconomicCode_checkbox_hesabix'); - $RegistrationNumber_isActive = get_option('ssbhesabix_contact_RegistrationNumber_checkbox_hesabix'); - $Website_isActive = get_option('ssbhesabix_contact_Website_checkbox_hesabix'); - $add_additional_fileds = get_option('ssbhesabix_contact_add_additional_checkout_fields_hesabix'); - $fields = array(); - - // add additional fields to checkout - if($add_additional_fileds == '1') { - $fields['NationalCode'] = get_post_meta( $id_order, $NationalCode, true) ?? null; - $fields['EconomicCode'] = get_post_meta( $id_order, $EconomicCode, true) ?? null; - $fields['RegistrationNumber'] = get_post_meta( $id_order, $RegistrationNumber, true) ?? null; - $fields['Website'] = get_post_meta( $id_order, $Website, true) ?? null; - } elseif($add_additional_fileds == '2') { - $NationalCode = get_option('ssbhesabix_contact_NationalCode_text_hesabix'); - $EconomicCode = get_option('ssbhesabix_contact_EconomicCode_text_hesabix'); - $RegistrationNumber = get_option('ssbhesabix_contact_RegistrationNumber_text_hesabix'); - $Website = get_option('ssbhesabix_contact_Website_text_hesabix'); - - if($NationalCode_isActive == 'yes' && $NationalCode) - $fields['NationalCode'] = get_post_meta( $id_order, $NationalCode, true) ?? null; - - if($EconomicCode_isActive == 'yes' && $EconomicCode) - $fields['EconomicCode'] = get_post_meta( $id_order, $EconomicCode, true) ?? null; - - if($RegistrationNumber_isActive == 'yes' && $RegistrationNumber) - $fields['RegistrationNumber'] = get_post_meta( $id_order, $RegistrationNumber, true) ?? null; - - if($Website_isActive == 'yes' && $Website) - $fields['Website'] = get_post_meta( $id_order, $Website, true) ?? null; - } - return $fields; - } -} diff --git a/admin/services/ssbhesabixItemService.php b/admin/services/ssbhesabixItemService.php deleted file mode 100644 index 1728036..0000000 --- a/admin/services/ssbhesabixItemService.php +++ /dev/null @@ -1,119 +0,0 @@ -get_category_ids(); - $code = $new ? null : $wpFaService->getProductCodeByWpId($id) ; - $price = $product->get_regular_price() ? $product->get_regular_price() : $product->get_price(); - - $hesabixItem = array( - 'code' => $code, - 'name' => Ssbhesabix_Validation::itemNameValidation($product->get_title()), - 'khadamat' => $product->is_virtual() == 1 ? 1 : 0, - 'Tag' => json_encode(array('id_product' => $id, 'id_attribute' => 0)) - ); - - if(get_option("ssbhesabix_do_not_update_titles_in_hesabix", "no") === "no") { - $hesabixItem['PurchasesTitle'] = Ssbhesabix_Validation::itemNameValidation($product->get_title()); - $hesabixItem['SalesTitle'] = Ssbhesabix_Validation::itemNameValidation($product->get_title()); - } - - if(!$code || get_option("ssbhesabix_do_not_update_product_price_in_hesabix", "no") === "no") - $hesabixItem["priceSell"] = self::getPriceInHesabixDefaultCurrency($price); - if(get_option("ssbhesabix_do_not_update_product_barcode_in_hesabix", "no") === "no") - $hesabixItem["barcodes"] = Ssbhesabix_Validation::itemBarcodeValidation($product->get_sku()); - if(get_option("ssbhesabix_do_not_update_product_category_in_hesabix", "no") === "no") - if($categories) $hesabixItem["NodeFamily"] = self::getCategoryPath($categories[0]); - if(get_option("ssbhesabix_do_not_update_product_product_code_in_hesabix", "no") === "no") - $hesabixItem["ProductCode"] = $id; - - return $hesabixItem; - } -//=========================================================================================================== - public static function mapProductVariation($product, $variation, $id_product, $new = true) { - $wpFaService = new HesabixWpFaService(); - - $id_attribute = $variation->get_id(); - $categories = $product->get_category_ids(); - $code = $new ? null : $wpFaService->getProductCodeByWpId($id_product, $id_attribute); - - $productName = $product->get_title(); - $variationName = $variation->get_attribute_summary(); - - if(get_option("ssbhesabix_remove_attributes_titles") == "yes" || get_option("ssbhesabix_remove_attributes_titles") == "1") { - $values = self::getAttributesValues($variationName); - $fullName = Ssbhesabix_Validation::itemNameValidation($productName . ' - ' . implode(", ", $values)); - } else { - $fullName = Ssbhesabix_Validation::itemNameValidation($productName . ' - ' . $variationName); - } - - $price = $variation->get_regular_price() ? $variation->get_regular_price() : $variation->get_price(); - - $hesabixItem = array( - 'code' => $code, - 'name' => $fullName, - 'khadamat' => $variation->is_virtual() == 1 ? 1 : 0, - 'Tag' => json_encode(array( - 'id_product' => $id_product, - 'id_attribute' => $id_attribute - )), - ); - - if(get_option("ssbhesabix_do_not_update_titles_in_hesabix", "no") === "no") { - $hesabixItem['PurchasesTitle'] = $fullName; - $hesabixItem['SalesTitle'] = $fullName; - } - - if(!$code || get_option("ssbhesabix_do_not_update_product_price_in_hesabix", "no") === "no") $hesabixItem["SellPrice"] = self::getPriceInHesabixDefaultCurrency($price); - if(get_option("ssbhesabix_do_not_update_product_barcode_in_hesabix", "no") === "no") $hesabixItem["Barcode"] = Ssbhesabix_Validation::itemBarcodeValidation($variation->get_sku()); - if(get_option("ssbhesabix_do_not_update_product_category_in_hesabix", "no") === "no") $hesabixItem["NodeFamily"] = self::getCategoryPath($categories[0]); - if(get_option("ssbhesabix_do_not_update_product_product_code_in_hesabix", "no") === "no") $hesabixItem["ProductCode"] = $id_attribute; - - return $hesabixItem; - } -//=========================================================================================================== - public static function getAttributesValues($variationName) { - $pairs = explode(",", $variationName); - - $values = array(); - foreach ($pairs as $pair) { - list($title, $value) = explode(":", $pair); - $values[] = trim($value); - } - return $values; - } -//=========================================================================================================== - public static function getPriceInHesabixDefaultCurrency($price) - { - if (!isset($price)) return false; - - $woocommerce_currency = get_woocommerce_currency(); - $hesabix_currency = get_option('ssbhesabix_hesabix_default_currency'); - - if (!is_numeric($price)) $price = intval($price); - - if ($hesabix_currency == 'IRR' && $woocommerce_currency == 'IRT') $price *= 10; - - if ($hesabix_currency == 'IRT' && $woocommerce_currency == 'IRR') $price /= 10; - - return $price; - } -//=========================================================================================================== - public static function getCategoryPath($id_category) - { - if (!isset($id_category)) return ''; - - $path = get_term_parents_list($id_category, 'product_cat', array( - 'format' => 'name', - 'separator' => ':', - 'link' => false, - 'inclusive' => true, - )); - - return substr('products: ' . $path, 0, -1); - } -//=========================================================================================================== -} \ No newline at end of file diff --git a/admin/css/bootstrap.css b/assets/css/bootstrap.css similarity index 93% rename from admin/css/bootstrap.css rename to assets/css/bootstrap.css index 8e6adc8..cd3dad1 100644 --- a/admin/css/bootstrap.css +++ b/assets/css/bootstrap.css @@ -1,10790 +1,10770 @@ -@charset "UTF-8"; -/*! - * Bootstrap v5.0.1 (https://getbootstrap.com/) - * Copyright 2011-2021 The Bootstrap Authors - * Copyright 2011-2021 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */ -:root { - --bs-blue: #0d6efd; - --bs-indigo: #6610f2; - --bs-purple: #6f42c1; - --bs-pink: #d63384; - --bs-red: #dc3545; - --bs-orange: #fd7e14; - --bs-yellow: #ffc107; - --bs-green: #198754; - --bs-teal: #20c997; - --bs-cyan: #0dcaf0; - --bs-white: #fff; - --bs-gray: #6c757d; - --bs-gray-dark: #343a40; - --bs-primary: #0d6efd; - --bs-secondary: #6c757d; - --bs-success: #198754; - --bs-info: #0dcaf0; - --bs-warning: #ffc107; - --bs-danger: #dc3545; - --bs-light: #f8f9fa; - --bs-dark: #212529; - --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; - --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); -} - -@media (prefers-reduced-motion: no-preference) { - :root { - scroll-behavior: smooth; - } -} - -.h6, .h5, .h4, .h3, .h2, .h1 { - margin-top: 0; - margin-bottom: 0.5rem; - font-weight: 500; - line-height: 1.2; -} - -.h1 { - font-size: calc(1.375rem + 1.5vw); -} -@media (min-width: 1200px) { - .h1 { - font-size: 2.5rem; - } -} - -.h2 { - font-size: calc(1.325rem + 0.9vw); -} -@media (min-width: 1200px) { - .h2 { - font-size: 2rem; - } -} - -.h3 { - font-size: calc(1.3rem + 0.6vw); -} -@media (min-width: 1200px) { - .h3 { - font-size: 1.75rem; - } -} - -.h4 { - font-size: calc(1.275rem + 0.3vw); -} -@media (min-width: 1200px) { - .h4 { - font-size: 1.5rem; - } -} - -.h5 { - font-size: 1.25rem; -} - -.h6 { - font-size: 1rem; -} - -.p { - margin-top: 0; - margin-bottom: 1rem; -} - - -abbr[title], -abbr[data-bs-original-title] { - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; - cursor: help; - -webkit-text-decoration-skip-ink: none; - text-decoration-skip-ink: none; -} - -address { - margin-bottom: 1rem; - font-style: normal; - line-height: inherit; -} - -ol, -ul { - padding-left: 2rem; -} - -ol, -ul, -dl { - margin-top: 0; - margin-bottom: 1rem; -} - -ol ol, -ul ul, -ol ul, -ul ol { - margin-bottom: 0; -} - -dt { - font-weight: 700; -} - -dd { - margin-bottom: 0.5rem; - margin-left: 0; -} - -blockquote { - margin: 0 0 1rem; -} - -b, -strong { - font-weight: bolder; -} - -small, .small { - font-size: 0.875em; -} - -mark, .mark { - padding: 0.2em; - background-color: #fcf8e3; -} - -sub, -sup { - position: relative; - font-size: 0.75em; - line-height: 0; - vertical-align: baseline; -} - -sub { - bottom: -0.25em; -} - -sup { - top: -0.5em; -} - -a { - color: #0d6efd; - text-decoration: underline; -} -a:hover { - color: #0a58ca; -} - -a:not([href]):not([class]), a:not([href]):not([class]):hover { - color: inherit; - text-decoration: none; -} - -pre, -code, -kbd, -samp { - font-family: var(--bs-font-monospace); - font-size: 1em; - direction: ltr /* rtl:ignore */; - unicode-bidi: bidi-override; -} - -pre { - display: block; - margin-top: 0; - margin-bottom: 1rem; - overflow: auto; - font-size: 0.875em; -} -pre code { - font-size: inherit; - color: inherit; - word-break: normal; -} - -code { - font-size: 0.875em; - color: #d63384; - word-wrap: break-word; -} -a > code { - color: inherit; -} - -kbd { - padding: 0.2rem 0.4rem; - font-size: 0.875em; - color: #fff; - background-color: #212529; - border-radius: 0.2rem; -} -kbd kbd { - padding: 0; - font-size: 1em; - font-weight: 700; -} - -figure { - margin: 0 0 1rem; -} - -img, -svg { - vertical-align: middle; -} - -table { - caption-side: bottom; - border-collapse: collapse; -} - -caption { - padding-top: 0.5rem; - padding-bottom: 0.5rem; - color: #6c757d; - text-align: left; -} - -th { - text-align: inherit; - text-align: -webkit-match-parent; -} - -thead, -tbody, -tfoot, -tr, -td, -th { - border-color: inherit; - border-style: solid; - border-width: 0; -} - -label { - display: inline-block; -} - -button { - border-radius: 0; -} - -button:focus:not(:focus-visible) { - outline: 0; -} - -input, -button, -select, -optgroup, -textarea { - margin: 0; - font-family: inherit; - font-size: inherit; - line-height: inherit; -} - -button, -select { - text-transform: none; -} - -[role=button] { - cursor: pointer; -} - -select { - word-wrap: normal; -} -select:disabled { - opacity: 1; -} - -[list]::-webkit-calendar-picker-indicator { - display: none; -} - -button, -[type=button], -[type=reset], -[type=submit] { - -webkit-appearance: button; -} -button:not(:disabled), -[type=button]:not(:disabled), -[type=reset]:not(:disabled), -[type=submit]:not(:disabled) { - cursor: pointer; -} - -::-moz-focus-inner { - padding: 0; - border-style: none; -} - -textarea { - resize: vertical; -} - -fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0; -} - -legend { - float: left; - width: 100%; - padding: 0; - margin-bottom: 0.5rem; - font-size: calc(1.275rem + 0.3vw); - line-height: inherit; -} -@media (min-width: 1200px) { - legend { - font-size: 1.5rem; - } -} -legend + * { - clear: left; -} - -::-webkit-datetime-edit-fields-wrapper, -::-webkit-datetime-edit-text, -::-webkit-datetime-edit-minute, -::-webkit-datetime-edit-hour-field, -::-webkit-datetime-edit-day-field, -::-webkit-datetime-edit-month-field, -::-webkit-datetime-edit-year-field { - padding: 0; -} - -::-webkit-inner-spin-button { - height: auto; -} - -[type=search] { - outline-offset: -2px; - -webkit-appearance: textfield; -} - -/* rtl:raw: -[type="tel"], -[type="url"], -[type="email"], -[type="number"] { - direction: ltr; -} -*/ -::-webkit-search-decoration { - -webkit-appearance: none; -} - -::-webkit-color-swatch-wrapper { - padding: 0; -} - -::file-selector-button { - font: inherit; -} - -::-webkit-file-upload-button { - font: inherit; - -webkit-appearance: button; -} - -output { - display: inline-block; -} - -iframe { - border: 0; -} - -summary { - display: list-item; - cursor: pointer; -} - -progress { - vertical-align: baseline; -} - -[hidden] { - display: none !important; -} - -.lead { - font-size: 1.25rem; - font-weight: 300; -} - -.display-1 { - font-size: calc(1.625rem + 4.5vw); - font-weight: 300; - line-height: 1.2; -} -@media (min-width: 1200px) { - .display-1 { - font-size: 5rem; - } -} - -.display-2 { - font-size: calc(1.575rem + 3.9vw); - font-weight: 300; - line-height: 1.2; -} -@media (min-width: 1200px) { - .display-2 { - font-size: 4.5rem; - } -} - -.display-3 { - font-size: calc(1.525rem + 3.3vw); - font-weight: 300; - line-height: 1.2; -} -@media (min-width: 1200px) { - .display-3 { - font-size: 4rem; - } -} - -.display-4 { - font-size: calc(1.475rem + 2.7vw); - font-weight: 300; - line-height: 1.2; -} -@media (min-width: 1200px) { - .display-4 { - font-size: 3.5rem; - } -} - -.display-5 { - font-size: calc(1.425rem + 2.1vw); - font-weight: 300; - line-height: 1.2; -} -@media (min-width: 1200px) { - .display-5 { - font-size: 3rem; - } -} - -.display-6 { - font-size: calc(1.375rem + 1.5vw); - font-weight: 300; - line-height: 1.2; -} -@media (min-width: 1200px) { - .display-6 { - font-size: 2.5rem; - } -} - -.list-unstyled { - padding-left: 0; - list-style: none; -} - -.list-inline { - padding-left: 0; - list-style: none; -} - -.list-inline-item { - display: inline-block; -} -.list-inline-item:not(:last-child) { - margin-right: 0.5rem; -} - -.initialism { - font-size: 0.875em; - text-transform: uppercase; -} - -.blockquote { - margin-bottom: 1rem; - font-size: 1.25rem; -} -.blockquote > :last-child { - margin-bottom: 0; -} - -.blockquote-footer { - margin-top: -1rem; - margin-bottom: 1rem; - font-size: 0.875em; - color: #6c757d; -} -.blockquote-footer::before { - content: "— "; -} - -.img-fluid { - max-width: 100%; - height: auto; -} - -.img-thumbnail { - padding: 0.25rem; - background-color: #fff; - border: 1px solid #dee2e6; - border-radius: 0.25rem; - max-width: 100%; - height: auto; -} - -.figure { - display: inline-block; -} - -.figure-img { - margin-bottom: 0.5rem; - line-height: 1; -} - -.figure-caption { - font-size: 0.875em; - color: #6c757d; -} - -.container, -.container-fluid, -.container-xxl, -.container-xl, -.container-lg, -.container-md, -.container-sm { - width: 100%; - padding-right: var(--bs-gutter-x, 0.75rem); - padding-left: var(--bs-gutter-x, 0.75rem); - margin-right: auto; - margin-left: auto; -} - -@media (min-width: 576px) { - .container-sm, .container { - max-width: 540px; - } -} -@media (min-width: 768px) { - .container-md, .container-sm, .container { - max-width: 720px; - } -} -@media (min-width: 992px) { - .container-lg, .container-md, .container-sm, .container { - max-width: 960px; - } -} -@media (min-width: 1200px) { - .container-xl, .container-lg, .container-md, .container-sm, .container { - max-width: 1140px; - } -} -@media (min-width: 1400px) { - .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container { - max-width: 1320px; - } -} -.row { - --bs-gutter-x: 1.5rem; - --bs-gutter-y: 0; - display: flex; - flex-wrap: wrap; - margin-top: calc(var(--bs-gutter-y) * -1); - margin-right: calc(var(--bs-gutter-x) / -2); - margin-left: calc(var(--bs-gutter-x) / -2); -} -.row > * { - flex-shrink: 0; - width: 100%; - max-width: 100%; - padding-right: calc(var(--bs-gutter-x) / 2); - padding-left: calc(var(--bs-gutter-x) / 2); - margin-top: var(--bs-gutter-y); -} - -.col { - flex: 1 0 0%; -} - -.row-cols-auto > * { - flex: 0 0 auto; - width: auto; -} - -.row-cols-1 > * { - flex: 0 0 auto; - width: 100%; -} - -.row-cols-2 > * { - flex: 0 0 auto; - width: 50%; -} - -.row-cols-3 > * { - flex: 0 0 auto; - width: 33.3333333333%; -} - -.row-cols-4 > * { - flex: 0 0 auto; - width: 25%; -} - -.row-cols-5 > * { - flex: 0 0 auto; - width: 20%; -} - -.row-cols-6 > * { - flex: 0 0 auto; - width: 16.6666666667%; -} - -.col-auto { - flex: 0 0 auto; - width: auto; -} - -.col-1 { - flex: 0 0 auto; - width: 8.3333333333%; -} - -.col-2 { - flex: 0 0 auto; - width: 16.6666666667%; -} - -.col-3 { - flex: 0 0 auto; - width: 25%; -} - -.col-4 { - flex: 0 0 auto; - width: 33.3333333333%; -} - -.col-5 { - flex: 0 0 auto; - width: 41.6666666667%; -} - -.col-6 { - flex: 0 0 auto; - width: 50%; -} - -.col-7 { - flex: 0 0 auto; - width: 58.3333333333%; -} - -.col-8 { - flex: 0 0 auto; - width: 66.6666666667%; -} - -.col-9 { - flex: 0 0 auto; - width: 75%; -} - -.col-10 { - flex: 0 0 auto; - width: 83.3333333333%; -} - -.col-11 { - flex: 0 0 auto; - width: 91.6666666667%; -} - -.col-12 { - flex: 0 0 auto; - width: 100%; -} - -.offset-1 { - margin-left: 8.3333333333%; -} - -.offset-2 { - margin-left: 16.6666666667%; -} - -.offset-3 { - margin-left: 25%; -} - -.offset-4 { - margin-left: 33.3333333333%; -} - -.offset-5 { - margin-left: 41.6666666667%; -} - -.offset-6 { - margin-left: 50%; -} - -.offset-7 { - margin-left: 58.3333333333%; -} - -.offset-8 { - margin-left: 66.6666666667%; -} - -.offset-9 { - margin-left: 75%; -} - -.offset-10 { - margin-left: 83.3333333333%; -} - -.offset-11 { - margin-left: 91.6666666667%; -} - -.g-0, -.gx-0 { - --bs-gutter-x: 0; -} - -.g-0, -.gy-0 { - --bs-gutter-y: 0; -} - -.g-1, -.gx-1 { - --bs-gutter-x: 0.25rem; -} - -.g-1, -.gy-1 { - --bs-gutter-y: 0.25rem; -} - -.g-2, -.gx-2 { - --bs-gutter-x: 0.5rem; -} - -.g-2, -.gy-2 { - --bs-gutter-y: 0.5rem; -} - -.g-3, -.gx-3 { - --bs-gutter-x: 1rem; -} - -.g-3, -.gy-3 { - --bs-gutter-y: 1rem; -} - -.g-4, -.gx-4 { - --bs-gutter-x: 1.5rem; -} - -.g-4, -.gy-4 { - --bs-gutter-y: 1.5rem; -} - -.g-5, -.gx-5 { - --bs-gutter-x: 3rem; -} - -.g-5, -.gy-5 { - --bs-gutter-y: 3rem; -} - -@media (min-width: 576px) { - .col-sm { - flex: 1 0 0%; - } - - .row-cols-sm-auto > * { - flex: 0 0 auto; - width: auto; - } - - .row-cols-sm-1 > * { - flex: 0 0 auto; - width: 100%; - } - - .row-cols-sm-2 > * { - flex: 0 0 auto; - width: 50%; - } - - .row-cols-sm-3 > * { - flex: 0 0 auto; - width: 33.3333333333%; - } - - .row-cols-sm-4 > * { - flex: 0 0 auto; - width: 25%; - } - - .row-cols-sm-5 > * { - flex: 0 0 auto; - width: 20%; - } - - .row-cols-sm-6 > * { - flex: 0 0 auto; - width: 16.6666666667%; - } - - .col-sm-auto { - flex: 0 0 auto; - width: auto; - } - - .col-sm-1 { - flex: 0 0 auto; - width: 8.3333333333%; - } - - .col-sm-2 { - flex: 0 0 auto; - width: 16.6666666667%; - } - - .col-sm-3 { - flex: 0 0 auto; - width: 25%; - } - - .col-sm-4 { - flex: 0 0 auto; - width: 33.3333333333%; - } - - .col-sm-5 { - flex: 0 0 auto; - width: 41.6666666667%; - } - - .col-sm-6 { - flex: 0 0 auto; - width: 50%; - } - - .col-sm-7 { - flex: 0 0 auto; - width: 58.3333333333%; - } - - .col-sm-8 { - flex: 0 0 auto; - width: 66.6666666667%; - } - - .col-sm-9 { - flex: 0 0 auto; - width: 75%; - } - - .col-sm-10 { - flex: 0 0 auto; - width: 83.3333333333%; - } - - .col-sm-11 { - flex: 0 0 auto; - width: 91.6666666667%; - } - - .col-sm-12 { - flex: 0 0 auto; - width: 100%; - } - - .offset-sm-0 { - margin-left: 0; - } - - .offset-sm-1 { - margin-left: 8.3333333333%; - } - - .offset-sm-2 { - margin-left: 16.6666666667%; - } - - .offset-sm-3 { - margin-left: 25%; - } - - .offset-sm-4 { - margin-left: 33.3333333333%; - } - - .offset-sm-5 { - margin-left: 41.6666666667%; - } - - .offset-sm-6 { - margin-left: 50%; - } - - .offset-sm-7 { - margin-left: 58.3333333333%; - } - - .offset-sm-8 { - margin-left: 66.6666666667%; - } - - .offset-sm-9 { - margin-left: 75%; - } - - .offset-sm-10 { - margin-left: 83.3333333333%; - } - - .offset-sm-11 { - margin-left: 91.6666666667%; - } - - .g-sm-0, -.gx-sm-0 { - --bs-gutter-x: 0; - } - - .g-sm-0, -.gy-sm-0 { - --bs-gutter-y: 0; - } - - .g-sm-1, -.gx-sm-1 { - --bs-gutter-x: 0.25rem; - } - - .g-sm-1, -.gy-sm-1 { - --bs-gutter-y: 0.25rem; - } - - .g-sm-2, -.gx-sm-2 { - --bs-gutter-x: 0.5rem; - } - - .g-sm-2, -.gy-sm-2 { - --bs-gutter-y: 0.5rem; - } - - .g-sm-3, -.gx-sm-3 { - --bs-gutter-x: 1rem; - } - - .g-sm-3, -.gy-sm-3 { - --bs-gutter-y: 1rem; - } - - .g-sm-4, -.gx-sm-4 { - --bs-gutter-x: 1.5rem; - } - - .g-sm-4, -.gy-sm-4 { - --bs-gutter-y: 1.5rem; - } - - .g-sm-5, -.gx-sm-5 { - --bs-gutter-x: 3rem; - } - - .g-sm-5, -.gy-sm-5 { - --bs-gutter-y: 3rem; - } -} -@media (min-width: 768px) { - .col-md { - flex: 1 0 0%; - } - - .row-cols-md-auto > * { - flex: 0 0 auto; - width: auto; - } - - .row-cols-md-1 > * { - flex: 0 0 auto; - width: 100%; - } - - .row-cols-md-2 > * { - flex: 0 0 auto; - width: 50%; - } - - .row-cols-md-3 > * { - flex: 0 0 auto; - width: 33.3333333333%; - } - - .row-cols-md-4 > * { - flex: 0 0 auto; - width: 25%; - } - - .row-cols-md-5 > * { - flex: 0 0 auto; - width: 20%; - } - - .row-cols-md-6 > * { - flex: 0 0 auto; - width: 16.6666666667%; - } - - .col-md-auto { - flex: 0 0 auto; - width: auto; - } - - .col-md-1 { - flex: 0 0 auto; - width: 8.3333333333%; - } - - .col-md-2 { - flex: 0 0 auto; - width: 16.6666666667%; - } - - .col-md-3 { - flex: 0 0 auto; - width: 25%; - } - - .col-md-4 { - flex: 0 0 auto; - width: 33.3333333333%; - } - - .col-md-5 { - flex: 0 0 auto; - width: 41.6666666667%; - } - - .col-md-6 { - flex: 0 0 auto; - width: 50%; - } - - .col-md-7 { - flex: 0 0 auto; - width: 58.3333333333%; - } - - .col-md-8 { - flex: 0 0 auto; - width: 66.6666666667%; - } - - .col-md-9 { - flex: 0 0 auto; - width: 75%; - } - - .col-md-10 { - flex: 0 0 auto; - width: 83.3333333333%; - } - - .col-md-11 { - flex: 0 0 auto; - width: 91.6666666667%; - } - - .col-md-12 { - flex: 0 0 auto; - width: 100%; - } - - .offset-md-0 { - margin-left: 0; - } - - .offset-md-1 { - margin-left: 8.3333333333%; - } - - .offset-md-2 { - margin-left: 16.6666666667%; - } - - .offset-md-3 { - margin-left: 25%; - } - - .offset-md-4 { - margin-left: 33.3333333333%; - } - - .offset-md-5 { - margin-left: 41.6666666667%; - } - - .offset-md-6 { - margin-left: 50%; - } - - .offset-md-7 { - margin-left: 58.3333333333%; - } - - .offset-md-8 { - margin-left: 66.6666666667%; - } - - .offset-md-9 { - margin-left: 75%; - } - - .offset-md-10 { - margin-left: 83.3333333333%; - } - - .offset-md-11 { - margin-left: 91.6666666667%; - } - - .g-md-0, -.gx-md-0 { - --bs-gutter-x: 0; - } - - .g-md-0, -.gy-md-0 { - --bs-gutter-y: 0; - } - - .g-md-1, -.gx-md-1 { - --bs-gutter-x: 0.25rem; - } - - .g-md-1, -.gy-md-1 { - --bs-gutter-y: 0.25rem; - } - - .g-md-2, -.gx-md-2 { - --bs-gutter-x: 0.5rem; - } - - .g-md-2, -.gy-md-2 { - --bs-gutter-y: 0.5rem; - } - - .g-md-3, -.gx-md-3 { - --bs-gutter-x: 1rem; - } - - .g-md-3, -.gy-md-3 { - --bs-gutter-y: 1rem; - } - - .g-md-4, -.gx-md-4 { - --bs-gutter-x: 1.5rem; - } - - .g-md-4, -.gy-md-4 { - --bs-gutter-y: 1.5rem; - } - - .g-md-5, -.gx-md-5 { - --bs-gutter-x: 3rem; - } - - .g-md-5, -.gy-md-5 { - --bs-gutter-y: 3rem; - } -} -@media (min-width: 992px) { - .col-lg { - flex: 1 0 0%; - } - - .row-cols-lg-auto > * { - flex: 0 0 auto; - width: auto; - } - - .row-cols-lg-1 > * { - flex: 0 0 auto; - width: 100%; - } - - .row-cols-lg-2 > * { - flex: 0 0 auto; - width: 50%; - } - - .row-cols-lg-3 > * { - flex: 0 0 auto; - width: 33.3333333333%; - } - - .row-cols-lg-4 > * { - flex: 0 0 auto; - width: 25%; - } - - .row-cols-lg-5 > * { - flex: 0 0 auto; - width: 20%; - } - - .row-cols-lg-6 > * { - flex: 0 0 auto; - width: 16.6666666667%; - } - - .col-lg-auto { - flex: 0 0 auto; - width: auto; - } - - .col-lg-1 { - flex: 0 0 auto; - width: 8.3333333333%; - } - - .col-lg-2 { - flex: 0 0 auto; - width: 16.6666666667%; - } - - .col-lg-3 { - flex: 0 0 auto; - width: 25%; - } - - .col-lg-4 { - flex: 0 0 auto; - width: 33.3333333333%; - } - - .col-lg-5 { - flex: 0 0 auto; - width: 41.6666666667%; - } - - .col-lg-6 { - flex: 0 0 auto; - width: 50%; - } - - .col-lg-7 { - flex: 0 0 auto; - width: 58.3333333333%; - } - - .col-lg-8 { - flex: 0 0 auto; - width: 66.6666666667%; - } - - .col-lg-9 { - flex: 0 0 auto; - width: 75%; - } - - .col-lg-10 { - flex: 0 0 auto; - width: 83.3333333333%; - } - - .col-lg-11 { - flex: 0 0 auto; - width: 91.6666666667%; - } - - .col-lg-12 { - flex: 0 0 auto; - width: 100%; - } - - .offset-lg-0 { - margin-left: 0; - } - - .offset-lg-1 { - margin-left: 8.3333333333%; - } - - .offset-lg-2 { - margin-left: 16.6666666667%; - } - - .offset-lg-3 { - margin-left: 25%; - } - - .offset-lg-4 { - margin-left: 33.3333333333%; - } - - .offset-lg-5 { - margin-left: 41.6666666667%; - } - - .offset-lg-6 { - margin-left: 50%; - } - - .offset-lg-7 { - margin-left: 58.3333333333%; - } - - .offset-lg-8 { - margin-left: 66.6666666667%; - } - - .offset-lg-9 { - margin-left: 75%; - } - - .offset-lg-10 { - margin-left: 83.3333333333%; - } - - .offset-lg-11 { - margin-left: 91.6666666667%; - } - - .g-lg-0, -.gx-lg-0 { - --bs-gutter-x: 0; - } - - .g-lg-0, -.gy-lg-0 { - --bs-gutter-y: 0; - } - - .g-lg-1, -.gx-lg-1 { - --bs-gutter-x: 0.25rem; - } - - .g-lg-1, -.gy-lg-1 { - --bs-gutter-y: 0.25rem; - } - - .g-lg-2, -.gx-lg-2 { - --bs-gutter-x: 0.5rem; - } - - .g-lg-2, -.gy-lg-2 { - --bs-gutter-y: 0.5rem; - } - - .g-lg-3, -.gx-lg-3 { - --bs-gutter-x: 1rem; - } - - .g-lg-3, -.gy-lg-3 { - --bs-gutter-y: 1rem; - } - - .g-lg-4, -.gx-lg-4 { - --bs-gutter-x: 1.5rem; - } - - .g-lg-4, -.gy-lg-4 { - --bs-gutter-y: 1.5rem; - } - - .g-lg-5, -.gx-lg-5 { - --bs-gutter-x: 3rem; - } - - .g-lg-5, -.gy-lg-5 { - --bs-gutter-y: 3rem; - } -} -@media (min-width: 1200px) { - .col-xl { - flex: 1 0 0%; - } - - .row-cols-xl-auto > * { - flex: 0 0 auto; - width: auto; - } - - .row-cols-xl-1 > * { - flex: 0 0 auto; - width: 100%; - } - - .row-cols-xl-2 > * { - flex: 0 0 auto; - width: 50%; - } - - .row-cols-xl-3 > * { - flex: 0 0 auto; - width: 33.3333333333%; - } - - .row-cols-xl-4 > * { - flex: 0 0 auto; - width: 25%; - } - - .row-cols-xl-5 > * { - flex: 0 0 auto; - width: 20%; - } - - .row-cols-xl-6 > * { - flex: 0 0 auto; - width: 16.6666666667%; - } - - .col-xl-auto { - flex: 0 0 auto; - width: auto; - } - - .col-xl-1 { - flex: 0 0 auto; - width: 8.3333333333%; - } - - .col-xl-2 { - flex: 0 0 auto; - width: 16.6666666667%; - } - - .col-xl-3 { - flex: 0 0 auto; - width: 25%; - } - - .col-xl-4 { - flex: 0 0 auto; - width: 33.3333333333%; - } - - .col-xl-5 { - flex: 0 0 auto; - width: 41.6666666667%; - } - - .col-xl-6 { - flex: 0 0 auto; - width: 50%; - } - - .col-xl-7 { - flex: 0 0 auto; - width: 58.3333333333%; - } - - .col-xl-8 { - flex: 0 0 auto; - width: 66.6666666667%; - } - - .col-xl-9 { - flex: 0 0 auto; - width: 75%; - } - - .col-xl-10 { - flex: 0 0 auto; - width: 83.3333333333%; - } - - .col-xl-11 { - flex: 0 0 auto; - width: 91.6666666667%; - } - - .col-xl-12 { - flex: 0 0 auto; - width: 100%; - } - - .offset-xl-0 { - margin-left: 0; - } - - .offset-xl-1 { - margin-left: 8.3333333333%; - } - - .offset-xl-2 { - margin-left: 16.6666666667%; - } - - .offset-xl-3 { - margin-left: 25%; - } - - .offset-xl-4 { - margin-left: 33.3333333333%; - } - - .offset-xl-5 { - margin-left: 41.6666666667%; - } - - .offset-xl-6 { - margin-left: 50%; - } - - .offset-xl-7 { - margin-left: 58.3333333333%; - } - - .offset-xl-8 { - margin-left: 66.6666666667%; - } - - .offset-xl-9 { - margin-left: 75%; - } - - .offset-xl-10 { - margin-left: 83.3333333333%; - } - - .offset-xl-11 { - margin-left: 91.6666666667%; - } - - .g-xl-0, -.gx-xl-0 { - --bs-gutter-x: 0; - } - - .g-xl-0, -.gy-xl-0 { - --bs-gutter-y: 0; - } - - .g-xl-1, -.gx-xl-1 { - --bs-gutter-x: 0.25rem; - } - - .g-xl-1, -.gy-xl-1 { - --bs-gutter-y: 0.25rem; - } - - .g-xl-2, -.gx-xl-2 { - --bs-gutter-x: 0.5rem; - } - - .g-xl-2, -.gy-xl-2 { - --bs-gutter-y: 0.5rem; - } - - .g-xl-3, -.gx-xl-3 { - --bs-gutter-x: 1rem; - } - - .g-xl-3, -.gy-xl-3 { - --bs-gutter-y: 1rem; - } - - .g-xl-4, -.gx-xl-4 { - --bs-gutter-x: 1.5rem; - } - - .g-xl-4, -.gy-xl-4 { - --bs-gutter-y: 1.5rem; - } - - .g-xl-5, -.gx-xl-5 { - --bs-gutter-x: 3rem; - } - - .g-xl-5, -.gy-xl-5 { - --bs-gutter-y: 3rem; - } -} -@media (min-width: 1400px) { - .col-xxl { - flex: 1 0 0%; - } - - .row-cols-xxl-auto > * { - flex: 0 0 auto; - width: auto; - } - - .row-cols-xxl-1 > * { - flex: 0 0 auto; - width: 100%; - } - - .row-cols-xxl-2 > * { - flex: 0 0 auto; - width: 50%; - } - - .row-cols-xxl-3 > * { - flex: 0 0 auto; - width: 33.3333333333%; - } - - .row-cols-xxl-4 > * { - flex: 0 0 auto; - width: 25%; - } - - .row-cols-xxl-5 > * { - flex: 0 0 auto; - width: 20%; - } - - .row-cols-xxl-6 > * { - flex: 0 0 auto; - width: 16.6666666667%; - } - - .col-xxl-auto { - flex: 0 0 auto; - width: auto; - } - - .col-xxl-1 { - flex: 0 0 auto; - width: 8.3333333333%; - } - - .col-xxl-2 { - flex: 0 0 auto; - width: 16.6666666667%; - } - - .col-xxl-3 { - flex: 0 0 auto; - width: 25%; - } - - .col-xxl-4 { - flex: 0 0 auto; - width: 33.3333333333%; - } - - .col-xxl-5 { - flex: 0 0 auto; - width: 41.6666666667%; - } - - .col-xxl-6 { - flex: 0 0 auto; - width: 50%; - } - - .col-xxl-7 { - flex: 0 0 auto; - width: 58.3333333333%; - } - - .col-xxl-8 { - flex: 0 0 auto; - width: 66.6666666667%; - } - - .col-xxl-9 { - flex: 0 0 auto; - width: 75%; - } - - .col-xxl-10 { - flex: 0 0 auto; - width: 83.3333333333%; - } - - .col-xxl-11 { - flex: 0 0 auto; - width: 91.6666666667%; - } - - .col-xxl-12 { - flex: 0 0 auto; - width: 100%; - } - - .offset-xxl-0 { - margin-left: 0; - } - - .offset-xxl-1 { - margin-left: 8.3333333333%; - } - - .offset-xxl-2 { - margin-left: 16.6666666667%; - } - - .offset-xxl-3 { - margin-left: 25%; - } - - .offset-xxl-4 { - margin-left: 33.3333333333%; - } - - .offset-xxl-5 { - margin-left: 41.6666666667%; - } - - .offset-xxl-6 { - margin-left: 50%; - } - - .offset-xxl-7 { - margin-left: 58.3333333333%; - } - - .offset-xxl-8 { - margin-left: 66.6666666667%; - } - - .offset-xxl-9 { - margin-left: 75%; - } - - .offset-xxl-10 { - margin-left: 83.3333333333%; - } - - .offset-xxl-11 { - margin-left: 91.6666666667%; - } - - .g-xxl-0, -.gx-xxl-0 { - --bs-gutter-x: 0; - } - - .g-xxl-0, -.gy-xxl-0 { - --bs-gutter-y: 0; - } - - .g-xxl-1, -.gx-xxl-1 { - --bs-gutter-x: 0.25rem; - } - - .g-xxl-1, -.gy-xxl-1 { - --bs-gutter-y: 0.25rem; - } - - .g-xxl-2, -.gx-xxl-2 { - --bs-gutter-x: 0.5rem; - } - - .g-xxl-2, -.gy-xxl-2 { - --bs-gutter-y: 0.5rem; - } - - .g-xxl-3, -.gx-xxl-3 { - --bs-gutter-x: 1rem; - } - - .g-xxl-3, -.gy-xxl-3 { - --bs-gutter-y: 1rem; - } - - .g-xxl-4, -.gx-xxl-4 { - --bs-gutter-x: 1.5rem; - } - - .g-xxl-4, -.gy-xxl-4 { - --bs-gutter-y: 1.5rem; - } - - .g-xxl-5, -.gx-xxl-5 { - --bs-gutter-x: 3rem; - } - - .g-xxl-5, -.gy-xxl-5 { - --bs-gutter-y: 3rem; - } -} -.table { - --bs-table-bg: transparent; - --bs-table-accent-bg: transparent; - --bs-table-striped-color: #212529; - --bs-table-striped-bg: rgba(0, 0, 0, 0.05); - --bs-table-active-color: #212529; - --bs-table-active-bg: rgba(0, 0, 0, 0.1); - --bs-table-hover-color: #212529; - --bs-table-hover-bg: rgba(0, 0, 0, 0.075); - width: 100%; - margin-bottom: 1rem; - color: #212529; - vertical-align: top; - border-color: #dee2e6; -} -.table > :not(caption) > * > * { - padding: 0.5rem 0.5rem; - background-color: var(--bs-table-bg); - border-bottom-width: 1px; - box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg); -} -.table > tbody { - vertical-align: inherit; -} -.table > thead { - vertical-align: bottom; -} -.table > :not(:last-child) > :last-child > * { - border-bottom-color: currentColor; -} - -.caption-top { - caption-side: top; -} - -.table-sm > :not(caption) > * > * { - padding: 0.25rem 0.25rem; -} - -.table-bordered > :not(caption) > * { - border-width: 1px 0; -} -.table-bordered > :not(caption) > * > * { - border-width: 0 1px; -} - -.table-borderless > :not(caption) > * > * { - border-bottom-width: 0; -} - -.table-striped > tbody > tr:nth-of-type(odd) { - --bs-table-accent-bg: var(--bs-table-striped-bg); - color: var(--bs-table-striped-color); -} - -.table-active { - --bs-table-accent-bg: var(--bs-table-active-bg); - color: var(--bs-table-active-color); -} - -.table-hover > tbody > tr:hover { - --bs-table-accent-bg: var(--bs-table-hover-bg); - color: var(--bs-table-hover-color); -} - -.table-primary { - --bs-table-bg: #cfe2ff; - --bs-table-striped-bg: #c5d7f2; - --bs-table-striped-color: #000; - --bs-table-active-bg: #bacbe6; - --bs-table-active-color: #000; - --bs-table-hover-bg: #bfd1ec; - --bs-table-hover-color: #000; - color: #000; - border-color: #bacbe6; -} - -.table-secondary { - --bs-table-bg: #e2e3e5; - --bs-table-striped-bg: #d7d8da; - --bs-table-striped-color: #000; - --bs-table-active-bg: #cbccce; - --bs-table-active-color: #000; - --bs-table-hover-bg: #d1d2d4; - --bs-table-hover-color: #000; - color: #000; - border-color: #cbccce; -} - -.table-success { - --bs-table-bg: #d1e7dd; - --bs-table-striped-bg: #c7dbd2; - --bs-table-striped-color: #000; - --bs-table-active-bg: #bcd0c7; - --bs-table-active-color: #000; - --bs-table-hover-bg: #c1d6cc; - --bs-table-hover-color: #000; - color: #000; - border-color: #bcd0c7; -} - -.table-info { - --bs-table-bg: #cff4fc; - --bs-table-striped-bg: #c5e8ef; - --bs-table-striped-color: #000; - --bs-table-active-bg: #badce3; - --bs-table-active-color: #000; - --bs-table-hover-bg: #bfe2e9; - --bs-table-hover-color: #000; - color: #000; - border-color: #badce3; -} - -.table-warning { - --bs-table-bg: #fff3cd; - --bs-table-striped-bg: #f2e7c3; - --bs-table-striped-color: #000; - --bs-table-active-bg: #e6dbb9; - --bs-table-active-color: #000; - --bs-table-hover-bg: #ece1be; - --bs-table-hover-color: #000; - color: #000; - border-color: #e6dbb9; -} - -.table-danger { - --bs-table-bg: #f8d7da; - --bs-table-striped-bg: #eccccf; - --bs-table-striped-color: #000; - --bs-table-active-bg: #dfc2c4; - --bs-table-active-color: #000; - --bs-table-hover-bg: #e5c7ca; - --bs-table-hover-color: #000; - color: #000; - border-color: #dfc2c4; -} - -.table-light { - --bs-table-bg: #f8f9fa; - --bs-table-striped-bg: #ecedee; - --bs-table-striped-color: #000; - --bs-table-active-bg: #dfe0e1; - --bs-table-active-color: #000; - --bs-table-hover-bg: #e5e6e7; - --bs-table-hover-color: #000; - color: #000; - border-color: #dfe0e1; -} - -.table-dark { - --bs-table-bg: #212529; - --bs-table-striped-bg: #2c3034; - --bs-table-striped-color: #fff; - --bs-table-active-bg: #373b3e; - --bs-table-active-color: #fff; - --bs-table-hover-bg: #323539; - --bs-table-hover-color: #fff; - color: #fff; - border-color: #373b3e; -} - -.table-responsive { - overflow-x: auto; - -webkit-overflow-scrolling: touch; -} - -@media (max-width: 575.98px) { - .table-responsive-sm { - overflow-x: auto; - -webkit-overflow-scrolling: touch; - } -} -@media (max-width: 767.98px) { - .table-responsive-md { - overflow-x: auto; - -webkit-overflow-scrolling: touch; - } -} -@media (max-width: 991.98px) { - .table-responsive-lg { - overflow-x: auto; - -webkit-overflow-scrolling: touch; - } -} -@media (max-width: 1199.98px) { - .table-responsive-xl { - overflow-x: auto; - -webkit-overflow-scrolling: touch; - } -} -@media (max-width: 1399.98px) { - .table-responsive-xxl { - overflow-x: auto; - -webkit-overflow-scrolling: touch; - } -} -.form-label { - margin-bottom: 0.5rem; -} - -.col-form-label { - padding-top: calc(0.375rem + 1px); - padding-bottom: calc(0.375rem + 1px); - margin-bottom: 0; - font-size: inherit; - line-height: 1.5; -} - -.col-form-label-lg { - padding-top: calc(0.5rem + 1px); - padding-bottom: calc(0.5rem + 1px); - font-size: 1.25rem; -} - -.col-form-label-sm { - padding-top: calc(0.25rem + 1px); - padding-bottom: calc(0.25rem + 1px); - font-size: 0.875rem; -} - -.form-text { - margin-top: 0.25rem; - font-size: 0.875em; - color: #6c757d; -} - -.form-control { - display: block; - width: 100%; - padding: 0.375rem 0.75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #212529; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #ced4da; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - border-radius: 0.25rem; - transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -} -@media (prefers-reduced-motion: reduce) { - .form-control { - transition: none; - } -} -.form-control[type=file] { - overflow: hidden; -} -.form-control[type=file]:not(:disabled):not([readonly]) { - cursor: pointer; -} -.form-control:focus { - color: #212529; - background-color: #fff; - border-color: #86b7fe; - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); -} -.form-control::-webkit-date-and-time-value { - height: 1.5em; -} -.form-control::-moz-placeholder { - color: #6c757d; - opacity: 1; -} -.form-control::placeholder { - color: #6c757d; - opacity: 1; -} -.form-control:disabled, .form-control[readonly] { - background-color: #e9ecef; - opacity: 1; -} -.form-control::file-selector-button { - padding: 0.375rem 0.75rem; - margin: -0.375rem -0.75rem; - -webkit-margin-end: 0.75rem; - margin-inline-end: 0.75rem; - color: #212529; - background-color: #e9ecef; - pointer-events: none; - border-color: inherit; - border-style: solid; - border-width: 0; - border-inline-end-width: 1px; - border-radius: 0; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -} -@media (prefers-reduced-motion: reduce) { - .form-control::file-selector-button { - transition: none; - } -} -.form-control:hover:not(:disabled):not([readonly])::file-selector-button { - background-color: #dde0e3; -} -.form-control::-webkit-file-upload-button { - padding: 0.375rem 0.75rem; - margin: -0.375rem -0.75rem; - -webkit-margin-end: 0.75rem; - margin-inline-end: 0.75rem; - color: #212529; - background-color: #e9ecef; - pointer-events: none; - border-color: inherit; - border-style: solid; - border-width: 0; - border-inline-end-width: 1px; - border-radius: 0; - -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -} -@media (prefers-reduced-motion: reduce) { - .form-control::-webkit-file-upload-button { - -webkit-transition: none; - transition: none; - } -} -.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button { - background-color: #dde0e3; -} - -.form-control-plaintext { - display: block; - width: 100%; - padding: 0.375rem 0; - margin-bottom: 0; - line-height: 1.5; - color: #212529; - background-color: transparent; - border: solid transparent; - border-width: 1px 0; -} -.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { - padding-right: 0; - padding-left: 0; -} - -.form-control-sm { - min-height: calc(1.5em + 0.5rem + 2px); - padding: 0.25rem 0.5rem; - font-size: 0.875rem; - border-radius: 0.2rem; -} -.form-control-sm::file-selector-button { - padding: 0.25rem 0.5rem; - margin: -0.25rem -0.5rem; - -webkit-margin-end: 0.5rem; - margin-inline-end: 0.5rem; -} -.form-control-sm::-webkit-file-upload-button { - padding: 0.25rem 0.5rem; - margin: -0.25rem -0.5rem; - -webkit-margin-end: 0.5rem; - margin-inline-end: 0.5rem; -} - -.form-control-lg { - min-height: calc(1.5em + 1rem + 2px); - padding: 0.5rem 1rem; - font-size: 1.25rem; - border-radius: 0.3rem; -} -.form-control-lg::file-selector-button { - padding: 0.5rem 1rem; - margin: -0.5rem -1rem; - -webkit-margin-end: 1rem; - margin-inline-end: 1rem; -} -.form-control-lg::-webkit-file-upload-button { - padding: 0.5rem 1rem; - margin: -0.5rem -1rem; - -webkit-margin-end: 1rem; - margin-inline-end: 1rem; -} - -textarea.form-control { - min-height: calc(1.5em + 0.75rem + 2px); -} -textarea.form-control-sm { - min-height: calc(1.5em + 0.5rem + 2px); -} -textarea.form-control-lg { - min-height: calc(1.5em + 1rem + 2px); -} - -.form-control-color { - max-width: 3rem; - height: auto; - padding: 0.375rem; -} -.form-control-color:not(:disabled):not([readonly]) { - cursor: pointer; -} -.form-control-color::-moz-color-swatch { - height: 1.5em; - border-radius: 0.25rem; -} -.form-control-color::-webkit-color-swatch { - height: 1.5em; - border-radius: 0.25rem; -} - -.form-select { - display: block; - width: 100%; - padding: 0.375rem 2.25rem 0.375rem 0.75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #212529; - background-color: #fff; - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"); - background-repeat: no-repeat; - background-position: right 0.75rem center; - background-size: 16px 12px; - border: 1px solid #ced4da; - border-radius: 0.25rem; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -} -.form-select:focus { - border-color: #86b7fe; - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); -} -.form-select[multiple], .form-select[size]:not([size="1"]) { - padding-right: 0.75rem; - background-image: none; -} -.form-select:disabled { - background-color: #e9ecef; -} -.form-select:-moz-focusring { - color: transparent; - text-shadow: 0 0 0 #212529; -} - -.form-select-sm { - padding-top: 0.25rem; - padding-bottom: 0.25rem; - padding-left: 0.5rem; - font-size: 0.875rem; -} - -.form-select-lg { - padding-top: 0.5rem; - padding-bottom: 0.5rem; - padding-left: 1rem; - font-size: 1.25rem; -} - -.form-check { - display: block; - min-height: 1.5rem; - padding-left: 1.5em; - margin-bottom: 0.125rem; -} -.form-check .form-check-input { - float: left; - margin-left: -1.5em; -} - -.form-check-input { - width: 1em; - height: 1em; - margin-top: 0.25em; - vertical-align: top; - background-color: #fff; - background-repeat: no-repeat; - background-position: center; - background-size: contain; - border: 1px solid rgba(0, 0, 0, 0.25); - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - -webkit-print-color-adjust: exact; - color-adjust: exact; -} -.form-check-input[type=checkbox] { - border-radius: 0.25em; -} -.form-check-input[type=radio] { - border-radius: 50%; -} -.form-check-input:active { - filter: brightness(90%); -} -.form-check-input:focus { - border-color: #86b7fe; - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); -} -.form-check-input:checked { - background-color: #0d6efd; - border-color: #0d6efd; -} -.form-check-input:checked[type=checkbox] { - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e"); -} -.form-check-input:checked[type=radio] { - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e"); -} -.form-check-input[type=checkbox]:indeterminate { - background-color: #0d6efd; - border-color: #0d6efd; - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e"); -} -.form-check-input:disabled { - pointer-events: none; - filter: none; - opacity: 0.5; -} -.form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label { - opacity: 0.5; -} - -.form-switch { - padding-left: 2.5em; -} -.form-switch .form-check-input { - width: 2em; - margin-left: -2.5em; - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e"); - background-position: left center; - border-radius: 2em; - transition: background-position 0.15s ease-in-out; -} -@media (prefers-reduced-motion: reduce) { - .form-switch .form-check-input { - transition: none; - } -} -.form-switch .form-check-input:focus { - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e"); -} -.form-switch .form-check-input:checked { - background-position: right center; - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); -} - -.form-check-inline { - display: inline-block; - margin-right: 1rem; -} - -.btn-check { - position: absolute; - clip: rect(0, 0, 0, 0); - pointer-events: none; -} -.btn-check[disabled] + .btn, .btn-check:disabled + .btn { - pointer-events: none; - filter: none; - opacity: 0.65; -} - -.form-range { - width: 100%; - height: 1.5rem; - padding: 0; - background-color: transparent; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -} -.form-range:focus { - outline: 0; -} -.form-range:focus::-webkit-slider-thumb { - box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); -} -.form-range:focus::-moz-range-thumb { - box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); -} -.form-range::-moz-focus-outer { - border: 0; -} -.form-range::-webkit-slider-thumb { - width: 1rem; - height: 1rem; - margin-top: -0.25rem; - background-color: #0d6efd; - border: 0; - border-radius: 1rem; - -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; - transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; - -webkit-appearance: none; - appearance: none; -} -@media (prefers-reduced-motion: reduce) { - .form-range::-webkit-slider-thumb { - -webkit-transition: none; - transition: none; - } -} -.form-range::-webkit-slider-thumb:active { - background-color: #b6d4fe; -} -.form-range::-webkit-slider-runnable-track { - width: 100%; - height: 0.5rem; - color: transparent; - cursor: pointer; - background-color: #dee2e6; - border-color: transparent; - border-radius: 1rem; -} -.form-range::-moz-range-thumb { - width: 1rem; - height: 1rem; - background-color: #0d6efd; - border: 0; - border-radius: 1rem; - -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; - transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; - -moz-appearance: none; - appearance: none; -} -@media (prefers-reduced-motion: reduce) { - .form-range::-moz-range-thumb { - -moz-transition: none; - transition: none; - } -} -.form-range::-moz-range-thumb:active { - background-color: #b6d4fe; -} -.form-range::-moz-range-track { - width: 100%; - height: 0.5rem; - color: transparent; - cursor: pointer; - background-color: #dee2e6; - border-color: transparent; - border-radius: 1rem; -} -.form-range:disabled { - pointer-events: none; -} -.form-range:disabled::-webkit-slider-thumb { - background-color: #adb5bd; -} -.form-range:disabled::-moz-range-thumb { - background-color: #adb5bd; -} - -.form-floating { - position: relative; -} -.form-floating > .form-control, -.form-floating > .form-select { - height: calc(3.5rem + 2px); - padding: 1rem 0.75rem; -} -.form-floating > label { - position: absolute; - top: 0; - left: 0; - height: 100%; - padding: 1rem 0.75rem; - pointer-events: none; - border: 1px solid transparent; - transform-origin: 0 0; - transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; -} -@media (prefers-reduced-motion: reduce) { - .form-floating > label { - transition: none; - } -} -.form-floating > .form-control::-moz-placeholder { - color: transparent; -} -.form-floating > .form-control::placeholder { - color: transparent; -} -.form-floating > .form-control:not(:-moz-placeholder-shown) { - padding-top: 1.625rem; - padding-bottom: 0.625rem; -} -.form-floating > .form-control:focus, .form-floating > .form-control:not(:placeholder-shown) { - padding-top: 1.625rem; - padding-bottom: 0.625rem; -} -.form-floating > .form-control:-webkit-autofill { - padding-top: 1.625rem; - padding-bottom: 0.625rem; -} -.form-floating > .form-select { - padding-top: 1.625rem; - padding-bottom: 0.625rem; -} -.form-floating > .form-control:not(:-moz-placeholder-shown) ~ label { - opacity: 0.65; - transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); -} -.form-floating > .form-control:focus ~ label, -.form-floating > .form-control:not(:placeholder-shown) ~ label, -.form-floating > .form-select ~ label { - opacity: 0.65; - transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); -} -.form-floating > .form-control:-webkit-autofill ~ label { - opacity: 0.65; - transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); -} - -.input-group { - position: relative; - display: flex; - flex-wrap: wrap; - align-items: stretch; - width: 100%; -} -.input-group > .form-control, -.input-group > .form-select { - position: relative; - flex: 1 1 auto; - width: 1%; - min-width: 0; -} -.input-group > .form-control:focus, -.input-group > .form-select:focus { - z-index: 3; -} -.input-group .btn { - position: relative; - z-index: 2; -} -.input-group .btn:focus { - z-index: 3; -} - -.input-group-text { - display: flex; - align-items: center; - padding: 0.375rem 0.75rem; - font-size: 1rem; - font-weight: 400; - line-height: 1.5; - color: #212529; - text-align: center; - white-space: nowrap; - background-color: #e9ecef; - border: 1px solid #ced4da; - border-radius: 0.25rem; -} - -.input-group-lg > .form-control, -.input-group-lg > .form-select, -.input-group-lg > .input-group-text, -.input-group-lg > .btn { - padding: 0.5rem 1rem; - font-size: 1.25rem; - border-radius: 0.3rem; -} - -.input-group-sm > .form-control, -.input-group-sm > .form-select, -.input-group-sm > .input-group-text, -.input-group-sm > .btn { - padding: 0.25rem 0.5rem; - font-size: 0.875rem; - border-radius: 0.2rem; -} - -.input-group-lg > .form-select, -.input-group-sm > .form-select { - padding-right: 3rem; -} - -.input-group:not(.has-validation) > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu), -.input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n+3) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.input-group.has-validation > :nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu), -.input-group.has-validation > .dropdown-toggle:nth-last-child(n+4) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.input-group > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { - margin-left: -1px; - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -.valid-feedback { - display: none; - width: 100%; - margin-top: 0.25rem; - font-size: 0.875em; - color: #198754; -} - -.valid-tooltip { - position: absolute; - top: 100%; - z-index: 5; - display: none; - max-width: 100%; - padding: 0.25rem 0.5rem; - margin-top: 0.1rem; - font-size: 0.875rem; - color: #fff; - background-color: rgba(25, 135, 84, 0.9); - border-radius: 0.25rem; -} - -.was-validated :valid ~ .valid-feedback, -.was-validated :valid ~ .valid-tooltip, -.is-valid ~ .valid-feedback, -.is-valid ~ .valid-tooltip { - display: block; -} - -.was-validated .form-control:valid, .form-control.is-valid { - border-color: #198754; - padding-right: calc(1.5em + 0.75rem); - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); - background-repeat: no-repeat; - background-position: right calc(0.375em + 0.1875rem) center; - background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); -} -.was-validated .form-control:valid:focus, .form-control.is-valid:focus { - border-color: #198754; - box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); -} - -.was-validated textarea.form-control:valid, textarea.form-control.is-valid { - padding-right: calc(1.5em + 0.75rem); - background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); -} - -.was-validated .form-select:valid, .form-select.is-valid { - border-color: #198754; -} -.was-validated .form-select:valid:not([multiple]):not([size]), .was-validated .form-select:valid:not([multiple])[size="1"], .form-select.is-valid:not([multiple]):not([size]), .form-select.is-valid:not([multiple])[size="1"] { - padding-right: 4.125rem; - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); - background-position: right 0.75rem center, center right 2.25rem; - background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); -} -.was-validated .form-select:valid:focus, .form-select.is-valid:focus { - border-color: #198754; - box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); -} - -.was-validated .form-check-input:valid, .form-check-input.is-valid { - border-color: #198754; -} -.was-validated .form-check-input:valid:checked, .form-check-input.is-valid:checked { - background-color: #198754; -} -.was-validated .form-check-input:valid:focus, .form-check-input.is-valid:focus { - box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); -} -.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { - color: #198754; -} - -.form-check-inline .form-check-input ~ .valid-feedback { - margin-left: 0.5em; -} - -.was-validated .input-group .form-control:valid, .input-group .form-control.is-valid, -.was-validated .input-group .form-select:valid, -.input-group .form-select.is-valid { - z-index: 1; -} -.was-validated .input-group .form-control:valid:focus, .input-group .form-control.is-valid:focus, -.was-validated .input-group .form-select:valid:focus, -.input-group .form-select.is-valid:focus { - z-index: 3; -} - -.invalid-feedback { - display: none; - width: 100%; - margin-top: 0.25rem; - font-size: 0.875em; - color: #dc3545; -} - -.invalid-tooltip { - position: absolute; - top: 100%; - z-index: 5; - display: none; - max-width: 100%; - padding: 0.25rem 0.5rem; - margin-top: 0.1rem; - font-size: 0.875rem; - color: #fff; - background-color: rgba(220, 53, 69, 0.9); - border-radius: 0.25rem; -} - -.was-validated :invalid ~ .invalid-feedback, -.was-validated :invalid ~ .invalid-tooltip, -.is-invalid ~ .invalid-feedback, -.is-invalid ~ .invalid-tooltip { - display: block; -} - -.was-validated .form-control:invalid, .form-control.is-invalid { - border-color: #dc3545; - padding-right: calc(1.5em + 0.75rem); - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); - background-repeat: no-repeat; - background-position: right calc(0.375em + 0.1875rem) center; - background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); -} -.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { - border-color: #dc3545; - box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); -} - -.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { - padding-right: calc(1.5em + 0.75rem); - background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); -} - -.was-validated .form-select:invalid, .form-select.is-invalid { - border-color: #dc3545; -} -.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] { - padding-right: 4.125rem; - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); - background-position: right 0.75rem center, center right 2.25rem; - background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); -} -.was-validated .form-select:invalid:focus, .form-select.is-invalid:focus { - border-color: #dc3545; - box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); -} - -.was-validated .form-check-input:invalid, .form-check-input.is-invalid { - border-color: #dc3545; -} -.was-validated .form-check-input:invalid:checked, .form-check-input.is-invalid:checked { - background-color: #dc3545; -} -.was-validated .form-check-input:invalid:focus, .form-check-input.is-invalid:focus { - box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); -} -.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { - color: #dc3545; -} - -.form-check-inline .form-check-input ~ .invalid-feedback { - margin-left: 0.5em; -} - -.was-validated .input-group .form-control:invalid, .input-group .form-control.is-invalid, -.was-validated .input-group .form-select:invalid, -.input-group .form-select.is-invalid { - z-index: 2; -} -.was-validated .input-group .form-control:invalid:focus, .input-group .form-control.is-invalid:focus, -.was-validated .input-group .form-select:invalid:focus, -.input-group .form-select.is-invalid:focus { - z-index: 3; -} - -.btn { - display: inline-block; - font-weight: 400; - line-height: 1.5; - color: #212529; - text-align: center; - text-decoration: none; - vertical-align: middle; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - background-color: transparent; - border: 1px solid transparent; - padding: 0.375rem 0.75rem; - font-size: 1rem; - border-radius: 0.25rem; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -} -@media (prefers-reduced-motion: reduce) { - .btn { - transition: none; - } -} -.btn:hover { - color: #212529; -} -.btn-check:focus + .btn, .btn:focus { - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); -} -.btn:disabled, .btn.disabled, fieldset:disabled .btn { - pointer-events: none; - opacity: 0.65; -} - -.btn-primary { - color: #fff; - background-color: #0d6efd; - border-color: #0d6efd; -} -.btn-primary:hover { - color: #fff; - background-color: #0b5ed7; - border-color: #0a58ca; -} -.btn-check:focus + .btn-primary, .btn-primary:focus { - color: #fff; - background-color: #0b5ed7; - border-color: #0a58ca; - box-shadow: 0 0 0 0.25rem rgba(49, 132, 253, 0.5); -} -.btn-check:checked + .btn-primary, .btn-check:active + .btn-primary, .btn-primary:active, .btn-primary.active, .show > .btn-primary.dropdown-toggle { - color: #fff; - background-color: #0a58ca; - border-color: #0a53be; -} -.btn-check:checked + .btn-primary:focus, .btn-check:active + .btn-primary:focus, .btn-primary:active:focus, .btn-primary.active:focus, .show > .btn-primary.dropdown-toggle:focus { - box-shadow: 0 0 0 0.25rem rgba(49, 132, 253, 0.5); -} -.btn-primary:disabled, .btn-primary.disabled { - color: #fff; - background-color: #0d6efd; - border-color: #0d6efd; -} - -.btn-secondary { - color: #fff; - background-color: #6c757d; - border-color: #6c757d; -} -.btn-secondary:hover { - color: #fff; - background-color: #5c636a; - border-color: #565e64; -} -.btn-check:focus + .btn-secondary, .btn-secondary:focus { - color: #fff; - background-color: #5c636a; - border-color: #565e64; - box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5); -} -.btn-check:checked + .btn-secondary, .btn-check:active + .btn-secondary, .btn-secondary:active, .btn-secondary.active, .show > .btn-secondary.dropdown-toggle { - color: #fff; - background-color: #565e64; - border-color: #51585e; -} -.btn-check:checked + .btn-secondary:focus, .btn-check:active + .btn-secondary:focus, .btn-secondary:active:focus, .btn-secondary.active:focus, .show > .btn-secondary.dropdown-toggle:focus { - box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5); -} -.btn-secondary:disabled, .btn-secondary.disabled { - color: #fff; - background-color: #6c757d; - border-color: #6c757d; -} - -.btn-success { - color: #fff; - background-color: #198754; - border-color: #198754; -} -.btn-success:hover { - color: #fff; - background-color: #157347; - border-color: #146c43; -} -.btn-check:focus + .btn-success, .btn-success:focus { - color: #fff; - background-color: #157347; - border-color: #146c43; - box-shadow: 0 0 0 0.25rem rgba(60, 153, 110, 0.5); -} -.btn-check:checked + .btn-success, .btn-check:active + .btn-success, .btn-success:active, .btn-success.active, .show > .btn-success.dropdown-toggle { - color: #fff; - background-color: #146c43; - border-color: #13653f; -} -.btn-check:checked + .btn-success:focus, .btn-check:active + .btn-success:focus, .btn-success:active:focus, .btn-success.active:focus, .show > .btn-success.dropdown-toggle:focus { - box-shadow: 0 0 0 0.25rem rgba(60, 153, 110, 0.5); -} -.btn-success:disabled, .btn-success.disabled { - color: #fff; - background-color: #198754; - border-color: #198754; -} - -.btn-info { - color: #000; - background-color: #0dcaf0; - border-color: #0dcaf0; -} -.btn-info:hover { - color: #000; - background-color: #31d2f2; - border-color: #25cff2; -} -.btn-check:focus + .btn-info, .btn-info:focus { - color: #000; - background-color: #31d2f2; - border-color: #25cff2; - box-shadow: 0 0 0 0.25rem rgba(11, 172, 204, 0.5); -} -.btn-check:checked + .btn-info, .btn-check:active + .btn-info, .btn-info:active, .btn-info.active, .show > .btn-info.dropdown-toggle { - color: #000; - background-color: #3dd5f3; - border-color: #25cff2; -} -.btn-check:checked + .btn-info:focus, .btn-check:active + .btn-info:focus, .btn-info:active:focus, .btn-info.active:focus, .show > .btn-info.dropdown-toggle:focus { - box-shadow: 0 0 0 0.25rem rgba(11, 172, 204, 0.5); -} -.btn-info:disabled, .btn-info.disabled { - color: #000; - background-color: #0dcaf0; - border-color: #0dcaf0; -} - -.btn-warning { - color: #000; - background-color: #ffc107; - border-color: #ffc107; -} -.btn-warning:hover { - color: #000; - background-color: #ffca2c; - border-color: #ffc720; -} -.btn-check:focus + .btn-warning, .btn-warning:focus { - color: #000; - background-color: #ffca2c; - border-color: #ffc720; - box-shadow: 0 0 0 0.25rem rgba(217, 164, 6, 0.5); -} -.btn-check:checked + .btn-warning, .btn-check:active + .btn-warning, .btn-warning:active, .btn-warning.active, .show > .btn-warning.dropdown-toggle { - color: #000; - background-color: #ffcd39; - border-color: #ffc720; -} -.btn-check:checked + .btn-warning:focus, .btn-check:active + .btn-warning:focus, .btn-warning:active:focus, .btn-warning.active:focus, .show > .btn-warning.dropdown-toggle:focus { - box-shadow: 0 0 0 0.25rem rgba(217, 164, 6, 0.5); -} -.btn-warning:disabled, .btn-warning.disabled { - color: #000; - background-color: #ffc107; - border-color: #ffc107; -} - -.btn-danger { - color: #fff; - background-color: #dc3545; - border-color: #dc3545; -} -.btn-danger:hover { - color: #fff; - background-color: #bb2d3b; - border-color: #b02a37; -} -.btn-check:focus + .btn-danger, .btn-danger:focus { - color: #fff; - background-color: #bb2d3b; - border-color: #b02a37; - box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5); -} -.btn-check:checked + .btn-danger, .btn-check:active + .btn-danger, .btn-danger:active, .btn-danger.active, .show > .btn-danger.dropdown-toggle { - color: #fff; - background-color: #b02a37; - border-color: #a52834; -} -.btn-check:checked + .btn-danger:focus, .btn-check:active + .btn-danger:focus, .btn-danger:active:focus, .btn-danger.active:focus, .show > .btn-danger.dropdown-toggle:focus { - box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5); -} -.btn-danger:disabled, .btn-danger.disabled { - color: #fff; - background-color: #dc3545; - border-color: #dc3545; -} - -.btn-light { - color: #000; - background-color: #f8f9fa; - border-color: #f8f9fa; -} -.btn-light:hover { - color: #000; - background-color: #f9fafb; - border-color: #f9fafb; -} -.btn-check:focus + .btn-light, .btn-light:focus { - color: #000; - background-color: #f9fafb; - border-color: #f9fafb; - box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5); -} -.btn-check:checked + .btn-light, .btn-check:active + .btn-light, .btn-light:active, .btn-light.active, .show > .btn-light.dropdown-toggle { - color: #000; - background-color: #f9fafb; - border-color: #f9fafb; -} -.btn-check:checked + .btn-light:focus, .btn-check:active + .btn-light:focus, .btn-light:active:focus, .btn-light.active:focus, .show > .btn-light.dropdown-toggle:focus { - box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5); -} -.btn-light:disabled, .btn-light.disabled { - color: #000; - background-color: #f8f9fa; - border-color: #f8f9fa; -} - -.btn-dark { - color: #fff; - background-color: #212529; - border-color: #212529; -} -.btn-dark:hover { - color: #fff; - background-color: #1c1f23; - border-color: #1a1e21; -} -.btn-check:focus + .btn-dark, .btn-dark:focus { - color: #fff; - background-color: #1c1f23; - border-color: #1a1e21; - box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5); -} -.btn-check:checked + .btn-dark, .btn-check:active + .btn-dark, .btn-dark:active, .btn-dark.active, .show > .btn-dark.dropdown-toggle { - color: #fff; - background-color: #1a1e21; - border-color: #191c1f; -} -.btn-check:checked + .btn-dark:focus, .btn-check:active + .btn-dark:focus, .btn-dark:active:focus, .btn-dark.active:focus, .show > .btn-dark.dropdown-toggle:focus { - box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5); -} -.btn-dark:disabled, .btn-dark.disabled { - color: #fff; - background-color: #212529; - border-color: #212529; -} - -.btn-outline-primary { - color: #0d6efd; - border-color: #0d6efd; -} -.btn-outline-primary:hover { - color: #fff; - background-color: #0d6efd; - border-color: #0d6efd; -} -.btn-check:focus + .btn-outline-primary, .btn-outline-primary:focus { - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.5); -} -.btn-check:checked + .btn-outline-primary, .btn-check:active + .btn-outline-primary, .btn-outline-primary:active, .btn-outline-primary.active, .btn-outline-primary.dropdown-toggle.show { - color: #fff; - background-color: #0d6efd; - border-color: #0d6efd; -} -.btn-check:checked + .btn-outline-primary:focus, .btn-check:active + .btn-outline-primary:focus, .btn-outline-primary:active:focus, .btn-outline-primary.active:focus, .btn-outline-primary.dropdown-toggle.show:focus { - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.5); -} -.btn-outline-primary:disabled, .btn-outline-primary.disabled { - color: #0d6efd; - background-color: transparent; -} - -.btn-outline-secondary { - color: #6c757d; - border-color: #6c757d; -} -.btn-outline-secondary:hover { - color: #fff; - background-color: #6c757d; - border-color: #6c757d; -} -.btn-check:focus + .btn-outline-secondary, .btn-outline-secondary:focus { - box-shadow: 0 0 0 0.25rem rgba(108, 117, 125, 0.5); -} -.btn-check:checked + .btn-outline-secondary, .btn-check:active + .btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show { - color: #fff; - background-color: #6c757d; - border-color: #6c757d; -} -.btn-check:checked + .btn-outline-secondary:focus, .btn-check:active + .btn-outline-secondary:focus, .btn-outline-secondary:active:focus, .btn-outline-secondary.active:focus, .btn-outline-secondary.dropdown-toggle.show:focus { - box-shadow: 0 0 0 0.25rem rgba(108, 117, 125, 0.5); -} -.btn-outline-secondary:disabled, .btn-outline-secondary.disabled { - color: #6c757d; - background-color: transparent; -} - -.btn-outline-success { - color: #198754; - border-color: #198754; -} -.btn-outline-success:hover { - color: #fff; - background-color: #198754; - border-color: #198754; -} -.btn-check:focus + .btn-outline-success, .btn-outline-success:focus { - box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.5); -} -.btn-check:checked + .btn-outline-success, .btn-check:active + .btn-outline-success, .btn-outline-success:active, .btn-outline-success.active, .btn-outline-success.dropdown-toggle.show { - color: #fff; - background-color: #198754; - border-color: #198754; -} -.btn-check:checked + .btn-outline-success:focus, .btn-check:active + .btn-outline-success:focus, .btn-outline-success:active:focus, .btn-outline-success.active:focus, .btn-outline-success.dropdown-toggle.show:focus { - box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.5); -} -.btn-outline-success:disabled, .btn-outline-success.disabled { - color: #198754; - background-color: transparent; -} - -.btn-outline-info { - color: #0dcaf0; - border-color: #0dcaf0; -} -.btn-outline-info:hover { - color: #000; - background-color: #0dcaf0; - border-color: #0dcaf0; -} -.btn-check:focus + .btn-outline-info, .btn-outline-info:focus { - box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.5); -} -.btn-check:checked + .btn-outline-info, .btn-check:active + .btn-outline-info, .btn-outline-info:active, .btn-outline-info.active, .btn-outline-info.dropdown-toggle.show { - color: #000; - background-color: #0dcaf0; - border-color: #0dcaf0; -} -.btn-check:checked + .btn-outline-info:focus, .btn-check:active + .btn-outline-info:focus, .btn-outline-info:active:focus, .btn-outline-info.active:focus, .btn-outline-info.dropdown-toggle.show:focus { - box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.5); -} -.btn-outline-info:disabled, .btn-outline-info.disabled { - color: #0dcaf0; - background-color: transparent; -} - -.btn-outline-warning { - color: #ffc107; - border-color: #ffc107; -} -.btn-outline-warning:hover { - color: #000; - background-color: #ffc107; - border-color: #ffc107; -} -.btn-check:focus + .btn-outline-warning, .btn-outline-warning:focus { - box-shadow: 0 0 0 0.25rem rgba(255, 193, 7, 0.5); -} -.btn-check:checked + .btn-outline-warning, .btn-check:active + .btn-outline-warning, .btn-outline-warning:active, .btn-outline-warning.active, .btn-outline-warning.dropdown-toggle.show { - color: #000; - background-color: #ffc107; - border-color: #ffc107; -} -.btn-check:checked + .btn-outline-warning:focus, .btn-check:active + .btn-outline-warning:focus, .btn-outline-warning:active:focus, .btn-outline-warning.active:focus, .btn-outline-warning.dropdown-toggle.show:focus { - box-shadow: 0 0 0 0.25rem rgba(255, 193, 7, 0.5); -} -.btn-outline-warning:disabled, .btn-outline-warning.disabled { - color: #ffc107; - background-color: transparent; -} - -.btn-outline-danger { - color: #dc3545; - border-color: #dc3545; -} -.btn-outline-danger:hover { - color: #fff; - background-color: #dc3545; - border-color: #dc3545; -} -.btn-check:focus + .btn-outline-danger, .btn-outline-danger:focus { - box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.5); -} -.btn-check:checked + .btn-outline-danger, .btn-check:active + .btn-outline-danger, .btn-outline-danger:active, .btn-outline-danger.active, .btn-outline-danger.dropdown-toggle.show { - color: #fff; - background-color: #dc3545; - border-color: #dc3545; -} -.btn-check:checked + .btn-outline-danger:focus, .btn-check:active + .btn-outline-danger:focus, .btn-outline-danger:active:focus, .btn-outline-danger.active:focus, .btn-outline-danger.dropdown-toggle.show:focus { - box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.5); -} -.btn-outline-danger:disabled, .btn-outline-danger.disabled { - color: #dc3545; - background-color: transparent; -} - -.btn-outline-light { - color: #f8f9fa; - border-color: #f8f9fa; -} -.btn-outline-light:hover { - color: #000; - background-color: #f8f9fa; - border-color: #f8f9fa; -} -.btn-check:focus + .btn-outline-light, .btn-outline-light:focus { - box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5); -} -.btn-check:checked + .btn-outline-light, .btn-check:active + .btn-outline-light, .btn-outline-light:active, .btn-outline-light.active, .btn-outline-light.dropdown-toggle.show { - color: #000; - background-color: #f8f9fa; - border-color: #f8f9fa; -} -.btn-check:checked + .btn-outline-light:focus, .btn-check:active + .btn-outline-light:focus, .btn-outline-light:active:focus, .btn-outline-light.active:focus, .btn-outline-light.dropdown-toggle.show:focus { - box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5); -} -.btn-outline-light:disabled, .btn-outline-light.disabled { - color: #f8f9fa; - background-color: transparent; -} - -.btn-outline-dark { - color: #212529; - border-color: #212529; -} -.btn-outline-dark:hover { - color: #fff; - background-color: #212529; - border-color: #212529; -} -.btn-check:focus + .btn-outline-dark, .btn-outline-dark:focus { - box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5); -} -.btn-check:checked + .btn-outline-dark, .btn-check:active + .btn-outline-dark, .btn-outline-dark:active, .btn-outline-dark.active, .btn-outline-dark.dropdown-toggle.show { - color: #fff; - background-color: #212529; - border-color: #212529; -} -.btn-check:checked + .btn-outline-dark:focus, .btn-check:active + .btn-outline-dark:focus, .btn-outline-dark:active:focus, .btn-outline-dark.active:focus, .btn-outline-dark.dropdown-toggle.show:focus { - box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5); -} -.btn-outline-dark:disabled, .btn-outline-dark.disabled { - color: #212529; - background-color: transparent; -} - -.btn-link { - font-weight: 400; - color: #0d6efd; - text-decoration: underline; -} -.btn-link:hover { - color: #0a58ca; -} -.btn-link:disabled, .btn-link.disabled { - color: #6c757d; -} - -.btn-lg, .btn-group-lg > .btn { - padding: 0.5rem 1rem; - font-size: 1.25rem; - border-radius: 0.3rem; -} - -.btn-sm, .btn-group-sm > .btn { - padding: 0.25rem 0.5rem; - font-size: 0.875rem; - border-radius: 0.2rem; -} - -.fade { - transition: opacity 0.15s linear; -} -@media (prefers-reduced-motion: reduce) { - .fade { - transition: none; - } -} -.fade:not(.show) { - opacity: 0; -} - -.collapse:not(.show) { - display: none; -} - -.collapsing { - height: 0; - overflow: hidden; - transition: height 0.35s ease; -} -@media (prefers-reduced-motion: reduce) { - .collapsing { - transition: none; - } -} - -.dropup, -.dropend, -.dropdown, -.dropstart { - position: relative; -} - -.dropdown-toggle { - white-space: nowrap; -} -.dropdown-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0.3em solid; - border-right: 0.3em solid transparent; - border-bottom: 0; - border-left: 0.3em solid transparent; -} -.dropdown-toggle:empty::after { - margin-left: 0; -} - -.dropdown-menu { - position: absolute; - z-index: 1000; - display: none; - min-width: 10rem; - padding: 0.5rem 0; - margin: 0; - font-size: 1rem; - color: #212529; - text-align: left; - list-style: none; - background-color: #fff; - background-clip: padding-box; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 0.25rem; -} -.dropdown-menu[data-bs-popper] { - top: 100%; - left: 0; - margin-top: 0.125rem; -} - -.dropdown-menu-start { - --bs-position: start; -} -.dropdown-menu-start[data-bs-popper] { - right: auto /* rtl:ignore */; - left: 0 /* rtl:ignore */; -} - -.dropdown-menu-end { - --bs-position: end; -} -.dropdown-menu-end[data-bs-popper] { - right: 0 /* rtl:ignore */; - left: auto /* rtl:ignore */; -} - -@media (min-width: 576px) { - .dropdown-menu-sm-start { - --bs-position: start; - } - .dropdown-menu-sm-start[data-bs-popper] { - right: auto /* rtl:ignore */; - left: 0 /* rtl:ignore */; - } - - .dropdown-menu-sm-end { - --bs-position: end; - } - .dropdown-menu-sm-end[data-bs-popper] { - right: 0 /* rtl:ignore */; - left: auto /* rtl:ignore */; - } -} -@media (min-width: 768px) { - .dropdown-menu-md-start { - --bs-position: start; - } - .dropdown-menu-md-start[data-bs-popper] { - right: auto /* rtl:ignore */; - left: 0 /* rtl:ignore */; - } - - .dropdown-menu-md-end { - --bs-position: end; - } - .dropdown-menu-md-end[data-bs-popper] { - right: 0 /* rtl:ignore */; - left: auto /* rtl:ignore */; - } -} -@media (min-width: 992px) { - .dropdown-menu-lg-start { - --bs-position: start; - } - .dropdown-menu-lg-start[data-bs-popper] { - right: auto /* rtl:ignore */; - left: 0 /* rtl:ignore */; - } - - .dropdown-menu-lg-end { - --bs-position: end; - } - .dropdown-menu-lg-end[data-bs-popper] { - right: 0 /* rtl:ignore */; - left: auto /* rtl:ignore */; - } -} -@media (min-width: 1200px) { - .dropdown-menu-xl-start { - --bs-position: start; - } - .dropdown-menu-xl-start[data-bs-popper] { - right: auto /* rtl:ignore */; - left: 0 /* rtl:ignore */; - } - - .dropdown-menu-xl-end { - --bs-position: end; - } - .dropdown-menu-xl-end[data-bs-popper] { - right: 0 /* rtl:ignore */; - left: auto /* rtl:ignore */; - } -} -@media (min-width: 1400px) { - .dropdown-menu-xxl-start { - --bs-position: start; - } - .dropdown-menu-xxl-start[data-bs-popper] { - right: auto /* rtl:ignore */; - left: 0 /* rtl:ignore */; - } - - .dropdown-menu-xxl-end { - --bs-position: end; - } - .dropdown-menu-xxl-end[data-bs-popper] { - right: 0 /* rtl:ignore */; - left: auto /* rtl:ignore */; - } -} -.dropup .dropdown-menu[data-bs-popper] { - top: auto; - bottom: 100%; - margin-top: 0; - margin-bottom: 0.125rem; -} -.dropup .dropdown-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0; - border-right: 0.3em solid transparent; - border-bottom: 0.3em solid; - border-left: 0.3em solid transparent; -} -.dropup .dropdown-toggle:empty::after { - margin-left: 0; -} - -.dropend .dropdown-menu[data-bs-popper] { - top: 0; - right: auto; - left: 100%; - margin-top: 0; - margin-left: 0.125rem; -} -.dropend .dropdown-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0.3em solid transparent; - border-right: 0; - border-bottom: 0.3em solid transparent; - border-left: 0.3em solid; -} -.dropend .dropdown-toggle:empty::after { - margin-left: 0; -} -.dropend .dropdown-toggle::after { - vertical-align: 0; -} - -.dropstart .dropdown-menu[data-bs-popper] { - top: 0; - right: 100%; - left: auto; - margin-top: 0; - margin-right: 0.125rem; -} -.dropstart .dropdown-toggle::after { - display: inline-block; - margin-left: 0.255em; - vertical-align: 0.255em; - content: ""; -} -.dropstart .dropdown-toggle::after { - display: none; -} -.dropstart .dropdown-toggle::before { - display: inline-block; - margin-right: 0.255em; - vertical-align: 0.255em; - content: ""; - border-top: 0.3em solid transparent; - border-right: 0.3em solid; - border-bottom: 0.3em solid transparent; -} -.dropstart .dropdown-toggle:empty::after { - margin-left: 0; -} -.dropstart .dropdown-toggle::before { - vertical-align: 0; -} - -.dropdown-divider { - height: 0; - margin: 0.5rem 0; - overflow: hidden; - border-top: 1px solid rgba(0, 0, 0, 0.15); -} - -.dropdown-item { - display: block; - padding: 0.25rem 1rem; - clear: both; - font-weight: 400; - color: #212529; - text-align: inherit; - text-decoration: none; - white-space: nowrap; - background-color: transparent; - border: 0; -} -.dropdown-item:hover, .dropdown-item:focus { - color: #1e2125; - background-color: #e9ecef; -} -.dropdown-item.active, .dropdown-item:active { - color: #fff; - text-decoration: none; - background-color: #0d6efd; -} -.dropdown-item.disabled, .dropdown-item:disabled { - color: #adb5bd; - pointer-events: none; - background-color: transparent; -} - -.dropdown-menu.show { - display: block; -} - -.dropdown-header { - display: block; - padding: 0.5rem 1rem; - margin-bottom: 0; - font-size: 0.875rem; - color: #6c757d; - white-space: nowrap; -} - -.dropdown-item-text { - display: block; - padding: 0.25rem 1rem; - color: #212529; -} - -.dropdown-menu-dark { - color: #dee2e6; - background-color: #343a40; - border-color: rgba(0, 0, 0, 0.15); -} -.dropdown-menu-dark .dropdown-item { - color: #dee2e6; -} -.dropdown-menu-dark .dropdown-item:hover, .dropdown-menu-dark .dropdown-item:focus { - color: #fff; - background-color: rgba(255, 255, 255, 0.15); -} -.dropdown-menu-dark .dropdown-item.active, .dropdown-menu-dark .dropdown-item:active { - color: #fff; - background-color: #0d6efd; -} -.dropdown-menu-dark .dropdown-item.disabled, .dropdown-menu-dark .dropdown-item:disabled { - color: #adb5bd; -} -.dropdown-menu-dark .dropdown-divider { - border-color: rgba(0, 0, 0, 0.15); -} -.dropdown-menu-dark .dropdown-item-text { - color: #dee2e6; -} -.dropdown-menu-dark .dropdown-header { - color: #adb5bd; -} - -.btn-group, -.btn-group-vertical { - position: relative; - display: inline-flex; - vertical-align: middle; -} -.btn-group > .btn, -.btn-group-vertical > .btn { - position: relative; - flex: 1 1 auto; -} -.btn-group > .btn-check:checked + .btn, -.btn-group > .btn-check:focus + .btn, -.btn-group > .btn:hover, -.btn-group > .btn:focus, -.btn-group > .btn:active, -.btn-group > .btn.active, -.btn-group-vertical > .btn-check:checked + .btn, -.btn-group-vertical > .btn-check:focus + .btn, -.btn-group-vertical > .btn:hover, -.btn-group-vertical > .btn:focus, -.btn-group-vertical > .btn:active, -.btn-group-vertical > .btn.active { - z-index: 1; -} - -.btn-toolbar { - display: flex; - flex-wrap: wrap; - justify-content: flex-start; -} -.btn-toolbar .input-group { - width: auto; -} - -.btn-group > .btn:not(:first-child), -.btn-group > .btn-group:not(:first-child) { - margin-left: -1px; -} -.btn-group > .btn:not(:last-child):not(.dropdown-toggle), -.btn-group > .btn-group:not(:last-child) > .btn { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn:nth-child(n+3), -.btn-group > :not(.btn-check) + .btn, -.btn-group > .btn-group:not(:first-child) > .btn { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -.dropdown-toggle-split { - padding-right: 0.5625rem; - padding-left: 0.5625rem; -} -.dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after, .dropend .dropdown-toggle-split::after { - margin-left: 0; -} -.dropstart .dropdown-toggle-split::before { - margin-right: 0; -} - -.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { - padding-right: 0.375rem; - padding-left: 0.375rem; -} - -.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { - padding-right: 0.75rem; - padding-left: 0.75rem; -} - -.btn-group-vertical { - flex-direction: column; - align-items: flex-start; - justify-content: center; -} -.btn-group-vertical > .btn, -.btn-group-vertical > .btn-group { - width: 100%; -} -.btn-group-vertical > .btn:not(:first-child), -.btn-group-vertical > .btn-group:not(:first-child) { - margin-top: -1px; -} -.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), -.btn-group-vertical > .btn-group:not(:last-child) > .btn { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn ~ .btn, -.btn-group-vertical > .btn-group:not(:first-child) > .btn { - border-top-left-radius: 0; - border-top-right-radius: 0; -} - -.nav { - display: flex; - flex-wrap: wrap; - padding-left: 0; - margin-bottom: 0; - list-style: none; -} - -.nav-link { - display: block; - padding: 0.5rem 1rem; - color: #0d6efd; - text-decoration: none; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; -} -@media (prefers-reduced-motion: reduce) { - .nav-link { - transition: none; - } -} -.nav-link:hover, .nav-link:focus { - color: #0a58ca; -} -.nav-link.disabled { - color: #6c757d; - pointer-events: none; - cursor: default; -} - -.nav-tabs { - border-bottom: 1px solid #dee2e6; -} -.nav-tabs .nav-link { - margin-bottom: -1px; - background: none; - border: 1px solid transparent; - border-top-left-radius: 0.25rem; - border-top-right-radius: 0.25rem; -} -.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { - border-color: #e9ecef #e9ecef #dee2e6; - isolation: isolate; -} -.nav-tabs .nav-link.disabled { - color: #6c757d; - background-color: transparent; - border-color: transparent; -} -.nav-tabs .nav-link.active, -.nav-tabs .nav-item.show .nav-link { - color: #495057; - background-color: #fff; - border-color: #dee2e6 #dee2e6 #fff; -} -.nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-left-radius: 0; - border-top-right-radius: 0; -} - -.nav-pills .nav-link { - background: none; - border: 0; - border-radius: 0.25rem; -} -.nav-pills .nav-link.active, -.nav-pills .show > .nav-link { - color: #fff; - background-color: #0d6efd; -} - -.nav-fill > .nav-link, -.nav-fill .nav-item { - flex: 1 1 auto; - text-align: center; -} - -.nav-justified > .nav-link, -.nav-justified .nav-item { - flex-basis: 0; - flex-grow: 1; - text-align: center; -} - -.nav-fill .nav-item .nav-link, -.nav-justified .nav-item .nav-link { - width: 100%; -} - -.tab-content > .tab-pane { - display: none; -} -.tab-content > .active { - display: block; -} - -.navbar { - position: relative; - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: space-between; - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} -.navbar > .container, -.navbar > .container-fluid, -.navbar > .container-sm, -.navbar > .container-md, -.navbar > .container-lg, -.navbar > .container-xl, -.navbar > .container-xxl { - display: flex; - flex-wrap: inherit; - align-items: center; - justify-content: space-between; -} -.navbar-brand { - padding-top: 0.3125rem; - padding-bottom: 0.3125rem; - margin-right: 1rem; - font-size: 1.25rem; - text-decoration: none; - white-space: nowrap; -} -.navbar-nav { - display: flex; - flex-direction: column; - padding-left: 0; - margin-bottom: 0; - list-style: none; -} -.navbar-nav .nav-link { - padding-right: 0; - padding-left: 0; -} -.navbar-nav .dropdown-menu { - position: static; -} - -.navbar-text { - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} - -.navbar-collapse { - flex-basis: 100%; - flex-grow: 1; - align-items: center; -} - -.navbar-toggler { - padding: 0.25rem 0.75rem; - font-size: 1.25rem; - line-height: 1; - background-color: transparent; - border: 1px solid transparent; - border-radius: 0.25rem; - transition: box-shadow 0.15s ease-in-out; -} -@media (prefers-reduced-motion: reduce) { - .navbar-toggler { - transition: none; - } -} -.navbar-toggler:hover { - text-decoration: none; -} -.navbar-toggler:focus { - text-decoration: none; - outline: 0; - box-shadow: 0 0 0 0.25rem; -} - -.navbar-toggler-icon { - display: inline-block; - width: 1.5em; - height: 1.5em; - vertical-align: middle; - background-repeat: no-repeat; - background-position: center; - background-size: 100%; -} - -.navbar-nav-scroll { - max-height: var(--bs-scroll-height, 75vh); - overflow-y: auto; -} - -@media (min-width: 576px) { - .navbar-expand-sm { - flex-wrap: nowrap; - justify-content: flex-start; - } - .navbar-expand-sm .navbar-nav { - flex-direction: row; - } - .navbar-expand-sm .navbar-nav .dropdown-menu { - position: absolute; - } - .navbar-expand-sm .navbar-nav .nav-link { - padding-right: 0.5rem; - padding-left: 0.5rem; - } - .navbar-expand-sm .navbar-nav-scroll { - overflow: visible; - } - .navbar-expand-sm .navbar-collapse { - display: flex !important; - flex-basis: auto; - } - .navbar-expand-sm .navbar-toggler { - display: none; - } -} -@media (min-width: 768px) { - .navbar-expand-md { - flex-wrap: nowrap; - justify-content: flex-start; - } - .navbar-expand-md .navbar-nav { - flex-direction: row; - } - .navbar-expand-md .navbar-nav .dropdown-menu { - position: absolute; - } - .navbar-expand-md .navbar-nav .nav-link { - padding-right: 0.5rem; - padding-left: 0.5rem; - } - .navbar-expand-md .navbar-nav-scroll { - overflow: visible; - } - .navbar-expand-md .navbar-collapse { - display: flex !important; - flex-basis: auto; - } - .navbar-expand-md .navbar-toggler { - display: none; - } -} -@media (min-width: 992px) { - .navbar-expand-lg { - flex-wrap: nowrap; - justify-content: flex-start; - } - .navbar-expand-lg .navbar-nav { - flex-direction: row; - } - .navbar-expand-lg .navbar-nav .dropdown-menu { - position: absolute; - } - .navbar-expand-lg .navbar-nav .nav-link { - padding-right: 0.5rem; - padding-left: 0.5rem; - } - .navbar-expand-lg .navbar-nav-scroll { - overflow: visible; - } - .navbar-expand-lg .navbar-collapse { - display: flex !important; - flex-basis: auto; - } - .navbar-expand-lg .navbar-toggler { - display: none; - } -} -@media (min-width: 1200px) { - .navbar-expand-xl { - flex-wrap: nowrap; - justify-content: flex-start; - } - .navbar-expand-xl .navbar-nav { - flex-direction: row; - } - .navbar-expand-xl .navbar-nav .dropdown-menu { - position: absolute; - } - .navbar-expand-xl .navbar-nav .nav-link { - padding-right: 0.5rem; - padding-left: 0.5rem; - } - .navbar-expand-xl .navbar-nav-scroll { - overflow: visible; - } - .navbar-expand-xl .navbar-collapse { - display: flex !important; - flex-basis: auto; - } - .navbar-expand-xl .navbar-toggler { - display: none; - } -} -@media (min-width: 1400px) { - .navbar-expand-xxl { - flex-wrap: nowrap; - justify-content: flex-start; - } - .navbar-expand-xxl .navbar-nav { - flex-direction: row; - } - .navbar-expand-xxl .navbar-nav .dropdown-menu { - position: absolute; - } - .navbar-expand-xxl .navbar-nav .nav-link { - padding-right: 0.5rem; - padding-left: 0.5rem; - } - .navbar-expand-xxl .navbar-nav-scroll { - overflow: visible; - } - .navbar-expand-xxl .navbar-collapse { - display: flex !important; - flex-basis: auto; - } - .navbar-expand-xxl .navbar-toggler { - display: none; - } -} -.navbar-expand { - flex-wrap: nowrap; - justify-content: flex-start; -} -.navbar-expand .navbar-nav { - flex-direction: row; -} -.navbar-expand .navbar-nav .dropdown-menu { - position: absolute; -} -.navbar-expand .navbar-nav .nav-link { - padding-right: 0.5rem; - padding-left: 0.5rem; -} -.navbar-expand .navbar-nav-scroll { - overflow: visible; -} -.navbar-expand .navbar-collapse { - display: flex !important; - flex-basis: auto; -} -.navbar-expand .navbar-toggler { - display: none; -} - -.navbar-light .navbar-brand { - color: rgba(0, 0, 0, 0.9); -} -.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus { - color: rgba(0, 0, 0, 0.9); -} -.navbar-light .navbar-nav .nav-link { - color: rgba(0, 0, 0, 0.55); -} -.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus { - color: rgba(0, 0, 0, 0.7); -} -.navbar-light .navbar-nav .nav-link.disabled { - color: rgba(0, 0, 0, 0.3); -} -.navbar-light .navbar-nav .show > .nav-link, -.navbar-light .navbar-nav .nav-link.active { - color: rgba(0, 0, 0, 0.9); -} -.navbar-light .navbar-toggler { - color: rgba(0, 0, 0, 0.55); - border-color: rgba(0, 0, 0, 0.1); -} -.navbar-light .navbar-toggler-icon { - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); -} -.navbar-light .navbar-text { - color: rgba(0, 0, 0, 0.55); -} -.navbar-light .navbar-text a, -.navbar-light .navbar-text a:hover, -.navbar-light .navbar-text a:focus { - color: rgba(0, 0, 0, 0.9); -} - -.navbar-dark .navbar-brand { - color: #fff; -} -.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus { - color: #fff; -} -.navbar-dark .navbar-nav .nav-link { - color: rgba(255, 255, 255, 0.55); -} -.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus { - color: rgba(255, 255, 255, 0.75); -} -.navbar-dark .navbar-nav .nav-link.disabled { - color: rgba(255, 255, 255, 0.25); -} -.navbar-dark .navbar-nav .show > .nav-link, -.navbar-dark .navbar-nav .nav-link.active { - color: #fff; -} -.navbar-dark .navbar-toggler { - color: rgba(255, 255, 255, 0.55); - border-color: rgba(255, 255, 255, 0.1); -} -.navbar-dark .navbar-toggler-icon { - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); -} -.navbar-dark .navbar-text { - color: rgba(255, 255, 255, 0.55); -} -.navbar-dark .navbar-text a, -.navbar-dark .navbar-text a:hover, -.navbar-dark .navbar-text a:focus { - color: #fff; -} - -.card { - position: relative; - display: flex; - flex-direction: column; - min-width: 0; - word-wrap: break-word; - background-color: #fff; - background-clip: border-box; - border: 1px solid rgba(0, 0, 0, 0.125); - border-radius: 0.25rem; -} -.card > hr { - margin-right: 0; - margin-left: 0; -} -.card > .list-group { - border-top: inherit; - border-bottom: inherit; -} -.card > .list-group:first-child { - border-top-width: 0; - border-top-left-radius: calc(0.25rem - 1px); - border-top-right-radius: calc(0.25rem - 1px); -} -.card > .list-group:last-child { - border-bottom-width: 0; - border-bottom-right-radius: calc(0.25rem - 1px); - border-bottom-left-radius: calc(0.25rem - 1px); -} -.card > .card-header + .list-group, -.card > .list-group + .card-footer { - border-top: 0; -} - -.card-body { - flex: 1 1 auto; - padding: 1rem 1rem; -} - -.card-title { - margin-bottom: 0.5rem; -} - -.card-subtitle { - margin-top: -0.25rem; - margin-bottom: 0; -} - -.card-text:last-child { - margin-bottom: 0; -} - -.card-link:hover { - text-decoration: none; -} -.card-link + .card-link { - margin-left: 1rem; -} - -.card-header { - padding: 0.5rem 1rem; - margin-bottom: 0; - background-color: rgba(0, 0, 0, 0.03); - border-bottom: 1px solid rgba(0, 0, 0, 0.125); -} -.card-header:first-child { - border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; -} - -.card-footer { - padding: 0.5rem 1rem; - background-color: rgba(0, 0, 0, 0.03); - border-top: 1px solid rgba(0, 0, 0, 0.125); -} -.card-footer:last-child { - border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); -} - -.card-header-tabs { - margin-right: -0.5rem; - margin-bottom: -0.5rem; - margin-left: -0.5rem; - border-bottom: 0; -} - -.card-header-pills { - margin-right: -0.5rem; - margin-left: -0.5rem; -} - -.card-img-overlay { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - padding: 1rem; - border-radius: calc(0.25rem - 1px); -} - -.card-img, -.card-img-top, -.card-img-bottom { - width: 100%; -} - -.card-img, -.card-img-top { - border-top-left-radius: calc(0.25rem - 1px); - border-top-right-radius: calc(0.25rem - 1px); -} - -.card-img, -.card-img-bottom { - border-bottom-right-radius: calc(0.25rem - 1px); - border-bottom-left-radius: calc(0.25rem - 1px); -} - -.card-group > .card { - margin-bottom: 0.75rem; -} -@media (min-width: 576px) { - .card-group { - display: flex; - flex-flow: row wrap; - } - .card-group > .card { - flex: 1 0 0%; - margin-bottom: 0; - } - .card-group > .card + .card { - margin-left: 0; - border-left: 0; - } - .card-group > .card:not(:last-child) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - } - .card-group > .card:not(:last-child) .card-img-top, -.card-group > .card:not(:last-child) .card-header { - border-top-right-radius: 0; - } - .card-group > .card:not(:last-child) .card-img-bottom, -.card-group > .card:not(:last-child) .card-footer { - border-bottom-right-radius: 0; - } - .card-group > .card:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - } - .card-group > .card:not(:first-child) .card-img-top, -.card-group > .card:not(:first-child) .card-header { - border-top-left-radius: 0; - } - .card-group > .card:not(:first-child) .card-img-bottom, -.card-group > .card:not(:first-child) .card-footer { - border-bottom-left-radius: 0; - } -} - -.accordion-button { - position: relative; - display: flex; - align-items: center; - width: 100%; - padding: 1rem 1.25rem; - font-size: 1rem; - color: #212529; - text-align: left; - background-color: #fff; - border: 0; - border-radius: 0; - overflow-anchor: none; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease; -} -@media (prefers-reduced-motion: reduce) { - .accordion-button { - transition: none; - } -} -.accordion-button:not(.collapsed) { - color: #0c63e4; - background-color: #e7f1ff; - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.125); -} -.accordion-button:not(.collapsed)::after { - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); - transform: rotate(-180deg); -} -.accordion-button::after { - flex-shrink: 0; - width: 1.25rem; - height: 1.25rem; - margin-left: auto; - content: ""; - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); - background-repeat: no-repeat; - background-size: 1.25rem; - transition: transform 0.2s ease-in-out; -} -@media (prefers-reduced-motion: reduce) { - .accordion-button::after { - transition: none; - } -} -.accordion-button:hover { - z-index: 2; -} -.accordion-button:focus { - z-index: 3; - border-color: #86b7fe; - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); -} - -.accordion-header { - margin-bottom: 0; -} - -.accordion-item { - background-color: #fff; - border: 1px solid rgba(0, 0, 0, 0.125); -} -.accordion-item:first-of-type { - border-top-left-radius: 0.25rem; - border-top-right-radius: 0.25rem; -} -.accordion-item:first-of-type .accordion-button { - border-top-left-radius: calc(0.25rem - 1px); - border-top-right-radius: calc(0.25rem - 1px); -} -.accordion-item:not(:first-of-type) { - border-top: 0; -} -.accordion-item:last-of-type { - border-bottom-right-radius: 0.25rem; - border-bottom-left-radius: 0.25rem; -} -.accordion-item:last-of-type .accordion-button.collapsed { - border-bottom-right-radius: calc(0.25rem - 1px); - border-bottom-left-radius: calc(0.25rem - 1px); -} -.accordion-item:last-of-type .accordion-collapse { - border-bottom-right-radius: 0.25rem; - border-bottom-left-radius: 0.25rem; -} - -.accordion-body { - padding: 1rem 1.25rem; -} - -.accordion-flush .accordion-collapse { - border-width: 0; -} -.accordion-flush .accordion-item { - border-right: 0; - border-left: 0; - border-radius: 0; -} -.accordion-flush .accordion-item:first-child { - border-top: 0; -} -.accordion-flush .accordion-item:last-child { - border-bottom: 0; -} -.accordion-flush .accordion-item .accordion-button { - border-radius: 0; -} - -.breadcrumb { - display: flex; - flex-wrap: wrap; - padding: 0 0; - margin-bottom: 1rem; - list-style: none; -} - -.breadcrumb-item + .breadcrumb-item { - padding-left: 0.5rem; -} -.breadcrumb-item + .breadcrumb-item::before { - float: left; - padding-right: 0.5rem; - color: #6c757d; - content: var(--bs-breadcrumb-divider, "/") /* rtl: var(--bs-breadcrumb-divider, "/") */; -} -.breadcrumb-item.active { - color: #6c757d; -} - -.pagination { - display: flex; - padding-left: 0; - list-style: none; -} - -.page-link { - position: relative; - display: block; - color: #0d6efd; - text-decoration: none; - background-color: #fff; - border: 1px solid #dee2e6; - transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -} -@media (prefers-reduced-motion: reduce) { - .page-link { - transition: none; - } -} -.page-link:hover { - z-index: 2; - color: #0a58ca; - background-color: #e9ecef; - border-color: #dee2e6; -} -.page-link:focus { - z-index: 3; - color: #0a58ca; - background-color: #e9ecef; - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); -} - -.page-item:not(:first-child) .page-link { - margin-left: -1px; -} -.page-item.active .page-link { - z-index: 3; - color: #fff; - background-color: #0d6efd; - border-color: #0d6efd; -} -.page-item.disabled .page-link { - color: #6c757d; - pointer-events: none; - background-color: #fff; - border-color: #dee2e6; -} - -.page-link { - padding: 0.375rem 0.75rem; -} - -.page-item:first-child .page-link { - border-top-left-radius: 0.25rem; - border-bottom-left-radius: 0.25rem; -} -.page-item:last-child .page-link { - border-top-right-radius: 0.25rem; - border-bottom-right-radius: 0.25rem; -} - -.pagination-lg .page-link { - padding: 0.75rem 1.5rem; - font-size: 1.25rem; -} -.pagination-lg .page-item:first-child .page-link { - border-top-left-radius: 0.3rem; - border-bottom-left-radius: 0.3rem; -} -.pagination-lg .page-item:last-child .page-link { - border-top-right-radius: 0.3rem; - border-bottom-right-radius: 0.3rem; -} - -.pagination-sm .page-link { - padding: 0.25rem 0.5rem; - font-size: 0.875rem; -} -.pagination-sm .page-item:first-child .page-link { - border-top-left-radius: 0.2rem; - border-bottom-left-radius: 0.2rem; -} -.pagination-sm .page-item:last-child .page-link { - border-top-right-radius: 0.2rem; - border-bottom-right-radius: 0.2rem; -} - -.badge { - display: inline-block; - padding: 0.35em 0.65em; - font-size: 0.75em; - font-weight: 700; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: 0.25rem; -} -.badge:empty { - display: none; -} - -.btn .badge { - position: relative; - top: -1px; -} - -.alert { - position: relative; - padding: 1rem 1rem; - margin-bottom: 1rem; - border: 1px solid transparent; - border-radius: 0.25rem; -} - -.alert-heading { - color: inherit; -} - -.alert-link { - font-weight: 700; -} - -.alert-dismissible { - padding-right: 3rem; -} -.alert-dismissible .btn-close { - position: absolute; - top: 0; - right: 0; - z-index: 2; - padding: 1.25rem 1rem; -} - -.alert-primary { - color: #084298; - background-color: #cfe2ff; - border-color: #b6d4fe; -} -.alert-primary .alert-link { - color: #06357a; -} - -.alert-secondary { - color: #41464b; - background-color: #e2e3e5; - border-color: #d3d6d8; -} -.alert-secondary .alert-link { - color: #34383c; -} - -.alert-success { - color: #0f5132; - background-color: #d1e7dd; - border-color: #badbcc; -} -.alert-success .alert-link { - color: #0c4128; -} - -.alert-info { - color: #055160; - background-color: #cff4fc; - border-color: #b6effb; -} -.alert-info .alert-link { - color: #04414d; -} - -.alert-warning { - color: #664d03; - background-color: #fff3cd; - border-color: #ffecb5; -} -.alert-warning .alert-link { - color: #523e02; -} - -.alert-danger { - color: #842029; - background-color: #f8d7da; - border-color: #f5c2c7; -} -.alert-danger .alert-link { - color: #6a1a21; -} - -.alert-light { - color: #636464; - background-color: #fefefe; - border-color: #fdfdfe; -} -.alert-light .alert-link { - color: #4f5050; -} - -.alert-dark { - color: #141619; - background-color: #d3d3d4; - border-color: #bcbebf; -} -.alert-dark .alert-link { - color: #101214; -} - -@-webkit-keyframes progress-bar-stripes { - 0% { - background-position-x: 1rem; - } -} - -@keyframes progress-bar-stripes { - 0% { - background-position-x: 1rem; - } -} -.progress { - display: flex; - height: 1rem; - overflow: hidden; - font-size: 0.75rem; - background-color: #e9ecef; - border-radius: 0.25rem; -} - -.progress-bar { - display: flex; - flex-direction: column; - justify-content: center; - overflow: hidden; - color: #fff; - text-align: center; - white-space: nowrap; - background-color: #0d6efd; - transition: width 0.6s ease; -} -@media (prefers-reduced-motion: reduce) { - .progress-bar { - transition: none; - } -} - -.progress-bar-striped { - background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); - background-size: 1rem 1rem; -} - -.progress-bar-animated { - -webkit-animation: 1s linear infinite progress-bar-stripes; - animation: 1s linear infinite progress-bar-stripes; -} -@media (prefers-reduced-motion: reduce) { - .progress-bar-animated { - -webkit-animation: none; - animation: none; - } -} - -.list-group { - display: flex; - flex-direction: column; - padding-left: 0; - margin-bottom: 0; - border-radius: 0.25rem; -} - -.list-group-numbered { - list-style-type: none; - counter-reset: section; -} -.list-group-numbered > li::before { - content: counters(section, ".") ". "; - counter-increment: section; -} - -.list-group-item-action { - width: 100%; - color: #495057; - text-align: inherit; -} -.list-group-item-action:hover, .list-group-item-action:focus { - z-index: 1; - color: #495057; - text-decoration: none; - background-color: #f8f9fa; -} -.list-group-item-action:active { - color: #212529; - background-color: #e9ecef; -} - -.list-group-item { - position: relative; - display: block; - padding: 0.5rem 1rem; - color: #212529; - text-decoration: none; - background-color: #fff; - border: 1px solid rgba(0, 0, 0, 0.125); -} -.list-group-item:first-child { - border-top-left-radius: inherit; - border-top-right-radius: inherit; -} -.list-group-item:last-child { - border-bottom-right-radius: inherit; - border-bottom-left-radius: inherit; -} -.list-group-item.disabled, .list-group-item:disabled { - color: #6c757d; - pointer-events: none; - background-color: #fff; -} -.list-group-item.active { - z-index: 2; - color: #fff; - background-color: #0d6efd; - border-color: #0d6efd; -} -.list-group-item + .list-group-item { - border-top-width: 0; -} -.list-group-item + .list-group-item.active { - margin-top: -1px; - border-top-width: 1px; -} - -.list-group-horizontal { - flex-direction: row; -} -.list-group-horizontal > .list-group-item:first-child { - border-bottom-left-radius: 0.25rem; - border-top-right-radius: 0; -} -.list-group-horizontal > .list-group-item:last-child { - border-top-right-radius: 0.25rem; - border-bottom-left-radius: 0; -} -.list-group-horizontal > .list-group-item.active { - margin-top: 0; -} -.list-group-horizontal > .list-group-item + .list-group-item { - border-top-width: 1px; - border-left-width: 0; -} -.list-group-horizontal > .list-group-item + .list-group-item.active { - margin-left: -1px; - border-left-width: 1px; -} - -@media (min-width: 576px) { - .list-group-horizontal-sm { - flex-direction: row; - } - .list-group-horizontal-sm > .list-group-item:first-child { - border-bottom-left-radius: 0.25rem; - border-top-right-radius: 0; - } - .list-group-horizontal-sm > .list-group-item:last-child { - border-top-right-radius: 0.25rem; - border-bottom-left-radius: 0; - } - .list-group-horizontal-sm > .list-group-item.active { - margin-top: 0; - } - .list-group-horizontal-sm > .list-group-item + .list-group-item { - border-top-width: 1px; - border-left-width: 0; - } - .list-group-horizontal-sm > .list-group-item + .list-group-item.active { - margin-left: -1px; - border-left-width: 1px; - } -} -@media (min-width: 768px) { - .list-group-horizontal-md { - flex-direction: row; - } - .list-group-horizontal-md > .list-group-item:first-child { - border-bottom-left-radius: 0.25rem; - border-top-right-radius: 0; - } - .list-group-horizontal-md > .list-group-item:last-child { - border-top-right-radius: 0.25rem; - border-bottom-left-radius: 0; - } - .list-group-horizontal-md > .list-group-item.active { - margin-top: 0; - } - .list-group-horizontal-md > .list-group-item + .list-group-item { - border-top-width: 1px; - border-left-width: 0; - } - .list-group-horizontal-md > .list-group-item + .list-group-item.active { - margin-left: -1px; - border-left-width: 1px; - } -} -@media (min-width: 992px) { - .list-group-horizontal-lg { - flex-direction: row; - } - .list-group-horizontal-lg > .list-group-item:first-child { - border-bottom-left-radius: 0.25rem; - border-top-right-radius: 0; - } - .list-group-horizontal-lg > .list-group-item:last-child { - border-top-right-radius: 0.25rem; - border-bottom-left-radius: 0; - } - .list-group-horizontal-lg > .list-group-item.active { - margin-top: 0; - } - .list-group-horizontal-lg > .list-group-item + .list-group-item { - border-top-width: 1px; - border-left-width: 0; - } - .list-group-horizontal-lg > .list-group-item + .list-group-item.active { - margin-left: -1px; - border-left-width: 1px; - } -} -@media (min-width: 1200px) { - .list-group-horizontal-xl { - flex-direction: row; - } - .list-group-horizontal-xl > .list-group-item:first-child { - border-bottom-left-radius: 0.25rem; - border-top-right-radius: 0; - } - .list-group-horizontal-xl > .list-group-item:last-child { - border-top-right-radius: 0.25rem; - border-bottom-left-radius: 0; - } - .list-group-horizontal-xl > .list-group-item.active { - margin-top: 0; - } - .list-group-horizontal-xl > .list-group-item + .list-group-item { - border-top-width: 1px; - border-left-width: 0; - } - .list-group-horizontal-xl > .list-group-item + .list-group-item.active { - margin-left: -1px; - border-left-width: 1px; - } -} -@media (min-width: 1400px) { - .list-group-horizontal-xxl { - flex-direction: row; - } - .list-group-horizontal-xxl > .list-group-item:first-child { - border-bottom-left-radius: 0.25rem; - border-top-right-radius: 0; - } - .list-group-horizontal-xxl > .list-group-item:last-child { - border-top-right-radius: 0.25rem; - border-bottom-left-radius: 0; - } - .list-group-horizontal-xxl > .list-group-item.active { - margin-top: 0; - } - .list-group-horizontal-xxl > .list-group-item + .list-group-item { - border-top-width: 1px; - border-left-width: 0; - } - .list-group-horizontal-xxl > .list-group-item + .list-group-item.active { - margin-left: -1px; - border-left-width: 1px; - } -} -.list-group-flush { - border-radius: 0; -} -.list-group-flush > .list-group-item { - border-width: 0 0 1px; -} -.list-group-flush > .list-group-item:last-child { - border-bottom-width: 0; -} - -.list-group-item-primary { - color: #084298; - background-color: #cfe2ff; -} -.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { - color: #084298; - background-color: #bacbe6; -} -.list-group-item-primary.list-group-item-action.active { - color: #fff; - background-color: #084298; - border-color: #084298; -} - -.list-group-item-secondary { - color: #41464b; - background-color: #e2e3e5; -} -.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { - color: #41464b; - background-color: #cbccce; -} -.list-group-item-secondary.list-group-item-action.active { - color: #fff; - background-color: #41464b; - border-color: #41464b; -} - -.list-group-item-success { - color: #0f5132; - background-color: #d1e7dd; -} -.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus { - color: #0f5132; - background-color: #bcd0c7; -} -.list-group-item-success.list-group-item-action.active { - color: #fff; - background-color: #0f5132; - border-color: #0f5132; -} - -.list-group-item-info { - color: #055160; - background-color: #cff4fc; -} -.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { - color: #055160; - background-color: #badce3; -} -.list-group-item-info.list-group-item-action.active { - color: #fff; - background-color: #055160; - border-color: #055160; -} - -.list-group-item-warning { - color: #664d03; - background-color: #fff3cd; -} -.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { - color: #664d03; - background-color: #e6dbb9; -} -.list-group-item-warning.list-group-item-action.active { - color: #fff; - background-color: #664d03; - border-color: #664d03; -} - -.list-group-item-danger { - color: #842029; - background-color: #f8d7da; -} -.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus { - color: #842029; - background-color: #dfc2c4; -} -.list-group-item-danger.list-group-item-action.active { - color: #fff; - background-color: #842029; - border-color: #842029; -} - -.list-group-item-light { - color: #636464; - background-color: #fefefe; -} -.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { - color: #636464; - background-color: #e5e5e5; -} -.list-group-item-light.list-group-item-action.active { - color: #fff; - background-color: #636464; - border-color: #636464; -} - -.list-group-item-dark { - color: #141619; - background-color: #d3d3d4; -} -.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus { - color: #141619; - background-color: #bebebf; -} -.list-group-item-dark.list-group-item-action.active { - color: #fff; - background-color: #141619; - border-color: #141619; -} - -.btn-close { - box-sizing: content-box; - width: 1em; - height: 1em; - padding: 0.25em 0.25em; - color: #000; - background: transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat; - border: 0; - border-radius: 0.25rem; - opacity: 0.5; -} -.btn-close:hover { - color: #000; - text-decoration: none; - opacity: 0.75; -} -.btn-close:focus { - outline: 0; - box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); - opacity: 1; -} -.btn-close:disabled, .btn-close.disabled { - pointer-events: none; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - opacity: 0.25; -} - -.btn-close-white { - filter: invert(1) grayscale(100%) brightness(200%); -} - -.toast { - width: 350px; - max-width: 100%; - font-size: 0.875rem; - pointer-events: auto; - background-color: rgba(255, 255, 255, 0.85); - background-clip: padding-box; - border: 1px solid rgba(0, 0, 0, 0.1); - box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); - border-radius: 0.25rem; -} -.toast:not(.showing):not(.show) { - opacity: 0; -} -.toast.hide { - display: none; -} - -.toast-container { - width: -webkit-max-content; - width: -moz-max-content; - width: max-content; - max-width: 100%; - pointer-events: none; -} -.toast-container > :not(:last-child) { - margin-bottom: 0.75rem; -} - -.toast-header { - display: flex; - align-items: center; - padding: 0.5rem 0.75rem; - color: #6c757d; - background-color: rgba(255, 255, 255, 0.85); - background-clip: padding-box; - border-bottom: 1px solid rgba(0, 0, 0, 0.05); - border-top-left-radius: calc(0.25rem - 1px); - border-top-right-radius: calc(0.25rem - 1px); -} -.toast-header .btn-close { - margin-right: -0.375rem; - margin-left: 0.75rem; -} - -.toast-body { - padding: 0.75rem; - word-wrap: break-word; -} - -.modal { - position: fixed; - top: 0; - left: 0; - z-index: 1060; - display: none; - width: 100%; - height: 100%; - overflow-x: hidden; - overflow-y: auto; - outline: 0; -} - -.modal-dialog { - position: relative; - width: auto; - margin: 0.5rem; - pointer-events: none; -} -.modal.fade .modal-dialog { - transition: transform 0.3s ease-out; - transform: translate(0, -50px); -} -@media (prefers-reduced-motion: reduce) { - .modal.fade .modal-dialog { - transition: none; - } -} -.modal.show .modal-dialog { - transform: none; -} -.modal.modal-static .modal-dialog { - transform: scale(1.02); -} - -.modal-dialog-scrollable { - height: calc(100% - 1rem); -} -.modal-dialog-scrollable .modal-content { - max-height: 100%; - overflow: hidden; -} -.modal-dialog-scrollable .modal-body { - overflow-y: auto; -} - -.modal-dialog-centered { - display: flex; - align-items: center; - min-height: calc(100% - 1rem); -} - -.modal-content { - position: relative; - display: flex; - flex-direction: column; - width: 100%; - pointer-events: auto; - background-color: #fff; - background-clip: padding-box; - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 0.3rem; - outline: 0; -} - -.modal-backdrop { - position: fixed; - top: 0; - left: 0; - z-index: 1040; - width: 100vw; - height: 100vh; - background-color: #000; -} -.modal-backdrop.fade { - opacity: 0; -} -.modal-backdrop.show { - opacity: 0.5; -} - -.modal-header { - display: flex; - flex-shrink: 0; - align-items: center; - justify-content: space-between; - padding: 1rem 1rem; - border-bottom: 1px solid #dee2e6; - border-top-left-radius: calc(0.3rem - 1px); - border-top-right-radius: calc(0.3rem - 1px); -} -.modal-header .btn-close { - padding: 0.5rem 0.5rem; - margin: -0.5rem -0.5rem -0.5rem auto; -} - -.modal-title { - margin-bottom: 0; - line-height: 1.5; -} - -.modal-body { - position: relative; - flex: 1 1 auto; - padding: 1rem; -} - -.modal-footer { - display: flex; - flex-wrap: wrap; - flex-shrink: 0; - align-items: center; - justify-content: flex-end; - padding: 0.75rem; - border-top: 1px solid #dee2e6; - border-bottom-right-radius: calc(0.3rem - 1px); - border-bottom-left-radius: calc(0.3rem - 1px); -} -.modal-footer > * { - margin: 0.25rem; -} - -@media (min-width: 576px) { - .modal-dialog { - max-width: 500px; - margin: 1.75rem auto; - } - - .modal-dialog-scrollable { - height: calc(100% - 3.5rem); - } - - .modal-dialog-centered { - min-height: calc(100% - 3.5rem); - } - - .modal-sm { - max-width: 300px; - } -} -@media (min-width: 992px) { - .modal-lg, -.modal-xl { - max-width: 800px; - } -} -@media (min-width: 1200px) { - .modal-xl { - max-width: 1140px; - } -} -.modal-fullscreen { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; -} -.modal-fullscreen .modal-content { - height: 100%; - border: 0; - border-radius: 0; -} -.modal-fullscreen .modal-header { - border-radius: 0; -} -.modal-fullscreen .modal-body { - overflow-y: auto; -} -.modal-fullscreen .modal-footer { - border-radius: 0; -} - -@media (max-width: 575.98px) { - .modal-fullscreen-sm-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; - } - .modal-fullscreen-sm-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; - } - .modal-fullscreen-sm-down .modal-header { - border-radius: 0; - } - .modal-fullscreen-sm-down .modal-body { - overflow-y: auto; - } - .modal-fullscreen-sm-down .modal-footer { - border-radius: 0; - } -} -@media (max-width: 767.98px) { - .modal-fullscreen-md-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; - } - .modal-fullscreen-md-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; - } - .modal-fullscreen-md-down .modal-header { - border-radius: 0; - } - .modal-fullscreen-md-down .modal-body { - overflow-y: auto; - } - .modal-fullscreen-md-down .modal-footer { - border-radius: 0; - } -} -@media (max-width: 991.98px) { - .modal-fullscreen-lg-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; - } - .modal-fullscreen-lg-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; - } - .modal-fullscreen-lg-down .modal-header { - border-radius: 0; - } - .modal-fullscreen-lg-down .modal-body { - overflow-y: auto; - } - .modal-fullscreen-lg-down .modal-footer { - border-radius: 0; - } -} -@media (max-width: 1199.98px) { - .modal-fullscreen-xl-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; - } - .modal-fullscreen-xl-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; - } - .modal-fullscreen-xl-down .modal-header { - border-radius: 0; - } - .modal-fullscreen-xl-down .modal-body { - overflow-y: auto; - } - .modal-fullscreen-xl-down .modal-footer { - border-radius: 0; - } -} -@media (max-width: 1399.98px) { - .modal-fullscreen-xxl-down { - width: 100vw; - max-width: none; - height: 100%; - margin: 0; - } - .modal-fullscreen-xxl-down .modal-content { - height: 100%; - border: 0; - border-radius: 0; - } - .modal-fullscreen-xxl-down .modal-header { - border-radius: 0; - } - .modal-fullscreen-xxl-down .modal-body { - overflow-y: auto; - } - .modal-fullscreen-xxl-down .modal-footer { - border-radius: 0; - } -} -.tooltip { - position: absolute; - z-index: 1080; - display: block; - margin: 0; - font-family: var(--bs-font-sans-serif); - font-style: normal; - font-weight: 400; - line-height: 1.5; - text-align: left; - text-align: start; - text-decoration: none; - text-shadow: none; - text-transform: none; - letter-spacing: normal; - word-break: normal; - word-spacing: normal; - white-space: normal; - line-break: auto; - font-size: 0.875rem; - word-wrap: break-word; - opacity: 0; -} -.tooltip.show { - opacity: 0.9; -} -.tooltip .tooltip-arrow { - position: absolute; - display: block; - width: 0.8rem; - height: 0.4rem; -} -.tooltip .tooltip-arrow::before { - position: absolute; - content: ""; - border-color: transparent; - border-style: solid; -} - -.bs-tooltip-top, .bs-tooltip-auto[data-popper-placement^=top] { - padding: 0.4rem 0; -} -.bs-tooltip-top .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow { - bottom: 0; -} -.bs-tooltip-top .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before { - top: -1px; - border-width: 0.4rem 0.4rem 0; - border-top-color: #000; -} - -.bs-tooltip-end, .bs-tooltip-auto[data-popper-placement^=right] { - padding: 0 0.4rem; -} -.bs-tooltip-end .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow { - left: 0; - width: 0.4rem; - height: 0.8rem; -} -.bs-tooltip-end .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before { - right: -1px; - border-width: 0.4rem 0.4rem 0.4rem 0; - border-right-color: #000; -} - -.bs-tooltip-bottom, .bs-tooltip-auto[data-popper-placement^=bottom] { - padding: 0.4rem 0; -} -.bs-tooltip-bottom .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow { - top: 0; -} -.bs-tooltip-bottom .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before { - bottom: -1px; - border-width: 0 0.4rem 0.4rem; - border-bottom-color: #000; -} - -.bs-tooltip-start, .bs-tooltip-auto[data-popper-placement^=left] { - padding: 0 0.4rem; -} -.bs-tooltip-start .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow { - right: 0; - width: 0.4rem; - height: 0.8rem; -} -.bs-tooltip-start .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before { - left: -1px; - border-width: 0.4rem 0 0.4rem 0.4rem; - border-left-color: #000; -} - -.tooltip-inner { - max-width: 200px; - padding: 0.25rem 0.5rem; - color: #fff; - text-align: center; - background-color: #000; - border-radius: 0.25rem; -} - -.popover { - position: absolute; - top: 0; - left: 0 /* rtl:ignore */; - z-index: 1070; - display: block; - max-width: 276px; - font-family: var(--bs-font-sans-serif); - font-style: normal; - font-weight: 400; - line-height: 1.5; - text-align: left; - text-align: start; - text-decoration: none; - text-shadow: none; - text-transform: none; - letter-spacing: normal; - word-break: normal; - word-spacing: normal; - white-space: normal; - line-break: auto; - font-size: 0.875rem; - word-wrap: break-word; - background-color: #fff; - background-clip: padding-box; - border: 1px solid rgba(0, 0, 0, 0.2); - border-radius: 0.3rem; -} -.popover .popover-arrow { - position: absolute; - display: block; - width: 1rem; - height: 0.5rem; -} -.popover .popover-arrow::before, .popover .popover-arrow::after { - position: absolute; - display: block; - content: ""; - border-color: transparent; - border-style: solid; -} - -.bs-popover-top > .popover-arrow, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow { - bottom: calc(-0.5rem - 1px); -} -.bs-popover-top > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::before { - bottom: 0; - border-width: 0.5rem 0.5rem 0; - border-top-color: rgba(0, 0, 0, 0.25); -} -.bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::after { - bottom: 1px; - border-width: 0.5rem 0.5rem 0; - border-top-color: #fff; -} - -.bs-popover-end > .popover-arrow, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow { - left: calc(-0.5rem - 1px); - width: 0.5rem; - height: 1rem; -} -.bs-popover-end > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::before { - left: 0; - border-width: 0.5rem 0.5rem 0.5rem 0; - border-right-color: rgba(0, 0, 0, 0.25); -} -.bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::after { - left: 1px; - border-width: 0.5rem 0.5rem 0.5rem 0; - border-right-color: #fff; -} - -.bs-popover-bottom > .popover-arrow, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow { - top: calc(-0.5rem - 1px); -} -.bs-popover-bottom > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::before { - top: 0; - border-width: 0 0.5rem 0.5rem 0.5rem; - border-bottom-color: rgba(0, 0, 0, 0.25); -} -.bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::after { - top: 1px; - border-width: 0 0.5rem 0.5rem 0.5rem; - border-bottom-color: #fff; -} -.bs-popover-bottom .popover-header::before, .bs-popover-auto[data-popper-placement^=bottom] .popover-header::before { - position: absolute; - top: 0; - left: 50%; - display: block; - width: 1rem; - margin-left: -0.5rem; - content: ""; - border-bottom: 1px solid #f0f0f0; -} - -.bs-popover-start > .popover-arrow, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow { - right: calc(-0.5rem - 1px); - width: 0.5rem; - height: 1rem; -} -.bs-popover-start > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::before { - right: 0; - border-width: 0.5rem 0 0.5rem 0.5rem; - border-left-color: rgba(0, 0, 0, 0.25); -} -.bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::after { - right: 1px; - border-width: 0.5rem 0 0.5rem 0.5rem; - border-left-color: #fff; -} - -.popover-header { - padding: 0.5rem 1rem; - margin-bottom: 0; - font-size: 1rem; - background-color: #f0f0f0; - border-bottom: 1px solid #d8d8d8; - border-top-left-radius: calc(0.3rem - 1px); - border-top-right-radius: calc(0.3rem - 1px); -} -.popover-header:empty { - display: none; -} - -.popover-body { - padding: 1rem 1rem; - color: #212529; -} - -.carousel { - position: relative; -} - -.carousel.pointer-event { - touch-action: pan-y; -} - -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} -.carousel-inner::after { - display: block; - clear: both; - content: ""; -} - -.carousel-item { - position: relative; - display: none; - float: left; - width: 100%; - margin-right: -100%; - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - transition: transform 0.6s ease-in-out; -} -@media (prefers-reduced-motion: reduce) { - .carousel-item { - transition: none; - } -} - -.carousel-item.active, -.carousel-item-next, -.carousel-item-prev { - display: block; -} - -/* rtl:begin:ignore */ -.carousel-item-next:not(.carousel-item-start), -.active.carousel-item-end { - transform: translateX(100%); -} - -.carousel-item-prev:not(.carousel-item-end), -.active.carousel-item-start { - transform: translateX(-100%); -} - -/* rtl:end:ignore */ -.carousel-fade .carousel-item { - opacity: 0; - transition-property: opacity; - transform: none; -} -.carousel-fade .carousel-item.active, -.carousel-fade .carousel-item-next.carousel-item-start, -.carousel-fade .carousel-item-prev.carousel-item-end { - z-index: 1; - opacity: 1; -} -.carousel-fade .active.carousel-item-start, -.carousel-fade .active.carousel-item-end { - z-index: 0; - opacity: 0; - transition: opacity 0s 0.6s; -} -@media (prefers-reduced-motion: reduce) { - .carousel-fade .active.carousel-item-start, -.carousel-fade .active.carousel-item-end { - transition: none; - } -} - -.carousel-control-prev, -.carousel-control-next { - position: absolute; - top: 0; - bottom: 0; - z-index: 1; - display: flex; - align-items: center; - justify-content: center; - width: 15%; - padding: 0; - color: #fff; - text-align: center; - background: none; - border: 0; - opacity: 0.5; - transition: opacity 0.15s ease; -} -@media (prefers-reduced-motion: reduce) { - .carousel-control-prev, -.carousel-control-next { - transition: none; - } -} -.carousel-control-prev:hover, .carousel-control-prev:focus, -.carousel-control-next:hover, -.carousel-control-next:focus { - color: #fff; - text-decoration: none; - outline: 0; - opacity: 0.9; -} - -.carousel-control-prev { - left: 0; -} - -.carousel-control-next { - right: 0; -} - -.carousel-control-prev-icon, -.carousel-control-next-icon { - display: inline-block; - width: 2rem; - height: 2rem; - background-repeat: no-repeat; - background-position: 50%; - background-size: 100% 100%; -} - -/* rtl:options: { - "autoRename": true, - "stringMap":[ { - "name" : "prev-next", - "search" : "prev", - "replace" : "next" - } ] -} */ -.carousel-control-prev-icon { - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e"); -} - -.carousel-control-next-icon { - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); -} - -.carousel-indicators { - position: absolute; - right: 0; - bottom: 0; - left: 0; - z-index: 2; - display: flex; - justify-content: center; - padding: 0; - margin-right: 15%; - margin-bottom: 1rem; - margin-left: 15%; - list-style: none; -} -.carousel-indicators [data-bs-target] { - box-sizing: content-box; - flex: 0 1 auto; - width: 30px; - height: 3px; - padding: 0; - margin-right: 3px; - margin-left: 3px; - text-indent: -999px; - cursor: pointer; - background-color: #fff; - background-clip: padding-box; - border: 0; - border-top: 10px solid transparent; - border-bottom: 10px solid transparent; - opacity: 0.5; - transition: opacity 0.6s ease; -} -@media (prefers-reduced-motion: reduce) { - .carousel-indicators [data-bs-target] { - transition: none; - } -} -.carousel-indicators .active { - opacity: 1; -} - -.carousel-caption { - position: absolute; - right: 15%; - bottom: 1.25rem; - left: 15%; - padding-top: 1.25rem; - padding-bottom: 1.25rem; - color: #fff; - text-align: center; -} - -.carousel-dark .carousel-control-prev-icon, -.carousel-dark .carousel-control-next-icon { - filter: invert(1) grayscale(100); -} -.carousel-dark .carousel-indicators [data-bs-target] { - background-color: #000; -} -.carousel-dark .carousel-caption { - color: #000; -} - -@-webkit-keyframes spinner-border { - to { - transform: rotate(360deg) /* rtl:ignore */; - } -} - -@keyframes spinner-border { - to { - transform: rotate(360deg) /* rtl:ignore */; - } -} -.spinner-border { - display: inline-block; - width: 2rem; - height: 2rem; - vertical-align: -0.125em; - border: 0.25em solid currentColor; - border-right-color: transparent; - border-radius: 50%; - -webkit-animation: 0.75s linear infinite spinner-border; - animation: 0.75s linear infinite spinner-border; -} - -.spinner-border-sm { - width: 1rem; - height: 1rem; - border-width: 0.2em; -} - -@-webkit-keyframes spinner-grow { - 0% { - transform: scale(0); - } - 50% { - opacity: 1; - transform: none; - } -} - -@keyframes spinner-grow { - 0% { - transform: scale(0); - } - 50% { - opacity: 1; - transform: none; - } -} -.spinner-grow { - display: inline-block; - width: 2rem; - height: 2rem; - vertical-align: -0.125em; - background-color: currentColor; - border-radius: 50%; - opacity: 0; - -webkit-animation: 0.75s linear infinite spinner-grow; - animation: 0.75s linear infinite spinner-grow; -} - -.spinner-grow-sm { - width: 1rem; - height: 1rem; -} - -@media (prefers-reduced-motion: reduce) { - .spinner-border, -.spinner-grow { - -webkit-animation-duration: 1.5s; - animation-duration: 1.5s; - } -} -.offcanvas { - position: fixed; - bottom: 0; - z-index: 1050; - display: flex; - flex-direction: column; - max-width: 100%; - visibility: hidden; - background-color: #fff; - background-clip: padding-box; - outline: 0; - transition: transform 0.3s ease-in-out; -} -@media (prefers-reduced-motion: reduce) { - .offcanvas { - transition: none; - } -} - -.offcanvas-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 1rem 1rem; -} -.offcanvas-header .btn-close { - padding: 0.5rem 0.5rem; - margin: -0.5rem -0.5rem -0.5rem auto; -} - -.offcanvas-title { - margin-bottom: 0; - line-height: 1.5; -} - -.offcanvas-body { - flex-grow: 1; - padding: 1rem 1rem; - overflow-y: auto; -} - -.offcanvas-start { - top: 0; - left: 0; - width: 400px; - border-right: 1px solid rgba(0, 0, 0, 0.2); - transform: translateX(-100%); -} - -.offcanvas-end { - top: 0; - right: 0; - width: 400px; - border-left: 1px solid rgba(0, 0, 0, 0.2); - transform: translateX(100%); -} - -.offcanvas-top { - top: 0; - right: 0; - left: 0; - height: 30vh; - max-height: 100%; - border-bottom: 1px solid rgba(0, 0, 0, 0.2); - transform: translateY(-100%); -} - -.offcanvas-bottom { - right: 0; - left: 0; - height: 30vh; - max-height: 100%; - border-top: 1px solid rgba(0, 0, 0, 0.2); - transform: translateY(100%); -} - -.offcanvas.show { - transform: none; -} - -.clearfix::after { - display: block; - clear: both; - content: ""; -} - -.link-primary { - color: #0d6efd; -} -.link-primary:hover, .link-primary:focus { - color: #0a58ca; -} - -.link-secondary { - color: #6c757d; -} -.link-secondary:hover, .link-secondary:focus { - color: #565e64; -} - -.link-success { - color: #198754; -} -.link-success:hover, .link-success:focus { - color: #146c43; -} - -.link-info { - color: #0dcaf0; -} -.link-info:hover, .link-info:focus { - color: #3dd5f3; -} - -.link-warning { - color: #ffc107; -} -.link-warning:hover, .link-warning:focus { - color: #ffcd39; -} - -.link-danger { - color: #dc3545; -} -.link-danger:hover, .link-danger:focus { - color: #b02a37; -} - -.link-light { - color: #f8f9fa; -} -.link-light:hover, .link-light:focus { - color: #f9fafb; -} - -.link-dark { - color: #212529; -} -.link-dark:hover, .link-dark:focus { - color: #1a1e21; -} - -.ratio { - position: relative; - width: 100%; -} -.ratio::before { - display: block; - padding-top: var(--bs-aspect-ratio); - content: ""; -} -.ratio > * { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} - -.ratio-1x1 { - --bs-aspect-ratio: 100%; -} - -.ratio-4x3 { - --bs-aspect-ratio: calc(3 / 4 * 100%); -} - -.ratio-16x9 { - --bs-aspect-ratio: calc(9 / 16 * 100%); -} - -.ratio-21x9 { - --bs-aspect-ratio: calc(9 / 21 * 100%); -} - -.fixed-top { - position: fixed; - top: 0; - right: 0; - left: 0; - z-index: 1030; -} - -.fixed-bottom { - position: fixed; - right: 0; - bottom: 0; - left: 0; - z-index: 1030; -} - -.sticky-top { - position: -webkit-sticky; - position: sticky; - top: 0; - z-index: 1020; -} - -@media (min-width: 576px) { - .sticky-sm-top { - position: -webkit-sticky; - position: sticky; - top: 0; - z-index: 1020; - } -} -@media (min-width: 768px) { - .sticky-md-top { - position: -webkit-sticky; - position: sticky; - top: 0; - z-index: 1020; - } -} -@media (min-width: 992px) { - .sticky-lg-top { - position: -webkit-sticky; - position: sticky; - top: 0; - z-index: 1020; - } -} -@media (min-width: 1200px) { - .sticky-xl-top { - position: -webkit-sticky; - position: sticky; - top: 0; - z-index: 1020; - } -} -@media (min-width: 1400px) { - .sticky-xxl-top { - position: -webkit-sticky; - position: sticky; - top: 0; - z-index: 1020; - } -} -.visually-hidden, -.visually-hidden-focusable:not(:focus):not(:focus-within) { - position: absolute !important; - width: 1px !important; - height: 1px !important; - padding: 0 !important; - margin: -1px !important; - overflow: hidden !important; - clip: rect(0, 0, 0, 0) !important; - white-space: nowrap !important; - border: 0 !important; -} - -.stretched-link::after { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1; - content: ""; -} - -.text-truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.align-baseline { - vertical-align: baseline !important; -} - -.align-top { - vertical-align: top !important; -} - -.align-middle { - vertical-align: middle !important; -} - -.align-bottom { - vertical-align: bottom !important; -} - -.align-text-bottom { - vertical-align: text-bottom !important; -} - -.align-text-top { - vertical-align: text-top !important; -} - -.float-start { - float: left !important; -} - -.float-end { - float: right !important; -} - -.float-none { - float: none !important; -} - -.overflow-auto { - overflow: auto !important; -} - -.overflow-hidden { - overflow: hidden !important; -} - -.overflow-visible { - overflow: visible !important; -} - -.overflow-scroll { - overflow: scroll !important; -} - -.d-inline { - display: inline !important; -} - -.d-inline-block { - display: inline-block !important; -} - -.d-block { - display: block !important; -} - -.d-grid { - display: grid !important; -} - -.d-table { - display: table !important; -} - -.d-table-row { - display: table-row !important; -} - -.d-table-cell { - display: table-cell !important; -} - -.d-flex { - display: flex !important; -} - -.d-inline-flex { - display: inline-flex !important; -} - -.d-none { - display: none !important; -} - -.shadow { - box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; -} - -.shadow-sm { - box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; -} - -.shadow-lg { - box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; -} - -.shadow-none { - box-shadow: none !important; -} - -.position-static { - position: static !important; -} - -.position-relative { - position: relative !important; -} - -.position-absolute { - position: absolute !important; -} - -.position-fixed { - position: fixed !important; -} - -.position-sticky { - position: -webkit-sticky !important; - position: sticky !important; -} - -.top-0 { - top: 0 !important; -} - -.top-50 { - top: 50% !important; -} - -.top-100 { - top: 100% !important; -} - -.bottom-0 { - bottom: 0 !important; -} - -.bottom-50 { - bottom: 50% !important; -} - -.bottom-100 { - bottom: 100% !important; -} - -.start-0 { - left: 0 !important; -} - -.start-50 { - left: 50% !important; -} - -.start-100 { - left: 100% !important; -} - -.end-0 { - right: 0 !important; -} - -.end-50 { - right: 50% !important; -} - -.end-100 { - right: 100% !important; -} - -.translate-middle { - transform: translate(-50%, -50%) !important; -} - -.translate-middle-x { - transform: translateX(-50%) !important; -} - -.translate-middle-y { - transform: translateY(-50%) !important; -} - -.border { - border: 1px solid #dee2e6 !important; -} - -.border-0 { - border: 0 !important; -} - -.border-top { - border-top: 1px solid #dee2e6 !important; -} - -.border-top-0 { - border-top: 0 !important; -} - -.border-end { - border-right: 1px solid #dee2e6 !important; -} - -.border-end-0 { - border-right: 0 !important; -} - -.border-bottom { - border-bottom: 1px solid #dee2e6 !important; -} - -.border-bottom-0 { - border-bottom: 0 !important; -} - -.border-start { - border-left: 1px solid #dee2e6 !important; -} - -.border-start-0 { - border-left: 0 !important; -} - -.border-primary { - border-color: #0d6efd !important; -} - -.border-secondary { - border-color: #6c757d !important; -} - -.border-success { - border-color: #198754 !important; -} - -.border-info { - border-color: #0dcaf0 !important; -} - -.border-warning { - border-color: #ffc107 !important; -} - -.border-danger { - border-color: #dc3545 !important; -} - -.border-light { - border-color: #f8f9fa !important; -} - -.border-dark { - border-color: #212529 !important; -} - -.border-white { - border-color: #fff !important; -} - -.border-1 { - border-width: 1px !important; -} - -.border-2 { - border-width: 2px !important; -} - -.border-3 { - border-width: 3px !important; -} - -.border-4 { - border-width: 4px !important; -} - -.border-5 { - border-width: 5px !important; -} - -.w-25 { - width: 25% !important; -} - -.w-50 { - width: 50% !important; -} - -.w-75 { - width: 75% !important; -} - -.w-100 { - width: 100% !important; -} - -.w-auto { - width: auto !important; -} - -.mw-100 { - max-width: 100% !important; -} - -.vw-100 { - width: 100vw !important; -} - -.min-vw-100 { - min-width: 100vw !important; -} - -.h-25 { - height: 25% !important; -} - -.h-50 { - height: 50% !important; -} - -.h-75 { - height: 75% !important; -} - -.h-100 { - height: 100% !important; -} - -.h-auto { - height: auto !important; -} - -.mh-100 { - max-height: 100% !important; -} - -.vh-100 { - height: 100vh !important; -} - -.min-vh-100 { - min-height: 100vh !important; -} - -.flex-fill { - flex: 1 1 auto !important; -} - -.flex-row { - flex-direction: row !important; -} - -.flex-column { - flex-direction: column !important; -} - -.flex-row-reverse { - flex-direction: row-reverse !important; -} - -.flex-column-reverse { - flex-direction: column-reverse !important; -} - -.flex-grow-0 { - flex-grow: 0 !important; -} - -.flex-grow-1 { - flex-grow: 1 !important; -} - -.flex-shrink-0 { - flex-shrink: 0 !important; -} - -.flex-shrink-1 { - flex-shrink: 1 !important; -} - -.flex-wrap { - flex-wrap: wrap !important; -} - -.flex-nowrap { - flex-wrap: nowrap !important; -} - -.flex-wrap-reverse { - flex-wrap: wrap-reverse !important; -} - -.gap-0 { - gap: 0 !important; -} - -.gap-1 { - gap: 0.25rem !important; -} - -.gap-2 { - gap: 0.5rem !important; -} - -.gap-3 { - gap: 1rem !important; -} - -.gap-4 { - gap: 1.5rem !important; -} - -.gap-5 { - gap: 3rem !important; -} - -.justify-content-start { - justify-content: flex-start !important; -} - -.justify-content-end { - justify-content: flex-end !important; -} - -.justify-content-center { - justify-content: center !important; -} - -.justify-content-between { - justify-content: space-between !important; -} - -.justify-content-around { - justify-content: space-around !important; -} - -.justify-content-evenly { - justify-content: space-evenly !important; -} - -.align-items-start { - align-items: flex-start !important; -} - -.align-items-end { - align-items: flex-end !important; -} - -.align-items-center { - align-items: center !important; -} - -.align-items-baseline { - align-items: baseline !important; -} - -.align-items-stretch { - align-items: stretch !important; -} - -.align-content-start { - align-content: flex-start !important; -} - -.align-content-end { - align-content: flex-end !important; -} - -.align-content-center { - align-content: center !important; -} - -.align-content-between { - align-content: space-between !important; -} - -.align-content-around { - align-content: space-around !important; -} - -.align-content-stretch { - align-content: stretch !important; -} - -.align-self-auto { - align-self: auto !important; -} - -.align-self-start { - align-self: flex-start !important; -} - -.align-self-end { - align-self: flex-end !important; -} - -.align-self-center { - align-self: center !important; -} - -.align-self-baseline { - align-self: baseline !important; -} - -.align-self-stretch { - align-self: stretch !important; -} - -.order-first { - order: -1 !important; -} - -.order-0 { - order: 0 !important; -} - -.order-1 { - order: 1 !important; -} - -.order-2 { - order: 2 !important; -} - -.order-3 { - order: 3 !important; -} - -.order-4 { - order: 4 !important; -} - -.order-5 { - order: 5 !important; -} - -.order-last { - order: 6 !important; -} - -.m-0 { - margin: 0 !important; -} - -.m-1 { - margin: 0.25rem !important; -} - -.m-2 { - margin: 0.5rem !important; -} - -.m-3 { - margin: 1rem !important; -} - -.m-4 { - margin: 1.5rem !important; -} - -.m-5 { - margin: 3rem !important; -} - -.m-auto { - margin: auto !important; -} - -.mx-0 { - margin-right: 0 !important; - margin-left: 0 !important; -} - -.mx-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; -} - -.mx-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; -} - -.mx-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; -} - -.mx-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; -} - -.mx-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; -} - -.mx-auto { - margin-right: auto !important; - margin-left: auto !important; -} - -.my-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; -} - -.my-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; -} - -.my-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; -} - -.my-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; -} - -.my-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; -} - -.my-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; -} - -.my-auto { - margin-top: auto !important; - margin-bottom: auto !important; -} - -.mt-0 { - margin-top: 0 !important; -} - -.mt-1 { - margin-top: 0.25rem !important; -} - -.mt-2 { - margin-top: 0.5rem !important; -} - -.mt-3 { - margin-top: 1rem !important; -} - -.mt-4 { - margin-top: 1.5rem !important; -} - -.mt-5 { - margin-top: 3rem !important; -} - -.mt-auto { - margin-top: auto !important; -} - -.me-0 { - margin-right: 0 !important; -} - -.me-1 { - margin-right: 0.25rem !important; -} - -.me-2 { - margin-right: 0.5rem !important; -} - -.me-3 { - margin-right: 1rem !important; -} - -.me-4 { - margin-right: 1.5rem !important; -} - -.me-5 { - margin-right: 3rem !important; -} - -.me-auto { - margin-right: auto !important; -} - -.mb-0 { - margin-bottom: 0 !important; -} - -.mb-1 { - margin-bottom: 0.25rem !important; -} - -.mb-2 { - margin-bottom: 0.5rem !important; -} - -.mb-3 { - margin-bottom: 1rem !important; -} - -.mb-4 { - margin-bottom: 1.5rem !important; -} - -.mb-5 { - margin-bottom: 3rem !important; -} - -.mb-auto { - margin-bottom: auto !important; -} - -.ms-0 { - margin-left: 0 !important; -} - -.ms-1 { - margin-left: 0.25rem !important; -} - -.ms-2 { - margin-left: 0.5rem !important; -} - -.ms-3 { - margin-left: 1rem !important; -} - -.ms-4 { - margin-left: 1.5rem !important; -} - -.ms-5 { - margin-left: 3rem !important; -} - -.ms-auto { - margin-left: auto !important; -} - -.p-0 { - padding: 0 !important; -} - -.p-1 { - padding: 0.25rem !important; -} - -.p-2 { - padding: 0.5rem !important; -} - -.p-3 { - padding: 1rem !important; -} - -.p-4 { - padding: 1.5rem !important; -} - -.p-5 { - padding: 3rem !important; -} - -.px-0 { - padding-right: 0 !important; - padding-left: 0 !important; -} - -.px-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; -} - -.px-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; -} - -.px-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; -} - -.px-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; -} - -.px-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; -} - -.py-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; -} - -.py-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; -} - -.py-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; -} - -.py-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; -} - -.py-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; -} - -.py-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; -} - -.pt-0 { - padding-top: 0 !important; -} - -.pt-1 { - padding-top: 0.25rem !important; -} - -.pt-2 { - padding-top: 0.5rem !important; -} - -.pt-3 { - padding-top: 1rem !important; -} - -.pt-4 { - padding-top: 1.5rem !important; -} - -.pt-5 { - padding-top: 3rem !important; -} - -.pe-0 { - padding-right: 0 !important; -} - -.pe-1 { - padding-right: 0.25rem !important; -} - -.pe-2 { - padding-right: 0.5rem !important; -} - -.pe-3 { - padding-right: 1rem !important; -} - -.pe-4 { - padding-right: 1.5rem !important; -} - -.pe-5 { - padding-right: 3rem !important; -} - -.pb-0 { - padding-bottom: 0 !important; -} - -.pb-1 { - padding-bottom: 0.25rem !important; -} - -.pb-2 { - padding-bottom: 0.5rem !important; -} - -.pb-3 { - padding-bottom: 1rem !important; -} - -.pb-4 { - padding-bottom: 1.5rem !important; -} - -.pb-5 { - padding-bottom: 3rem !important; -} - -.ps-0 { - padding-left: 0 !important; -} - -.ps-1 { - padding-left: 0.25rem !important; -} - -.ps-2 { - padding-left: 0.5rem !important; -} - -.ps-3 { - padding-left: 1rem !important; -} - -.ps-4 { - padding-left: 1.5rem !important; -} - -.ps-5 { - padding-left: 3rem !important; -} - -.font-monospace { - font-family: var(--bs-font-monospace) !important; -} - -.fs-1 { - font-size: calc(1.375rem + 1.5vw) !important; -} - -.fs-2 { - font-size: calc(1.325rem + 0.9vw) !important; -} - -.fs-3 { - font-size: calc(1.3rem + 0.6vw) !important; -} - -.fs-4 { - font-size: calc(1.275rem + 0.3vw) !important; -} - -.fs-5 { - font-size: 1.25rem !important; -} - -.fs-6 { - font-size: 1rem !important; -} - -.fst-italic { - font-style: italic !important; -} - -.fst-normal { - font-style: normal !important; -} - -.fw-light { - font-weight: 300 !important; -} - -.fw-lighter { - font-weight: lighter !important; -} - -.fw-normal { - font-weight: 400 !important; -} - -.fw-bold { - font-weight: 700 !important; -} - -.fw-bolder { - font-weight: bolder !important; -} - -.lh-1 { - line-height: 1 !important; -} - -.lh-sm { - line-height: 1.25 !important; -} - -.lh-base { - line-height: 1.5 !important; -} - -.lh-lg { - line-height: 2 !important; -} - -.text-start { - text-align: left !important; -} - -.text-end { - text-align: right !important; -} - -.text-center { - text-align: center !important; -} - -.text-decoration-none { - text-decoration: none !important; -} - -.text-decoration-underline { - text-decoration: underline !important; -} - -.text-decoration-line-through { - text-decoration: line-through !important; -} - -.text-lowercase { - text-transform: lowercase !important; -} - -.text-uppercase { - text-transform: uppercase !important; -} - -.text-capitalize { - text-transform: capitalize !important; -} - -.text-wrap { - white-space: normal !important; -} - -.text-nowrap { - white-space: nowrap !important; -} - -/* rtl:begin:remove */ -.text-break { - word-wrap: break-word !important; - word-break: break-word !important; -} - -/* rtl:end:remove */ -.text-primary { - color: #0d6efd !important; -} - -.text-secondary { - color: #6c757d !important; -} - -.text-success { - color: #198754 !important; -} - -.text-info { - color: #0dcaf0 !important; -} - -.text-warning { - color: #ffc107 !important; -} - -.text-danger { - color: #dc3545 !important; -} - -.text-light { - color: #f8f9fa !important; -} - -.text-dark { - color: #212529 !important; -} - -.text-white { - color: #fff !important; -} - -.text-body { - color: #212529 !important; -} - -.text-muted { - color: #6c757d !important; -} - -.text-black-50 { - color: rgba(0, 0, 0, 0.5) !important; -} - -.text-white-50 { - color: rgba(255, 255, 255, 0.5) !important; -} - -.text-reset { - color: inherit !important; -} - -.bg-primary { - background-color: #0d6efd !important; -} - -.bg-secondary { - background-color: #6c757d !important; -} - -.bg-success { - background-color: #198754 !important; -} - -.bg-info { - background-color: #0dcaf0 !important; -} - -.bg-warning { - background-color: #ffc107 !important; -} - -.bg-danger { - background-color: #dc3545 !important; -} - -.bg-light { - background-color: #f8f9fa !important; -} - -.bg-dark { - background-color: #212529 !important; -} - -.bg-body { - background-color: #fff !important; -} - -.bg-white { - background-color: #fff !important; -} - -.bg-transparent { - background-color: transparent !important; -} - -.bg-gradient { - background-image: var(--bs-gradient) !important; -} - -.user-select-all { - -webkit-user-select: all !important; - -moz-user-select: all !important; - user-select: all !important; -} - -.user-select-auto { - -webkit-user-select: auto !important; - -moz-user-select: auto !important; - user-select: auto !important; -} - -.user-select-none { - -webkit-user-select: none !important; - -moz-user-select: none !important; - user-select: none !important; -} - -.pe-none { - pointer-events: none !important; -} - -.pe-auto { - pointer-events: auto !important; -} - -.rounded { - border-radius: 0.25rem !important; -} - -.rounded-0 { - border-radius: 0 !important; -} - -.rounded-1 { - border-radius: 0.2rem !important; -} - -.rounded-2 { - border-radius: 0.25rem !important; -} - -.rounded-3 { - border-radius: 0.3rem !important; -} - -.rounded-circle { - border-radius: 50% !important; -} - -.rounded-pill { - border-radius: 50rem !important; -} - -.rounded-top { - border-top-left-radius: 0.25rem !important; - border-top-right-radius: 0.25rem !important; -} - -.rounded-end { - border-top-right-radius: 0.25rem !important; - border-bottom-right-radius: 0.25rem !important; -} - -.rounded-bottom { - border-bottom-right-radius: 0.25rem !important; - border-bottom-left-radius: 0.25rem !important; -} - -.rounded-start { - border-bottom-left-radius: 0.25rem !important; - border-top-left-radius: 0.25rem !important; -} - -.visible { - visibility: visible !important; -} - -.invisible { - visibility: hidden !important; -} - -@media (min-width: 576px) { - .float-sm-start { - float: left !important; - } - - .float-sm-end { - float: right !important; - } - - .float-sm-none { - float: none !important; - } - - .d-sm-inline { - display: inline !important; - } - - .d-sm-inline-block { - display: inline-block !important; - } - - .d-sm-block { - display: block !important; - } - - .d-sm-grid { - display: grid !important; - } - - .d-sm-table { - display: table !important; - } - - .d-sm-table-row { - display: table-row !important; - } - - .d-sm-table-cell { - display: table-cell !important; - } - - .d-sm-flex { - display: flex !important; - } - - .d-sm-inline-flex { - display: inline-flex !important; - } - - .d-sm-none { - display: none !important; - } - - .flex-sm-fill { - flex: 1 1 auto !important; - } - - .flex-sm-row { - flex-direction: row !important; - } - - .flex-sm-column { - flex-direction: column !important; - } - - .flex-sm-row-reverse { - flex-direction: row-reverse !important; - } - - .flex-sm-column-reverse { - flex-direction: column-reverse !important; - } - - .flex-sm-grow-0 { - flex-grow: 0 !important; - } - - .flex-sm-grow-1 { - flex-grow: 1 !important; - } - - .flex-sm-shrink-0 { - flex-shrink: 0 !important; - } - - .flex-sm-shrink-1 { - flex-shrink: 1 !important; - } - - .flex-sm-wrap { - flex-wrap: wrap !important; - } - - .flex-sm-nowrap { - flex-wrap: nowrap !important; - } - - .flex-sm-wrap-reverse { - flex-wrap: wrap-reverse !important; - } - - .gap-sm-0 { - gap: 0 !important; - } - - .gap-sm-1 { - gap: 0.25rem !important; - } - - .gap-sm-2 { - gap: 0.5rem !important; - } - - .gap-sm-3 { - gap: 1rem !important; - } - - .gap-sm-4 { - gap: 1.5rem !important; - } - - .gap-sm-5 { - gap: 3rem !important; - } - - .justify-content-sm-start { - justify-content: flex-start !important; - } - - .justify-content-sm-end { - justify-content: flex-end !important; - } - - .justify-content-sm-center { - justify-content: center !important; - } - - .justify-content-sm-between { - justify-content: space-between !important; - } - - .justify-content-sm-around { - justify-content: space-around !important; - } - - .justify-content-sm-evenly { - justify-content: space-evenly !important; - } - - .align-items-sm-start { - align-items: flex-start !important; - } - - .align-items-sm-end { - align-items: flex-end !important; - } - - .align-items-sm-center { - align-items: center !important; - } - - .align-items-sm-baseline { - align-items: baseline !important; - } - - .align-items-sm-stretch { - align-items: stretch !important; - } - - .align-content-sm-start { - align-content: flex-start !important; - } - - .align-content-sm-end { - align-content: flex-end !important; - } - - .align-content-sm-center { - align-content: center !important; - } - - .align-content-sm-between { - align-content: space-between !important; - } - - .align-content-sm-around { - align-content: space-around !important; - } - - .align-content-sm-stretch { - align-content: stretch !important; - } - - .align-self-sm-auto { - align-self: auto !important; - } - - .align-self-sm-start { - align-self: flex-start !important; - } - - .align-self-sm-end { - align-self: flex-end !important; - } - - .align-self-sm-center { - align-self: center !important; - } - - .align-self-sm-baseline { - align-self: baseline !important; - } - - .align-self-sm-stretch { - align-self: stretch !important; - } - - .order-sm-first { - order: -1 !important; - } - - .order-sm-0 { - order: 0 !important; - } - - .order-sm-1 { - order: 1 !important; - } - - .order-sm-2 { - order: 2 !important; - } - - .order-sm-3 { - order: 3 !important; - } - - .order-sm-4 { - order: 4 !important; - } - - .order-sm-5 { - order: 5 !important; - } - - .order-sm-last { - order: 6 !important; - } - - .m-sm-0 { - margin: 0 !important; - } - - .m-sm-1 { - margin: 0.25rem !important; - } - - .m-sm-2 { - margin: 0.5rem !important; - } - - .m-sm-3 { - margin: 1rem !important; - } - - .m-sm-4 { - margin: 1.5rem !important; - } - - .m-sm-5 { - margin: 3rem !important; - } - - .m-sm-auto { - margin: auto !important; - } - - .mx-sm-0 { - margin-right: 0 !important; - margin-left: 0 !important; - } - - .mx-sm-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; - } - - .mx-sm-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; - } - - .mx-sm-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; - } - - .mx-sm-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; - } - - .mx-sm-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; - } - - .mx-sm-auto { - margin-right: auto !important; - margin-left: auto !important; - } - - .my-sm-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; - } - - .my-sm-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; - } - - .my-sm-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; - } - - .my-sm-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; - } - - .my-sm-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; - } - - .my-sm-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; - } - - .my-sm-auto { - margin-top: auto !important; - margin-bottom: auto !important; - } - - .mt-sm-0 { - margin-top: 0 !important; - } - - .mt-sm-1 { - margin-top: 0.25rem !important; - } - - .mt-sm-2 { - margin-top: 0.5rem !important; - } - - .mt-sm-3 { - margin-top: 1rem !important; - } - - .mt-sm-4 { - margin-top: 1.5rem !important; - } - - .mt-sm-5 { - margin-top: 3rem !important; - } - - .mt-sm-auto { - margin-top: auto !important; - } - - .me-sm-0 { - margin-right: 0 !important; - } - - .me-sm-1 { - margin-right: 0.25rem !important; - } - - .me-sm-2 { - margin-right: 0.5rem !important; - } - - .me-sm-3 { - margin-right: 1rem !important; - } - - .me-sm-4 { - margin-right: 1.5rem !important; - } - - .me-sm-5 { - margin-right: 3rem !important; - } - - .me-sm-auto { - margin-right: auto !important; - } - - .mb-sm-0 { - margin-bottom: 0 !important; - } - - .mb-sm-1 { - margin-bottom: 0.25rem !important; - } - - .mb-sm-2 { - margin-bottom: 0.5rem !important; - } - - .mb-sm-3 { - margin-bottom: 1rem !important; - } - - .mb-sm-4 { - margin-bottom: 1.5rem !important; - } - - .mb-sm-5 { - margin-bottom: 3rem !important; - } - - .mb-sm-auto { - margin-bottom: auto !important; - } - - .ms-sm-0 { - margin-left: 0 !important; - } - - .ms-sm-1 { - margin-left: 0.25rem !important; - } - - .ms-sm-2 { - margin-left: 0.5rem !important; - } - - .ms-sm-3 { - margin-left: 1rem !important; - } - - .ms-sm-4 { - margin-left: 1.5rem !important; - } - - .ms-sm-5 { - margin-left: 3rem !important; - } - - .ms-sm-auto { - margin-left: auto !important; - } - - .p-sm-0 { - padding: 0 !important; - } - - .p-sm-1 { - padding: 0.25rem !important; - } - - .p-sm-2 { - padding: 0.5rem !important; - } - - .p-sm-3 { - padding: 1rem !important; - } - - .p-sm-4 { - padding: 1.5rem !important; - } - - .p-sm-5 { - padding: 3rem !important; - } - - .px-sm-0 { - padding-right: 0 !important; - padding-left: 0 !important; - } - - .px-sm-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; - } - - .px-sm-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; - } - - .px-sm-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; - } - - .px-sm-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; - } - - .px-sm-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; - } - - .py-sm-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; - } - - .py-sm-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; - } - - .py-sm-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; - } - - .py-sm-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; - } - - .py-sm-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; - } - - .py-sm-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; - } - - .pt-sm-0 { - padding-top: 0 !important; - } - - .pt-sm-1 { - padding-top: 0.25rem !important; - } - - .pt-sm-2 { - padding-top: 0.5rem !important; - } - - .pt-sm-3 { - padding-top: 1rem !important; - } - - .pt-sm-4 { - padding-top: 1.5rem !important; - } - - .pt-sm-5 { - padding-top: 3rem !important; - } - - .pe-sm-0 { - padding-right: 0 !important; - } - - .pe-sm-1 { - padding-right: 0.25rem !important; - } - - .pe-sm-2 { - padding-right: 0.5rem !important; - } - - .pe-sm-3 { - padding-right: 1rem !important; - } - - .pe-sm-4 { - padding-right: 1.5rem !important; - } - - .pe-sm-5 { - padding-right: 3rem !important; - } - - .pb-sm-0 { - padding-bottom: 0 !important; - } - - .pb-sm-1 { - padding-bottom: 0.25rem !important; - } - - .pb-sm-2 { - padding-bottom: 0.5rem !important; - } - - .pb-sm-3 { - padding-bottom: 1rem !important; - } - - .pb-sm-4 { - padding-bottom: 1.5rem !important; - } - - .pb-sm-5 { - padding-bottom: 3rem !important; - } - - .ps-sm-0 { - padding-left: 0 !important; - } - - .ps-sm-1 { - padding-left: 0.25rem !important; - } - - .ps-sm-2 { - padding-left: 0.5rem !important; - } - - .ps-sm-3 { - padding-left: 1rem !important; - } - - .ps-sm-4 { - padding-left: 1.5rem !important; - } - - .ps-sm-5 { - padding-left: 3rem !important; - } - - .text-sm-start { - text-align: left !important; - } - - .text-sm-end { - text-align: right !important; - } - - .text-sm-center { - text-align: center !important; - } -} -@media (min-width: 768px) { - .float-md-start { - float: left !important; - } - - .float-md-end { - float: right !important; - } - - .float-md-none { - float: none !important; - } - - .d-md-inline { - display: inline !important; - } - - .d-md-inline-block { - display: inline-block !important; - } - - .d-md-block { - display: block !important; - } - - .d-md-grid { - display: grid !important; - } - - .d-md-table { - display: table !important; - } - - .d-md-table-row { - display: table-row !important; - } - - .d-md-table-cell { - display: table-cell !important; - } - - .d-md-flex { - display: flex !important; - } - - .d-md-inline-flex { - display: inline-flex !important; - } - - .d-md-none { - display: none !important; - } - - .flex-md-fill { - flex: 1 1 auto !important; - } - - .flex-md-row { - flex-direction: row !important; - } - - .flex-md-column { - flex-direction: column !important; - } - - .flex-md-row-reverse { - flex-direction: row-reverse !important; - } - - .flex-md-column-reverse { - flex-direction: column-reverse !important; - } - - .flex-md-grow-0 { - flex-grow: 0 !important; - } - - .flex-md-grow-1 { - flex-grow: 1 !important; - } - - .flex-md-shrink-0 { - flex-shrink: 0 !important; - } - - .flex-md-shrink-1 { - flex-shrink: 1 !important; - } - - .flex-md-wrap { - flex-wrap: wrap !important; - } - - .flex-md-nowrap { - flex-wrap: nowrap !important; - } - - .flex-md-wrap-reverse { - flex-wrap: wrap-reverse !important; - } - - .gap-md-0 { - gap: 0 !important; - } - - .gap-md-1 { - gap: 0.25rem !important; - } - - .gap-md-2 { - gap: 0.5rem !important; - } - - .gap-md-3 { - gap: 1rem !important; - } - - .gap-md-4 { - gap: 1.5rem !important; - } - - .gap-md-5 { - gap: 3rem !important; - } - - .justify-content-md-start { - justify-content: flex-start !important; - } - - .justify-content-md-end { - justify-content: flex-end !important; - } - - .justify-content-md-center { - justify-content: center !important; - } - - .justify-content-md-between { - justify-content: space-between !important; - } - - .justify-content-md-around { - justify-content: space-around !important; - } - - .justify-content-md-evenly { - justify-content: space-evenly !important; - } - - .align-items-md-start { - align-items: flex-start !important; - } - - .align-items-md-end { - align-items: flex-end !important; - } - - .align-items-md-center { - align-items: center !important; - } - - .align-items-md-baseline { - align-items: baseline !important; - } - - .align-items-md-stretch { - align-items: stretch !important; - } - - .align-content-md-start { - align-content: flex-start !important; - } - - .align-content-md-end { - align-content: flex-end !important; - } - - .align-content-md-center { - align-content: center !important; - } - - .align-content-md-between { - align-content: space-between !important; - } - - .align-content-md-around { - align-content: space-around !important; - } - - .align-content-md-stretch { - align-content: stretch !important; - } - - .align-self-md-auto { - align-self: auto !important; - } - - .align-self-md-start { - align-self: flex-start !important; - } - - .align-self-md-end { - align-self: flex-end !important; - } - - .align-self-md-center { - align-self: center !important; - } - - .align-self-md-baseline { - align-self: baseline !important; - } - - .align-self-md-stretch { - align-self: stretch !important; - } - - .order-md-first { - order: -1 !important; - } - - .order-md-0 { - order: 0 !important; - } - - .order-md-1 { - order: 1 !important; - } - - .order-md-2 { - order: 2 !important; - } - - .order-md-3 { - order: 3 !important; - } - - .order-md-4 { - order: 4 !important; - } - - .order-md-5 { - order: 5 !important; - } - - .order-md-last { - order: 6 !important; - } - - .m-md-0 { - margin: 0 !important; - } - - .m-md-1 { - margin: 0.25rem !important; - } - - .m-md-2 { - margin: 0.5rem !important; - } - - .m-md-3 { - margin: 1rem !important; - } - - .m-md-4 { - margin: 1.5rem !important; - } - - .m-md-5 { - margin: 3rem !important; - } - - .m-md-auto { - margin: auto !important; - } - - .mx-md-0 { - margin-right: 0 !important; - margin-left: 0 !important; - } - - .mx-md-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; - } - - .mx-md-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; - } - - .mx-md-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; - } - - .mx-md-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; - } - - .mx-md-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; - } - - .mx-md-auto { - margin-right: auto !important; - margin-left: auto !important; - } - - .my-md-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; - } - - .my-md-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; - } - - .my-md-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; - } - - .my-md-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; - } - - .my-md-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; - } - - .my-md-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; - } - - .my-md-auto { - margin-top: auto !important; - margin-bottom: auto !important; - } - - .mt-md-0 { - margin-top: 0 !important; - } - - .mt-md-1 { - margin-top: 0.25rem !important; - } - - .mt-md-2 { - margin-top: 0.5rem !important; - } - - .mt-md-3 { - margin-top: 1rem !important; - } - - .mt-md-4 { - margin-top: 1.5rem !important; - } - - .mt-md-5 { - margin-top: 3rem !important; - } - - .mt-md-auto { - margin-top: auto !important; - } - - .me-md-0 { - margin-right: 0 !important; - } - - .me-md-1 { - margin-right: 0.25rem !important; - } - - .me-md-2 { - margin-right: 0.5rem !important; - } - - .me-md-3 { - margin-right: 1rem !important; - } - - .me-md-4 { - margin-right: 1.5rem !important; - } - - .me-md-5 { - margin-right: 3rem !important; - } - - .me-md-auto { - margin-right: auto !important; - } - - .mb-md-0 { - margin-bottom: 0 !important; - } - - .mb-md-1 { - margin-bottom: 0.25rem !important; - } - - .mb-md-2 { - margin-bottom: 0.5rem !important; - } - - .mb-md-3 { - margin-bottom: 1rem !important; - } - - .mb-md-4 { - margin-bottom: 1.5rem !important; - } - - .mb-md-5 { - margin-bottom: 3rem !important; - } - - .mb-md-auto { - margin-bottom: auto !important; - } - - .ms-md-0 { - margin-left: 0 !important; - } - - .ms-md-1 { - margin-left: 0.25rem !important; - } - - .ms-md-2 { - margin-left: 0.5rem !important; - } - - .ms-md-3 { - margin-left: 1rem !important; - } - - .ms-md-4 { - margin-left: 1.5rem !important; - } - - .ms-md-5 { - margin-left: 3rem !important; - } - - .ms-md-auto { - margin-left: auto !important; - } - - .p-md-0 { - padding: 0 !important; - } - - .p-md-1 { - padding: 0.25rem !important; - } - - .p-md-2 { - padding: 0.5rem !important; - } - - .p-md-3 { - padding: 1rem !important; - } - - .p-md-4 { - padding: 1.5rem !important; - } - - .p-md-5 { - padding: 3rem !important; - } - - .px-md-0 { - padding-right: 0 !important; - padding-left: 0 !important; - } - - .px-md-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; - } - - .px-md-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; - } - - .px-md-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; - } - - .px-md-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; - } - - .px-md-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; - } - - .py-md-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; - } - - .py-md-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; - } - - .py-md-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; - } - - .py-md-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; - } - - .py-md-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; - } - - .py-md-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; - } - - .pt-md-0 { - padding-top: 0 !important; - } - - .pt-md-1 { - padding-top: 0.25rem !important; - } - - .pt-md-2 { - padding-top: 0.5rem !important; - } - - .pt-md-3 { - padding-top: 1rem !important; - } - - .pt-md-4 { - padding-top: 1.5rem !important; - } - - .pt-md-5 { - padding-top: 3rem !important; - } - - .pe-md-0 { - padding-right: 0 !important; - } - - .pe-md-1 { - padding-right: 0.25rem !important; - } - - .pe-md-2 { - padding-right: 0.5rem !important; - } - - .pe-md-3 { - padding-right: 1rem !important; - } - - .pe-md-4 { - padding-right: 1.5rem !important; - } - - .pe-md-5 { - padding-right: 3rem !important; - } - - .pb-md-0 { - padding-bottom: 0 !important; - } - - .pb-md-1 { - padding-bottom: 0.25rem !important; - } - - .pb-md-2 { - padding-bottom: 0.5rem !important; - } - - .pb-md-3 { - padding-bottom: 1rem !important; - } - - .pb-md-4 { - padding-bottom: 1.5rem !important; - } - - .pb-md-5 { - padding-bottom: 3rem !important; - } - - .ps-md-0 { - padding-left: 0 !important; - } - - .ps-md-1 { - padding-left: 0.25rem !important; - } - - .ps-md-2 { - padding-left: 0.5rem !important; - } - - .ps-md-3 { - padding-left: 1rem !important; - } - - .ps-md-4 { - padding-left: 1.5rem !important; - } - - .ps-md-5 { - padding-left: 3rem !important; - } - - .text-md-start { - text-align: left !important; - } - - .text-md-end { - text-align: right !important; - } - - .text-md-center { - text-align: center !important; - } -} -@media (min-width: 992px) { - .float-lg-start { - float: left !important; - } - - .float-lg-end { - float: right !important; - } - - .float-lg-none { - float: none !important; - } - - .d-lg-inline { - display: inline !important; - } - - .d-lg-inline-block { - display: inline-block !important; - } - - .d-lg-block { - display: block !important; - } - - .d-lg-grid { - display: grid !important; - } - - .d-lg-table { - display: table !important; - } - - .d-lg-table-row { - display: table-row !important; - } - - .d-lg-table-cell { - display: table-cell !important; - } - - .d-lg-flex { - display: flex !important; - } - - .d-lg-inline-flex { - display: inline-flex !important; - } - - .d-lg-none { - display: none !important; - } - - .flex-lg-fill { - flex: 1 1 auto !important; - } - - .flex-lg-row { - flex-direction: row !important; - } - - .flex-lg-column { - flex-direction: column !important; - } - - .flex-lg-row-reverse { - flex-direction: row-reverse !important; - } - - .flex-lg-column-reverse { - flex-direction: column-reverse !important; - } - - .flex-lg-grow-0 { - flex-grow: 0 !important; - } - - .flex-lg-grow-1 { - flex-grow: 1 !important; - } - - .flex-lg-shrink-0 { - flex-shrink: 0 !important; - } - - .flex-lg-shrink-1 { - flex-shrink: 1 !important; - } - - .flex-lg-wrap { - flex-wrap: wrap !important; - } - - .flex-lg-nowrap { - flex-wrap: nowrap !important; - } - - .flex-lg-wrap-reverse { - flex-wrap: wrap-reverse !important; - } - - .gap-lg-0 { - gap: 0 !important; - } - - .gap-lg-1 { - gap: 0.25rem !important; - } - - .gap-lg-2 { - gap: 0.5rem !important; - } - - .gap-lg-3 { - gap: 1rem !important; - } - - .gap-lg-4 { - gap: 1.5rem !important; - } - - .gap-lg-5 { - gap: 3rem !important; - } - - .justify-content-lg-start { - justify-content: flex-start !important; - } - - .justify-content-lg-end { - justify-content: flex-end !important; - } - - .justify-content-lg-center { - justify-content: center !important; - } - - .justify-content-lg-between { - justify-content: space-between !important; - } - - .justify-content-lg-around { - justify-content: space-around !important; - } - - .justify-content-lg-evenly { - justify-content: space-evenly !important; - } - - .align-items-lg-start { - align-items: flex-start !important; - } - - .align-items-lg-end { - align-items: flex-end !important; - } - - .align-items-lg-center { - align-items: center !important; - } - - .align-items-lg-baseline { - align-items: baseline !important; - } - - .align-items-lg-stretch { - align-items: stretch !important; - } - - .align-content-lg-start { - align-content: flex-start !important; - } - - .align-content-lg-end { - align-content: flex-end !important; - } - - .align-content-lg-center { - align-content: center !important; - } - - .align-content-lg-between { - align-content: space-between !important; - } - - .align-content-lg-around { - align-content: space-around !important; - } - - .align-content-lg-stretch { - align-content: stretch !important; - } - - .align-self-lg-auto { - align-self: auto !important; - } - - .align-self-lg-start { - align-self: flex-start !important; - } - - .align-self-lg-end { - align-self: flex-end !important; - } - - .align-self-lg-center { - align-self: center !important; - } - - .align-self-lg-baseline { - align-self: baseline !important; - } - - .align-self-lg-stretch { - align-self: stretch !important; - } - - .order-lg-first { - order: -1 !important; - } - - .order-lg-0 { - order: 0 !important; - } - - .order-lg-1 { - order: 1 !important; - } - - .order-lg-2 { - order: 2 !important; - } - - .order-lg-3 { - order: 3 !important; - } - - .order-lg-4 { - order: 4 !important; - } - - .order-lg-5 { - order: 5 !important; - } - - .order-lg-last { - order: 6 !important; - } - - .m-lg-0 { - margin: 0 !important; - } - - .m-lg-1 { - margin: 0.25rem !important; - } - - .m-lg-2 { - margin: 0.5rem !important; - } - - .m-lg-3 { - margin: 1rem !important; - } - - .m-lg-4 { - margin: 1.5rem !important; - } - - .m-lg-5 { - margin: 3rem !important; - } - - .m-lg-auto { - margin: auto !important; - } - - .mx-lg-0 { - margin-right: 0 !important; - margin-left: 0 !important; - } - - .mx-lg-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; - } - - .mx-lg-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; - } - - .mx-lg-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; - } - - .mx-lg-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; - } - - .mx-lg-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; - } - - .mx-lg-auto { - margin-right: auto !important; - margin-left: auto !important; - } - - .my-lg-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; - } - - .my-lg-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; - } - - .my-lg-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; - } - - .my-lg-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; - } - - .my-lg-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; - } - - .my-lg-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; - } - - .my-lg-auto { - margin-top: auto !important; - margin-bottom: auto !important; - } - - .mt-lg-0 { - margin-top: 0 !important; - } - - .mt-lg-1 { - margin-top: 0.25rem !important; - } - - .mt-lg-2 { - margin-top: 0.5rem !important; - } - - .mt-lg-3 { - margin-top: 1rem !important; - } - - .mt-lg-4 { - margin-top: 1.5rem !important; - } - - .mt-lg-5 { - margin-top: 3rem !important; - } - - .mt-lg-auto { - margin-top: auto !important; - } - - .me-lg-0 { - margin-right: 0 !important; - } - - .me-lg-1 { - margin-right: 0.25rem !important; - } - - .me-lg-2 { - margin-right: 0.5rem !important; - } - - .me-lg-3 { - margin-right: 1rem !important; - } - - .me-lg-4 { - margin-right: 1.5rem !important; - } - - .me-lg-5 { - margin-right: 3rem !important; - } - - .me-lg-auto { - margin-right: auto !important; - } - - .mb-lg-0 { - margin-bottom: 0 !important; - } - - .mb-lg-1 { - margin-bottom: 0.25rem !important; - } - - .mb-lg-2 { - margin-bottom: 0.5rem !important; - } - - .mb-lg-3 { - margin-bottom: 1rem !important; - } - - .mb-lg-4 { - margin-bottom: 1.5rem !important; - } - - .mb-lg-5 { - margin-bottom: 3rem !important; - } - - .mb-lg-auto { - margin-bottom: auto !important; - } - - .ms-lg-0 { - margin-left: 0 !important; - } - - .ms-lg-1 { - margin-left: 0.25rem !important; - } - - .ms-lg-2 { - margin-left: 0.5rem !important; - } - - .ms-lg-3 { - margin-left: 1rem !important; - } - - .ms-lg-4 { - margin-left: 1.5rem !important; - } - - .ms-lg-5 { - margin-left: 3rem !important; - } - - .ms-lg-auto { - margin-left: auto !important; - } - - .p-lg-0 { - padding: 0 !important; - } - - .p-lg-1 { - padding: 0.25rem !important; - } - - .p-lg-2 { - padding: 0.5rem !important; - } - - .p-lg-3 { - padding: 1rem !important; - } - - .p-lg-4 { - padding: 1.5rem !important; - } - - .p-lg-5 { - padding: 3rem !important; - } - - .px-lg-0 { - padding-right: 0 !important; - padding-left: 0 !important; - } - - .px-lg-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; - } - - .px-lg-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; - } - - .px-lg-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; - } - - .px-lg-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; - } - - .px-lg-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; - } - - .py-lg-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; - } - - .py-lg-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; - } - - .py-lg-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; - } - - .py-lg-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; - } - - .py-lg-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; - } - - .py-lg-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; - } - - .pt-lg-0 { - padding-top: 0 !important; - } - - .pt-lg-1 { - padding-top: 0.25rem !important; - } - - .pt-lg-2 { - padding-top: 0.5rem !important; - } - - .pt-lg-3 { - padding-top: 1rem !important; - } - - .pt-lg-4 { - padding-top: 1.5rem !important; - } - - .pt-lg-5 { - padding-top: 3rem !important; - } - - .pe-lg-0 { - padding-right: 0 !important; - } - - .pe-lg-1 { - padding-right: 0.25rem !important; - } - - .pe-lg-2 { - padding-right: 0.5rem !important; - } - - .pe-lg-3 { - padding-right: 1rem !important; - } - - .pe-lg-4 { - padding-right: 1.5rem !important; - } - - .pe-lg-5 { - padding-right: 3rem !important; - } - - .pb-lg-0 { - padding-bottom: 0 !important; - } - - .pb-lg-1 { - padding-bottom: 0.25rem !important; - } - - .pb-lg-2 { - padding-bottom: 0.5rem !important; - } - - .pb-lg-3 { - padding-bottom: 1rem !important; - } - - .pb-lg-4 { - padding-bottom: 1.5rem !important; - } - - .pb-lg-5 { - padding-bottom: 3rem !important; - } - - .ps-lg-0 { - padding-left: 0 !important; - } - - .ps-lg-1 { - padding-left: 0.25rem !important; - } - - .ps-lg-2 { - padding-left: 0.5rem !important; - } - - .ps-lg-3 { - padding-left: 1rem !important; - } - - .ps-lg-4 { - padding-left: 1.5rem !important; - } - - .ps-lg-5 { - padding-left: 3rem !important; - } - - .text-lg-start { - text-align: left !important; - } - - .text-lg-end { - text-align: right !important; - } - - .text-lg-center { - text-align: center !important; - } -} -@media (min-width: 1200px) { - .float-xl-start { - float: left !important; - } - - .float-xl-end { - float: right !important; - } - - .float-xl-none { - float: none !important; - } - - .d-xl-inline { - display: inline !important; - } - - .d-xl-inline-block { - display: inline-block !important; - } - - .d-xl-block { - display: block !important; - } - - .d-xl-grid { - display: grid !important; - } - - .d-xl-table { - display: table !important; - } - - .d-xl-table-row { - display: table-row !important; - } - - .d-xl-table-cell { - display: table-cell !important; - } - - .d-xl-flex { - display: flex !important; - } - - .d-xl-inline-flex { - display: inline-flex !important; - } - - .d-xl-none { - display: none !important; - } - - .flex-xl-fill { - flex: 1 1 auto !important; - } - - .flex-xl-row { - flex-direction: row !important; - } - - .flex-xl-column { - flex-direction: column !important; - } - - .flex-xl-row-reverse { - flex-direction: row-reverse !important; - } - - .flex-xl-column-reverse { - flex-direction: column-reverse !important; - } - - .flex-xl-grow-0 { - flex-grow: 0 !important; - } - - .flex-xl-grow-1 { - flex-grow: 1 !important; - } - - .flex-xl-shrink-0 { - flex-shrink: 0 !important; - } - - .flex-xl-shrink-1 { - flex-shrink: 1 !important; - } - - .flex-xl-wrap { - flex-wrap: wrap !important; - } - - .flex-xl-nowrap { - flex-wrap: nowrap !important; - } - - .flex-xl-wrap-reverse { - flex-wrap: wrap-reverse !important; - } - - .gap-xl-0 { - gap: 0 !important; - } - - .gap-xl-1 { - gap: 0.25rem !important; - } - - .gap-xl-2 { - gap: 0.5rem !important; - } - - .gap-xl-3 { - gap: 1rem !important; - } - - .gap-xl-4 { - gap: 1.5rem !important; - } - - .gap-xl-5 { - gap: 3rem !important; - } - - .justify-content-xl-start { - justify-content: flex-start !important; - } - - .justify-content-xl-end { - justify-content: flex-end !important; - } - - .justify-content-xl-center { - justify-content: center !important; - } - - .justify-content-xl-between { - justify-content: space-between !important; - } - - .justify-content-xl-around { - justify-content: space-around !important; - } - - .justify-content-xl-evenly { - justify-content: space-evenly !important; - } - - .align-items-xl-start { - align-items: flex-start !important; - } - - .align-items-xl-end { - align-items: flex-end !important; - } - - .align-items-xl-center { - align-items: center !important; - } - - .align-items-xl-baseline { - align-items: baseline !important; - } - - .align-items-xl-stretch { - align-items: stretch !important; - } - - .align-content-xl-start { - align-content: flex-start !important; - } - - .align-content-xl-end { - align-content: flex-end !important; - } - - .align-content-xl-center { - align-content: center !important; - } - - .align-content-xl-between { - align-content: space-between !important; - } - - .align-content-xl-around { - align-content: space-around !important; - } - - .align-content-xl-stretch { - align-content: stretch !important; - } - - .align-self-xl-auto { - align-self: auto !important; - } - - .align-self-xl-start { - align-self: flex-start !important; - } - - .align-self-xl-end { - align-self: flex-end !important; - } - - .align-self-xl-center { - align-self: center !important; - } - - .align-self-xl-baseline { - align-self: baseline !important; - } - - .align-self-xl-stretch { - align-self: stretch !important; - } - - .order-xl-first { - order: -1 !important; - } - - .order-xl-0 { - order: 0 !important; - } - - .order-xl-1 { - order: 1 !important; - } - - .order-xl-2 { - order: 2 !important; - } - - .order-xl-3 { - order: 3 !important; - } - - .order-xl-4 { - order: 4 !important; - } - - .order-xl-5 { - order: 5 !important; - } - - .order-xl-last { - order: 6 !important; - } - - .m-xl-0 { - margin: 0 !important; - } - - .m-xl-1 { - margin: 0.25rem !important; - } - - .m-xl-2 { - margin: 0.5rem !important; - } - - .m-xl-3 { - margin: 1rem !important; - } - - .m-xl-4 { - margin: 1.5rem !important; - } - - .m-xl-5 { - margin: 3rem !important; - } - - .m-xl-auto { - margin: auto !important; - } - - .mx-xl-0 { - margin-right: 0 !important; - margin-left: 0 !important; - } - - .mx-xl-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; - } - - .mx-xl-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; - } - - .mx-xl-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; - } - - .mx-xl-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; - } - - .mx-xl-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; - } - - .mx-xl-auto { - margin-right: auto !important; - margin-left: auto !important; - } - - .my-xl-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; - } - - .my-xl-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; - } - - .my-xl-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; - } - - .my-xl-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; - } - - .my-xl-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; - } - - .my-xl-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; - } - - .my-xl-auto { - margin-top: auto !important; - margin-bottom: auto !important; - } - - .mt-xl-0 { - margin-top: 0 !important; - } - - .mt-xl-1 { - margin-top: 0.25rem !important; - } - - .mt-xl-2 { - margin-top: 0.5rem !important; - } - - .mt-xl-3 { - margin-top: 1rem !important; - } - - .mt-xl-4 { - margin-top: 1.5rem !important; - } - - .mt-xl-5 { - margin-top: 3rem !important; - } - - .mt-xl-auto { - margin-top: auto !important; - } - - .me-xl-0 { - margin-right: 0 !important; - } - - .me-xl-1 { - margin-right: 0.25rem !important; - } - - .me-xl-2 { - margin-right: 0.5rem !important; - } - - .me-xl-3 { - margin-right: 1rem !important; - } - - .me-xl-4 { - margin-right: 1.5rem !important; - } - - .me-xl-5 { - margin-right: 3rem !important; - } - - .me-xl-auto { - margin-right: auto !important; - } - - .mb-xl-0 { - margin-bottom: 0 !important; - } - - .mb-xl-1 { - margin-bottom: 0.25rem !important; - } - - .mb-xl-2 { - margin-bottom: 0.5rem !important; - } - - .mb-xl-3 { - margin-bottom: 1rem !important; - } - - .mb-xl-4 { - margin-bottom: 1.5rem !important; - } - - .mb-xl-5 { - margin-bottom: 3rem !important; - } - - .mb-xl-auto { - margin-bottom: auto !important; - } - - .ms-xl-0 { - margin-left: 0 !important; - } - - .ms-xl-1 { - margin-left: 0.25rem !important; - } - - .ms-xl-2 { - margin-left: 0.5rem !important; - } - - .ms-xl-3 { - margin-left: 1rem !important; - } - - .ms-xl-4 { - margin-left: 1.5rem !important; - } - - .ms-xl-5 { - margin-left: 3rem !important; - } - - .ms-xl-auto { - margin-left: auto !important; - } - - .p-xl-0 { - padding: 0 !important; - } - - .p-xl-1 { - padding: 0.25rem !important; - } - - .p-xl-2 { - padding: 0.5rem !important; - } - - .p-xl-3 { - padding: 1rem !important; - } - - .p-xl-4 { - padding: 1.5rem !important; - } - - .p-xl-5 { - padding: 3rem !important; - } - - .px-xl-0 { - padding-right: 0 !important; - padding-left: 0 !important; - } - - .px-xl-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; - } - - .px-xl-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; - } - - .px-xl-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; - } - - .px-xl-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; - } - - .px-xl-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; - } - - .py-xl-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; - } - - .py-xl-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; - } - - .py-xl-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; - } - - .py-xl-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; - } - - .py-xl-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; - } - - .py-xl-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; - } - - .pt-xl-0 { - padding-top: 0 !important; - } - - .pt-xl-1 { - padding-top: 0.25rem !important; - } - - .pt-xl-2 { - padding-top: 0.5rem !important; - } - - .pt-xl-3 { - padding-top: 1rem !important; - } - - .pt-xl-4 { - padding-top: 1.5rem !important; - } - - .pt-xl-5 { - padding-top: 3rem !important; - } - - .pe-xl-0 { - padding-right: 0 !important; - } - - .pe-xl-1 { - padding-right: 0.25rem !important; - } - - .pe-xl-2 { - padding-right: 0.5rem !important; - } - - .pe-xl-3 { - padding-right: 1rem !important; - } - - .pe-xl-4 { - padding-right: 1.5rem !important; - } - - .pe-xl-5 { - padding-right: 3rem !important; - } - - .pb-xl-0 { - padding-bottom: 0 !important; - } - - .pb-xl-1 { - padding-bottom: 0.25rem !important; - } - - .pb-xl-2 { - padding-bottom: 0.5rem !important; - } - - .pb-xl-3 { - padding-bottom: 1rem !important; - } - - .pb-xl-4 { - padding-bottom: 1.5rem !important; - } - - .pb-xl-5 { - padding-bottom: 3rem !important; - } - - .ps-xl-0 { - padding-left: 0 !important; - } - - .ps-xl-1 { - padding-left: 0.25rem !important; - } - - .ps-xl-2 { - padding-left: 0.5rem !important; - } - - .ps-xl-3 { - padding-left: 1rem !important; - } - - .ps-xl-4 { - padding-left: 1.5rem !important; - } - - .ps-xl-5 { - padding-left: 3rem !important; - } - - .text-xl-start { - text-align: left !important; - } - - .text-xl-end { - text-align: right !important; - } - - .text-xl-center { - text-align: center !important; - } -} -@media (min-width: 1400px) { - .float-xxl-start { - float: left !important; - } - - .float-xxl-end { - float: right !important; - } - - .float-xxl-none { - float: none !important; - } - - .d-xxl-inline { - display: inline !important; - } - - .d-xxl-inline-block { - display: inline-block !important; - } - - .d-xxl-block { - display: block !important; - } - - .d-xxl-grid { - display: grid !important; - } - - .d-xxl-table { - display: table !important; - } - - .d-xxl-table-row { - display: table-row !important; - } - - .d-xxl-table-cell { - display: table-cell !important; - } - - .d-xxl-flex { - display: flex !important; - } - - .d-xxl-inline-flex { - display: inline-flex !important; - } - - .d-xxl-none { - display: none !important; - } - - .flex-xxl-fill { - flex: 1 1 auto !important; - } - - .flex-xxl-row { - flex-direction: row !important; - } - - .flex-xxl-column { - flex-direction: column !important; - } - - .flex-xxl-row-reverse { - flex-direction: row-reverse !important; - } - - .flex-xxl-column-reverse { - flex-direction: column-reverse !important; - } - - .flex-xxl-grow-0 { - flex-grow: 0 !important; - } - - .flex-xxl-grow-1 { - flex-grow: 1 !important; - } - - .flex-xxl-shrink-0 { - flex-shrink: 0 !important; - } - - .flex-xxl-shrink-1 { - flex-shrink: 1 !important; - } - - .flex-xxl-wrap { - flex-wrap: wrap !important; - } - - .flex-xxl-nowrap { - flex-wrap: nowrap !important; - } - - .flex-xxl-wrap-reverse { - flex-wrap: wrap-reverse !important; - } - - .gap-xxl-0 { - gap: 0 !important; - } - - .gap-xxl-1 { - gap: 0.25rem !important; - } - - .gap-xxl-2 { - gap: 0.5rem !important; - } - - .gap-xxl-3 { - gap: 1rem !important; - } - - .gap-xxl-4 { - gap: 1.5rem !important; - } - - .gap-xxl-5 { - gap: 3rem !important; - } - - .justify-content-xxl-start { - justify-content: flex-start !important; - } - - .justify-content-xxl-end { - justify-content: flex-end !important; - } - - .justify-content-xxl-center { - justify-content: center !important; - } - - .justify-content-xxl-between { - justify-content: space-between !important; - } - - .justify-content-xxl-around { - justify-content: space-around !important; - } - - .justify-content-xxl-evenly { - justify-content: space-evenly !important; - } - - .align-items-xxl-start { - align-items: flex-start !important; - } - - .align-items-xxl-end { - align-items: flex-end !important; - } - - .align-items-xxl-center { - align-items: center !important; - } - - .align-items-xxl-baseline { - align-items: baseline !important; - } - - .align-items-xxl-stretch { - align-items: stretch !important; - } - - .align-content-xxl-start { - align-content: flex-start !important; - } - - .align-content-xxl-end { - align-content: flex-end !important; - } - - .align-content-xxl-center { - align-content: center !important; - } - - .align-content-xxl-between { - align-content: space-between !important; - } - - .align-content-xxl-around { - align-content: space-around !important; - } - - .align-content-xxl-stretch { - align-content: stretch !important; - } - - .align-self-xxl-auto { - align-self: auto !important; - } - - .align-self-xxl-start { - align-self: flex-start !important; - } - - .align-self-xxl-end { - align-self: flex-end !important; - } - - .align-self-xxl-center { - align-self: center !important; - } - - .align-self-xxl-baseline { - align-self: baseline !important; - } - - .align-self-xxl-stretch { - align-self: stretch !important; - } - - .order-xxl-first { - order: -1 !important; - } - - .order-xxl-0 { - order: 0 !important; - } - - .order-xxl-1 { - order: 1 !important; - } - - .order-xxl-2 { - order: 2 !important; - } - - .order-xxl-3 { - order: 3 !important; - } - - .order-xxl-4 { - order: 4 !important; - } - - .order-xxl-5 { - order: 5 !important; - } - - .order-xxl-last { - order: 6 !important; - } - - .m-xxl-0 { - margin: 0 !important; - } - - .m-xxl-1 { - margin: 0.25rem !important; - } - - .m-xxl-2 { - margin: 0.5rem !important; - } - - .m-xxl-3 { - margin: 1rem !important; - } - - .m-xxl-4 { - margin: 1.5rem !important; - } - - .m-xxl-5 { - margin: 3rem !important; - } - - .m-xxl-auto { - margin: auto !important; - } - - .mx-xxl-0 { - margin-right: 0 !important; - margin-left: 0 !important; - } - - .mx-xxl-1 { - margin-right: 0.25rem !important; - margin-left: 0.25rem !important; - } - - .mx-xxl-2 { - margin-right: 0.5rem !important; - margin-left: 0.5rem !important; - } - - .mx-xxl-3 { - margin-right: 1rem !important; - margin-left: 1rem !important; - } - - .mx-xxl-4 { - margin-right: 1.5rem !important; - margin-left: 1.5rem !important; - } - - .mx-xxl-5 { - margin-right: 3rem !important; - margin-left: 3rem !important; - } - - .mx-xxl-auto { - margin-right: auto !important; - margin-left: auto !important; - } - - .my-xxl-0 { - margin-top: 0 !important; - margin-bottom: 0 !important; - } - - .my-xxl-1 { - margin-top: 0.25rem !important; - margin-bottom: 0.25rem !important; - } - - .my-xxl-2 { - margin-top: 0.5rem !important; - margin-bottom: 0.5rem !important; - } - - .my-xxl-3 { - margin-top: 1rem !important; - margin-bottom: 1rem !important; - } - - .my-xxl-4 { - margin-top: 1.5rem !important; - margin-bottom: 1.5rem !important; - } - - .my-xxl-5 { - margin-top: 3rem !important; - margin-bottom: 3rem !important; - } - - .my-xxl-auto { - margin-top: auto !important; - margin-bottom: auto !important; - } - - .mt-xxl-0 { - margin-top: 0 !important; - } - - .mt-xxl-1 { - margin-top: 0.25rem !important; - } - - .mt-xxl-2 { - margin-top: 0.5rem !important; - } - - .mt-xxl-3 { - margin-top: 1rem !important; - } - - .mt-xxl-4 { - margin-top: 1.5rem !important; - } - - .mt-xxl-5 { - margin-top: 3rem !important; - } - - .mt-xxl-auto { - margin-top: auto !important; - } - - .me-xxl-0 { - margin-right: 0 !important; - } - - .me-xxl-1 { - margin-right: 0.25rem !important; - } - - .me-xxl-2 { - margin-right: 0.5rem !important; - } - - .me-xxl-3 { - margin-right: 1rem !important; - } - - .me-xxl-4 { - margin-right: 1.5rem !important; - } - - .me-xxl-5 { - margin-right: 3rem !important; - } - - .me-xxl-auto { - margin-right: auto !important; - } - - .mb-xxl-0 { - margin-bottom: 0 !important; - } - - .mb-xxl-1 { - margin-bottom: 0.25rem !important; - } - - .mb-xxl-2 { - margin-bottom: 0.5rem !important; - } - - .mb-xxl-3 { - margin-bottom: 1rem !important; - } - - .mb-xxl-4 { - margin-bottom: 1.5rem !important; - } - - .mb-xxl-5 { - margin-bottom: 3rem !important; - } - - .mb-xxl-auto { - margin-bottom: auto !important; - } - - .ms-xxl-0 { - margin-left: 0 !important; - } - - .ms-xxl-1 { - margin-left: 0.25rem !important; - } - - .ms-xxl-2 { - margin-left: 0.5rem !important; - } - - .ms-xxl-3 { - margin-left: 1rem !important; - } - - .ms-xxl-4 { - margin-left: 1.5rem !important; - } - - .ms-xxl-5 { - margin-left: 3rem !important; - } - - .ms-xxl-auto { - margin-left: auto !important; - } - - .p-xxl-0 { - padding: 0 !important; - } - - .p-xxl-1 { - padding: 0.25rem !important; - } - - .p-xxl-2 { - padding: 0.5rem !important; - } - - .p-xxl-3 { - padding: 1rem !important; - } - - .p-xxl-4 { - padding: 1.5rem !important; - } - - .p-xxl-5 { - padding: 3rem !important; - } - - .px-xxl-0 { - padding-right: 0 !important; - padding-left: 0 !important; - } - - .px-xxl-1 { - padding-right: 0.25rem !important; - padding-left: 0.25rem !important; - } - - .px-xxl-2 { - padding-right: 0.5rem !important; - padding-left: 0.5rem !important; - } - - .px-xxl-3 { - padding-right: 1rem !important; - padding-left: 1rem !important; - } - - .px-xxl-4 { - padding-right: 1.5rem !important; - padding-left: 1.5rem !important; - } - - .px-xxl-5 { - padding-right: 3rem !important; - padding-left: 3rem !important; - } - - .py-xxl-0 { - padding-top: 0 !important; - padding-bottom: 0 !important; - } - - .py-xxl-1 { - padding-top: 0.25rem !important; - padding-bottom: 0.25rem !important; - } - - .py-xxl-2 { - padding-top: 0.5rem !important; - padding-bottom: 0.5rem !important; - } - - .py-xxl-3 { - padding-top: 1rem !important; - padding-bottom: 1rem !important; - } - - .py-xxl-4 { - padding-top: 1.5rem !important; - padding-bottom: 1.5rem !important; - } - - .py-xxl-5 { - padding-top: 3rem !important; - padding-bottom: 3rem !important; - } - - .pt-xxl-0 { - padding-top: 0 !important; - } - - .pt-xxl-1 { - padding-top: 0.25rem !important; - } - - .pt-xxl-2 { - padding-top: 0.5rem !important; - } - - .pt-xxl-3 { - padding-top: 1rem !important; - } - - .pt-xxl-4 { - padding-top: 1.5rem !important; - } - - .pt-xxl-5 { - padding-top: 3rem !important; - } - - .pe-xxl-0 { - padding-right: 0 !important; - } - - .pe-xxl-1 { - padding-right: 0.25rem !important; - } - - .pe-xxl-2 { - padding-right: 0.5rem !important; - } - - .pe-xxl-3 { - padding-right: 1rem !important; - } - - .pe-xxl-4 { - padding-right: 1.5rem !important; - } - - .pe-xxl-5 { - padding-right: 3rem !important; - } - - .pb-xxl-0 { - padding-bottom: 0 !important; - } - - .pb-xxl-1 { - padding-bottom: 0.25rem !important; - } - - .pb-xxl-2 { - padding-bottom: 0.5rem !important; - } - - .pb-xxl-3 { - padding-bottom: 1rem !important; - } - - .pb-xxl-4 { - padding-bottom: 1.5rem !important; - } - - .pb-xxl-5 { - padding-bottom: 3rem !important; - } - - .ps-xxl-0 { - padding-left: 0 !important; - } - - .ps-xxl-1 { - padding-left: 0.25rem !important; - } - - .ps-xxl-2 { - padding-left: 0.5rem !important; - } - - .ps-xxl-3 { - padding-left: 1rem !important; - } - - .ps-xxl-4 { - padding-left: 1.5rem !important; - } - - .ps-xxl-5 { - padding-left: 3rem !important; - } - - .text-xxl-start { - text-align: left !important; - } - - .text-xxl-end { - text-align: right !important; - } - - .text-xxl-center { - text-align: center !important; - } -} -@media (min-width: 1200px) { - .fs-1 { - font-size: 2.5rem !important; - } - - .fs-2 { - font-size: 2rem !important; - } - - .fs-3 { - font-size: 1.75rem !important; - } - - .fs-4 { - font-size: 1.5rem !important; - } -} -@media print { - .d-print-inline { - display: inline !important; - } - - .d-print-inline-block { - display: inline-block !important; - } - - .d-print-block { - display: block !important; - } - - .d-print-grid { - display: grid !important; - } - - .d-print-table { - display: table !important; - } - - .d-print-table-row { - display: table-row !important; - } - - .d-print-table-cell { - display: table-cell !important; - } - - .d-print-flex { - display: flex !important; - } - - .d-print-inline-flex { - display: inline-flex !important; - } - - .d-print-none { - display: none !important; - } -} - -/*# sourceMappingURL=bootstrap.css.map */ \ No newline at end of file +@charset "UTF-8"; + +:root { + --bs-blue: #0d6efd; + --bs-indigo: #6610f2; + --bs-purple: #6f42c1; + --bs-pink: #d63384; + --bs-red: #dc3545; + --bs-orange: #fd7e14; + --bs-yellow: #ffc107; + --bs-green: #198754; + --bs-teal: #20c997; + --bs-cyan: #0dcaf0; + --bs-white: #fff; + --bs-gray: #6c757d; + --bs-gray-dark: #343a40; + --bs-primary: #0d6efd; + --bs-secondary: #6c757d; + --bs-success: #198754; + --bs-info: #0dcaf0; + --bs-warning: #ffc107; + --bs-danger: #dc3545; + --bs-light: #f8f9fa; + --bs-dark: #212529; + --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); +} + +@media (prefers-reduced-motion: no-preference) { + :root { + scroll-behavior: smooth; + } +} + +.h6, .h5, .h4, .h3, .h2, .h1 { + margin-top: 0; + margin-bottom: 0.5rem; + font-weight: 500; + line-height: 1.2; +} + +.h1 { + font-size: calc(1.375rem + 1.5vw); +} +@media (min-width: 1200px) { + .h1 { + font-size: 2.5rem; + } +} + +.h2 { + font-size: calc(1.325rem + 0.9vw); +} +@media (min-width: 1200px) { + .h2 { + font-size: 2rem; + } +} + +.h3 { + font-size: calc(1.3rem + 0.6vw); +} +@media (min-width: 1200px) { + .h3 { + font-size: 1.75rem; + } +} + +.h4 { + font-size: calc(1.275rem + 0.3vw); +} +@media (min-width: 1200px) { + .h4 { + font-size: 1.5rem; + } +} + +.h5 { + font-size: 1.25rem; +} + +.h6 { + font-size: 1rem; +} + +.p { + margin-top: 0; + margin-bottom: 1rem; +} + + +abbr[title], +abbr[data-bs-original-title] { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + -webkit-text-decoration-skip-ink: none; + text-decoration-skip-ink: none; +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} + +ol, +ul { + padding-left: 2rem; +} + +ol, +ul, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +ol ol, +ul ul, +ol ul, +ul ol { + margin-bottom: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-bottom: 0.5rem; + margin-left: 0; +} + +blockquote { + margin: 0 0 1rem; +} + +b, +strong { + font-weight: bolder; +} + +small, .small { + font-size: 0.875em; +} + +mark, .mark { + padding: 0.2em; + background-color: #fcf8e3; +} + +sub, +sup { + position: relative; + font-size: 0.75em; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +a { + color: #0d6efd; + text-decoration: underline; +} +a:hover { + color: #0a58ca; +} + +a:not([href]):not([class]), a:not([href]):not([class]):hover { + color: inherit; + text-decoration: none; +} + +pre, +code, +kbd, +samp { + font-family: var(--bs-font-monospace); + font-size: 1em; + direction: ltr ; + unicode-bidi: bidi-override; +} + +pre { + display: block; + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; + font-size: 0.875em; +} +pre code { + font-size: inherit; + color: inherit; + word-break: normal; +} + +code { + font-size: 0.875em; + color: #d63384; + word-wrap: break-word; +} +a > code { + color: inherit; +} + +kbd { + padding: 0.2rem 0.4rem; + font-size: 0.875em; + color: #fff; + background-color: #212529; + border-radius: 0.2rem; +} +kbd kbd { + padding: 0; + font-size: 1em; + font-weight: 700; +} + +figure { + margin: 0 0 1rem; +} + +img, +svg { + vertical-align: middle; +} + +table { + caption-side: bottom; + border-collapse: collapse; +} + +caption { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + color: #6c757d; + text-align: left; +} + +th { + text-align: inherit; + text-align: -webkit-match-parent; +} + +thead, +tbody, +tfoot, +tr, +td, +th { + border-color: inherit; + border-style: solid; + border-width: 0; +} + +label { + display: inline-block; +} + +button { + border-radius: 0; +} + +button:focus:not(:focus-visible) { + outline: 0; +} + +input, +button, +select, +optgroup, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +select { + text-transform: none; +} + +[role=button] { + cursor: pointer; +} + +select { + word-wrap: normal; +} +select:disabled { + opacity: 1; +} + +[list]::-webkit-calendar-picker-indicator { + display: none; +} + +button, +[type=button], +[type=reset], +[type=submit] { + -webkit-appearance: button; +} +button:not(:disabled), +[type=button]:not(:disabled), +[type=reset]:not(:disabled), +[type=submit]:not(:disabled) { + cursor: pointer; +} + +::-moz-focus-inner { + padding: 0; + border-style: none; +} + +textarea { + resize: vertical; +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +legend { + float: left; + width: 100%; + padding: 0; + margin-bottom: 0.5rem; + font-size: calc(1.275rem + 0.3vw); + line-height: inherit; +} +@media (min-width: 1200px) { + legend { + font-size: 1.5rem; + } +} +legend + * { + clear: left; +} + +::-webkit-datetime-edit-fields-wrapper, +::-webkit-datetime-edit-text, +::-webkit-datetime-edit-minute, +::-webkit-datetime-edit-hour-field, +::-webkit-datetime-edit-day-field, +::-webkit-datetime-edit-month-field, +::-webkit-datetime-edit-year-field { + padding: 0; +} + +::-webkit-inner-spin-button { + height: auto; +} + +[type=search] { + outline-offset: -2px; + -webkit-appearance: textfield; +} + + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-color-swatch-wrapper { + padding: 0; +} + +::file-selector-button { + font: inherit; +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button; +} + +output { + display: inline-block; +} + +iframe { + border: 0; +} + +summary { + display: list-item; + cursor: pointer; +} + +progress { + vertical-align: baseline; +} + +[hidden] { + display: none !important; +} + +.lead { + font-size: 1.25rem; + font-weight: 300; +} + +.display-1 { + font-size: calc(1.625rem + 4.5vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-1 { + font-size: 5rem; + } +} + +.display-2 { + font-size: calc(1.575rem + 3.9vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-2 { + font-size: 4.5rem; + } +} + +.display-3 { + font-size: calc(1.525rem + 3.3vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-3 { + font-size: 4rem; + } +} + +.display-4 { + font-size: calc(1.475rem + 2.7vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-4 { + font-size: 3.5rem; + } +} + +.display-5 { + font-size: calc(1.425rem + 2.1vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-5 { + font-size: 3rem; + } +} + +.display-6 { + font-size: calc(1.375rem + 1.5vw); + font-weight: 300; + line-height: 1.2; +} +@media (min-width: 1200px) { + .display-6 { + font-size: 2.5rem; + } +} + +.list-unstyled { + padding-left: 0; + list-style: none; +} + +.list-inline { + padding-left: 0; + list-style: none; +} + +.list-inline-item { + display: inline-block; +} +.list-inline-item:not(:last-child) { + margin-right: 0.5rem; +} + +.initialism { + font-size: 0.875em; + text-transform: uppercase; +} + +.blockquote { + margin-bottom: 1rem; + font-size: 1.25rem; +} +.blockquote > :last-child { + margin-bottom: 0; +} + +.blockquote-footer { + margin-top: -1rem; + margin-bottom: 1rem; + font-size: 0.875em; + color: #6c757d; +} +.blockquote-footer::before { + content: "— "; +} + +.img-fluid { + max-width: 100%; + height: auto; +} + +.img-thumbnail { + padding: 0.25rem; + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: 0.25rem; + max-width: 100%; + height: auto; +} + +.figure { + display: inline-block; +} + +.figure-img { + margin-bottom: 0.5rem; + line-height: 1; +} + +.figure-caption { + font-size: 0.875em; + color: #6c757d; +} + +.container, +.container-fluid, +.container-xxl, +.container-xl, +.container-lg, +.container-md, +.container-sm { + width: 100%; + padding-right: var(--bs-gutter-x, 0.75rem); + padding-left: var(--bs-gutter-x, 0.75rem); + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container-sm, .container { + max-width: 540px; + } +} +@media (min-width: 768px) { + .container-md, .container-sm, .container { + max-width: 720px; + } +} +@media (min-width: 992px) { + .container-lg, .container-md, .container-sm, .container { + max-width: 960px; + } +} +@media (min-width: 1200px) { + .container-xl, .container-lg, .container-md, .container-sm, .container { + max-width: 1140px; + } +} +@media (min-width: 1400px) { + .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container { + max-width: 1320px; + } +} +.row { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + display: flex; + flex-wrap: wrap; + margin-top: calc(var(--bs-gutter-y) * -1); + margin-right: calc(var(--bs-gutter-x) / -2); + margin-left: calc(var(--bs-gutter-x) / -2); +} +.row > * { + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--bs-gutter-x) / 2); + padding-left: calc(var(--bs-gutter-x) / 2); + margin-top: var(--bs-gutter-y); +} + +.col { + flex: 1 0 0%; +} + +.row-cols-auto > * { + flex: 0 0 auto; + width: auto; +} + +.row-cols-1 > * { + flex: 0 0 auto; + width: 100%; +} + +.row-cols-2 > * { + flex: 0 0 auto; + width: 50%; +} + +.row-cols-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; +} + +.row-cols-4 > * { + flex: 0 0 auto; + width: 25%; +} + +.row-cols-5 > * { + flex: 0 0 auto; + width: 20%; +} + +.row-cols-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; +} + +.col-auto { + flex: 0 0 auto; + width: auto; +} + +.col-1 { + flex: 0 0 auto; + width: 8.3333333333%; +} + +.col-2 { + flex: 0 0 auto; + width: 16.6666666667%; +} + +.col-3 { + flex: 0 0 auto; + width: 25%; +} + +.col-4 { + flex: 0 0 auto; + width: 33.3333333333%; +} + +.col-5 { + flex: 0 0 auto; + width: 41.6666666667%; +} + +.col-6 { + flex: 0 0 auto; + width: 50%; +} + +.col-7 { + flex: 0 0 auto; + width: 58.3333333333%; +} + +.col-8 { + flex: 0 0 auto; + width: 66.6666666667%; +} + +.col-9 { + flex: 0 0 auto; + width: 75%; +} + +.col-10 { + flex: 0 0 auto; + width: 83.3333333333%; +} + +.col-11 { + flex: 0 0 auto; + width: 91.6666666667%; +} + +.col-12 { + flex: 0 0 auto; + width: 100%; +} + +.offset-1 { + margin-left: 8.3333333333%; +} + +.offset-2 { + margin-left: 16.6666666667%; +} + +.offset-3 { + margin-left: 25%; +} + +.offset-4 { + margin-left: 33.3333333333%; +} + +.offset-5 { + margin-left: 41.6666666667%; +} + +.offset-6 { + margin-left: 50%; +} + +.offset-7 { + margin-left: 58.3333333333%; +} + +.offset-8 { + margin-left: 66.6666666667%; +} + +.offset-9 { + margin-left: 75%; +} + +.offset-10 { + margin-left: 83.3333333333%; +} + +.offset-11 { + margin-left: 91.6666666667%; +} + +.g-0, +.gx-0 { + --bs-gutter-x: 0; +} + +.g-0, +.gy-0 { + --bs-gutter-y: 0; +} + +.g-1, +.gx-1 { + --bs-gutter-x: 0.25rem; +} + +.g-1, +.gy-1 { + --bs-gutter-y: 0.25rem; +} + +.g-2, +.gx-2 { + --bs-gutter-x: 0.5rem; +} + +.g-2, +.gy-2 { + --bs-gutter-y: 0.5rem; +} + +.g-3, +.gx-3 { + --bs-gutter-x: 1rem; +} + +.g-3, +.gy-3 { + --bs-gutter-y: 1rem; +} + +.g-4, +.gx-4 { + --bs-gutter-x: 1.5rem; +} + +.g-4, +.gy-4 { + --bs-gutter-y: 1.5rem; +} + +.g-5, +.gx-5 { + --bs-gutter-x: 3rem; +} + +.g-5, +.gy-5 { + --bs-gutter-y: 3rem; +} + +@media (min-width: 576px) { + .col-sm { + flex: 1 0 0%; + } + + .row-cols-sm-auto > * { + flex: 0 0 auto; + width: auto; + } + + .row-cols-sm-1 > * { + flex: 0 0 auto; + width: 100%; + } + + .row-cols-sm-2 > * { + flex: 0 0 auto; + width: 50%; + } + + .row-cols-sm-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .row-cols-sm-4 > * { + flex: 0 0 auto; + width: 25%; + } + + .row-cols-sm-5 > * { + flex: 0 0 auto; + width: 20%; + } + + .row-cols-sm-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-sm-auto { + flex: 0 0 auto; + width: auto; + } + + .col-sm-1 { + flex: 0 0 auto; + width: 8.3333333333%; + } + + .col-sm-2 { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-sm-3 { + flex: 0 0 auto; + width: 25%; + } + + .col-sm-4 { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .col-sm-5 { + flex: 0 0 auto; + width: 41.6666666667%; + } + + .col-sm-6 { + flex: 0 0 auto; + width: 50%; + } + + .col-sm-7 { + flex: 0 0 auto; + width: 58.3333333333%; + } + + .col-sm-8 { + flex: 0 0 auto; + width: 66.6666666667%; + } + + .col-sm-9 { + flex: 0 0 auto; + width: 75%; + } + + .col-sm-10 { + flex: 0 0 auto; + width: 83.3333333333%; + } + + .col-sm-11 { + flex: 0 0 auto; + width: 91.6666666667%; + } + + .col-sm-12 { + flex: 0 0 auto; + width: 100%; + } + + .offset-sm-0 { + margin-left: 0; + } + + .offset-sm-1 { + margin-left: 8.3333333333%; + } + + .offset-sm-2 { + margin-left: 16.6666666667%; + } + + .offset-sm-3 { + margin-left: 25%; + } + + .offset-sm-4 { + margin-left: 33.3333333333%; + } + + .offset-sm-5 { + margin-left: 41.6666666667%; + } + + .offset-sm-6 { + margin-left: 50%; + } + + .offset-sm-7 { + margin-left: 58.3333333333%; + } + + .offset-sm-8 { + margin-left: 66.6666666667%; + } + + .offset-sm-9 { + margin-left: 75%; + } + + .offset-sm-10 { + margin-left: 83.3333333333%; + } + + .offset-sm-11 { + margin-left: 91.6666666667%; + } + + .g-sm-0, +.gx-sm-0 { + --bs-gutter-x: 0; + } + + .g-sm-0, +.gy-sm-0 { + --bs-gutter-y: 0; + } + + .g-sm-1, +.gx-sm-1 { + --bs-gutter-x: 0.25rem; + } + + .g-sm-1, +.gy-sm-1 { + --bs-gutter-y: 0.25rem; + } + + .g-sm-2, +.gx-sm-2 { + --bs-gutter-x: 0.5rem; + } + + .g-sm-2, +.gy-sm-2 { + --bs-gutter-y: 0.5rem; + } + + .g-sm-3, +.gx-sm-3 { + --bs-gutter-x: 1rem; + } + + .g-sm-3, +.gy-sm-3 { + --bs-gutter-y: 1rem; + } + + .g-sm-4, +.gx-sm-4 { + --bs-gutter-x: 1.5rem; + } + + .g-sm-4, +.gy-sm-4 { + --bs-gutter-y: 1.5rem; + } + + .g-sm-5, +.gx-sm-5 { + --bs-gutter-x: 3rem; + } + + .g-sm-5, +.gy-sm-5 { + --bs-gutter-y: 3rem; + } +} +@media (min-width: 768px) { + .col-md { + flex: 1 0 0%; + } + + .row-cols-md-auto > * { + flex: 0 0 auto; + width: auto; + } + + .row-cols-md-1 > * { + flex: 0 0 auto; + width: 100%; + } + + .row-cols-md-2 > * { + flex: 0 0 auto; + width: 50%; + } + + .row-cols-md-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .row-cols-md-4 > * { + flex: 0 0 auto; + width: 25%; + } + + .row-cols-md-5 > * { + flex: 0 0 auto; + width: 20%; + } + + .row-cols-md-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-md-auto { + flex: 0 0 auto; + width: auto; + } + + .col-md-1 { + flex: 0 0 auto; + width: 8.3333333333%; + } + + .col-md-2 { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-md-3 { + flex: 0 0 auto; + width: 25%; + } + + .col-md-4 { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .col-md-5 { + flex: 0 0 auto; + width: 41.6666666667%; + } + + .col-md-6 { + flex: 0 0 auto; + width: 50%; + } + + .col-md-7 { + flex: 0 0 auto; + width: 58.3333333333%; + } + + .col-md-8 { + flex: 0 0 auto; + width: 66.6666666667%; + } + + .col-md-9 { + flex: 0 0 auto; + width: 75%; + } + + .col-md-10 { + flex: 0 0 auto; + width: 83.3333333333%; + } + + .col-md-11 { + flex: 0 0 auto; + width: 91.6666666667%; + } + + .col-md-12 { + flex: 0 0 auto; + width: 100%; + } + + .offset-md-0 { + margin-left: 0; + } + + .offset-md-1 { + margin-left: 8.3333333333%; + } + + .offset-md-2 { + margin-left: 16.6666666667%; + } + + .offset-md-3 { + margin-left: 25%; + } + + .offset-md-4 { + margin-left: 33.3333333333%; + } + + .offset-md-5 { + margin-left: 41.6666666667%; + } + + .offset-md-6 { + margin-left: 50%; + } + + .offset-md-7 { + margin-left: 58.3333333333%; + } + + .offset-md-8 { + margin-left: 66.6666666667%; + } + + .offset-md-9 { + margin-left: 75%; + } + + .offset-md-10 { + margin-left: 83.3333333333%; + } + + .offset-md-11 { + margin-left: 91.6666666667%; + } + + .g-md-0, +.gx-md-0 { + --bs-gutter-x: 0; + } + + .g-md-0, +.gy-md-0 { + --bs-gutter-y: 0; + } + + .g-md-1, +.gx-md-1 { + --bs-gutter-x: 0.25rem; + } + + .g-md-1, +.gy-md-1 { + --bs-gutter-y: 0.25rem; + } + + .g-md-2, +.gx-md-2 { + --bs-gutter-x: 0.5rem; + } + + .g-md-2, +.gy-md-2 { + --bs-gutter-y: 0.5rem; + } + + .g-md-3, +.gx-md-3 { + --bs-gutter-x: 1rem; + } + + .g-md-3, +.gy-md-3 { + --bs-gutter-y: 1rem; + } + + .g-md-4, +.gx-md-4 { + --bs-gutter-x: 1.5rem; + } + + .g-md-4, +.gy-md-4 { + --bs-gutter-y: 1.5rem; + } + + .g-md-5, +.gx-md-5 { + --bs-gutter-x: 3rem; + } + + .g-md-5, +.gy-md-5 { + --bs-gutter-y: 3rem; + } +} +@media (min-width: 992px) { + .col-lg { + flex: 1 0 0%; + } + + .row-cols-lg-auto > * { + flex: 0 0 auto; + width: auto; + } + + .row-cols-lg-1 > * { + flex: 0 0 auto; + width: 100%; + } + + .row-cols-lg-2 > * { + flex: 0 0 auto; + width: 50%; + } + + .row-cols-lg-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .row-cols-lg-4 > * { + flex: 0 0 auto; + width: 25%; + } + + .row-cols-lg-5 > * { + flex: 0 0 auto; + width: 20%; + } + + .row-cols-lg-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-lg-auto { + flex: 0 0 auto; + width: auto; + } + + .col-lg-1 { + flex: 0 0 auto; + width: 8.3333333333%; + } + + .col-lg-2 { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-lg-3 { + flex: 0 0 auto; + width: 25%; + } + + .col-lg-4 { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .col-lg-5 { + flex: 0 0 auto; + width: 41.6666666667%; + } + + .col-lg-6 { + flex: 0 0 auto; + width: 50%; + } + + .col-lg-7 { + flex: 0 0 auto; + width: 58.3333333333%; + } + + .col-lg-8 { + flex: 0 0 auto; + width: 66.6666666667%; + } + + .col-lg-9 { + flex: 0 0 auto; + width: 75%; + } + + .col-lg-10 { + flex: 0 0 auto; + width: 83.3333333333%; + } + + .col-lg-11 { + flex: 0 0 auto; + width: 91.6666666667%; + } + + .col-lg-12 { + flex: 0 0 auto; + width: 100%; + } + + .offset-lg-0 { + margin-left: 0; + } + + .offset-lg-1 { + margin-left: 8.3333333333%; + } + + .offset-lg-2 { + margin-left: 16.6666666667%; + } + + .offset-lg-3 { + margin-left: 25%; + } + + .offset-lg-4 { + margin-left: 33.3333333333%; + } + + .offset-lg-5 { + margin-left: 41.6666666667%; + } + + .offset-lg-6 { + margin-left: 50%; + } + + .offset-lg-7 { + margin-left: 58.3333333333%; + } + + .offset-lg-8 { + margin-left: 66.6666666667%; + } + + .offset-lg-9 { + margin-left: 75%; + } + + .offset-lg-10 { + margin-left: 83.3333333333%; + } + + .offset-lg-11 { + margin-left: 91.6666666667%; + } + + .g-lg-0, +.gx-lg-0 { + --bs-gutter-x: 0; + } + + .g-lg-0, +.gy-lg-0 { + --bs-gutter-y: 0; + } + + .g-lg-1, +.gx-lg-1 { + --bs-gutter-x: 0.25rem; + } + + .g-lg-1, +.gy-lg-1 { + --bs-gutter-y: 0.25rem; + } + + .g-lg-2, +.gx-lg-2 { + --bs-gutter-x: 0.5rem; + } + + .g-lg-2, +.gy-lg-2 { + --bs-gutter-y: 0.5rem; + } + + .g-lg-3, +.gx-lg-3 { + --bs-gutter-x: 1rem; + } + + .g-lg-3, +.gy-lg-3 { + --bs-gutter-y: 1rem; + } + + .g-lg-4, +.gx-lg-4 { + --bs-gutter-x: 1.5rem; + } + + .g-lg-4, +.gy-lg-4 { + --bs-gutter-y: 1.5rem; + } + + .g-lg-5, +.gx-lg-5 { + --bs-gutter-x: 3rem; + } + + .g-lg-5, +.gy-lg-5 { + --bs-gutter-y: 3rem; + } +} +@media (min-width: 1200px) { + .col-xl { + flex: 1 0 0%; + } + + .row-cols-xl-auto > * { + flex: 0 0 auto; + width: auto; + } + + .row-cols-xl-1 > * { + flex: 0 0 auto; + width: 100%; + } + + .row-cols-xl-2 > * { + flex: 0 0 auto; + width: 50%; + } + + .row-cols-xl-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .row-cols-xl-4 > * { + flex: 0 0 auto; + width: 25%; + } + + .row-cols-xl-5 > * { + flex: 0 0 auto; + width: 20%; + } + + .row-cols-xl-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-xl-auto { + flex: 0 0 auto; + width: auto; + } + + .col-xl-1 { + flex: 0 0 auto; + width: 8.3333333333%; + } + + .col-xl-2 { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-xl-3 { + flex: 0 0 auto; + width: 25%; + } + + .col-xl-4 { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .col-xl-5 { + flex: 0 0 auto; + width: 41.6666666667%; + } + + .col-xl-6 { + flex: 0 0 auto; + width: 50%; + } + + .col-xl-7 { + flex: 0 0 auto; + width: 58.3333333333%; + } + + .col-xl-8 { + flex: 0 0 auto; + width: 66.6666666667%; + } + + .col-xl-9 { + flex: 0 0 auto; + width: 75%; + } + + .col-xl-10 { + flex: 0 0 auto; + width: 83.3333333333%; + } + + .col-xl-11 { + flex: 0 0 auto; + width: 91.6666666667%; + } + + .col-xl-12 { + flex: 0 0 auto; + width: 100%; + } + + .offset-xl-0 { + margin-left: 0; + } + + .offset-xl-1 { + margin-left: 8.3333333333%; + } + + .offset-xl-2 { + margin-left: 16.6666666667%; + } + + .offset-xl-3 { + margin-left: 25%; + } + + .offset-xl-4 { + margin-left: 33.3333333333%; + } + + .offset-xl-5 { + margin-left: 41.6666666667%; + } + + .offset-xl-6 { + margin-left: 50%; + } + + .offset-xl-7 { + margin-left: 58.3333333333%; + } + + .offset-xl-8 { + margin-left: 66.6666666667%; + } + + .offset-xl-9 { + margin-left: 75%; + } + + .offset-xl-10 { + margin-left: 83.3333333333%; + } + + .offset-xl-11 { + margin-left: 91.6666666667%; + } + + .g-xl-0, +.gx-xl-0 { + --bs-gutter-x: 0; + } + + .g-xl-0, +.gy-xl-0 { + --bs-gutter-y: 0; + } + + .g-xl-1, +.gx-xl-1 { + --bs-gutter-x: 0.25rem; + } + + .g-xl-1, +.gy-xl-1 { + --bs-gutter-y: 0.25rem; + } + + .g-xl-2, +.gx-xl-2 { + --bs-gutter-x: 0.5rem; + } + + .g-xl-2, +.gy-xl-2 { + --bs-gutter-y: 0.5rem; + } + + .g-xl-3, +.gx-xl-3 { + --bs-gutter-x: 1rem; + } + + .g-xl-3, +.gy-xl-3 { + --bs-gutter-y: 1rem; + } + + .g-xl-4, +.gx-xl-4 { + --bs-gutter-x: 1.5rem; + } + + .g-xl-4, +.gy-xl-4 { + --bs-gutter-y: 1.5rem; + } + + .g-xl-5, +.gx-xl-5 { + --bs-gutter-x: 3rem; + } + + .g-xl-5, +.gy-xl-5 { + --bs-gutter-y: 3rem; + } +} +@media (min-width: 1400px) { + .col-xxl { + flex: 1 0 0%; + } + + .row-cols-xxl-auto > * { + flex: 0 0 auto; + width: auto; + } + + .row-cols-xxl-1 > * { + flex: 0 0 auto; + width: 100%; + } + + .row-cols-xxl-2 > * { + flex: 0 0 auto; + width: 50%; + } + + .row-cols-xxl-3 > * { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .row-cols-xxl-4 > * { + flex: 0 0 auto; + width: 25%; + } + + .row-cols-xxl-5 > * { + flex: 0 0 auto; + width: 20%; + } + + .row-cols-xxl-6 > * { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-xxl-auto { + flex: 0 0 auto; + width: auto; + } + + .col-xxl-1 { + flex: 0 0 auto; + width: 8.3333333333%; + } + + .col-xxl-2 { + flex: 0 0 auto; + width: 16.6666666667%; + } + + .col-xxl-3 { + flex: 0 0 auto; + width: 25%; + } + + .col-xxl-4 { + flex: 0 0 auto; + width: 33.3333333333%; + } + + .col-xxl-5 { + flex: 0 0 auto; + width: 41.6666666667%; + } + + .col-xxl-6 { + flex: 0 0 auto; + width: 50%; + } + + .col-xxl-7 { + flex: 0 0 auto; + width: 58.3333333333%; + } + + .col-xxl-8 { + flex: 0 0 auto; + width: 66.6666666667%; + } + + .col-xxl-9 { + flex: 0 0 auto; + width: 75%; + } + + .col-xxl-10 { + flex: 0 0 auto; + width: 83.3333333333%; + } + + .col-xxl-11 { + flex: 0 0 auto; + width: 91.6666666667%; + } + + .col-xxl-12 { + flex: 0 0 auto; + width: 100%; + } + + .offset-xxl-0 { + margin-left: 0; + } + + .offset-xxl-1 { + margin-left: 8.3333333333%; + } + + .offset-xxl-2 { + margin-left: 16.6666666667%; + } + + .offset-xxl-3 { + margin-left: 25%; + } + + .offset-xxl-4 { + margin-left: 33.3333333333%; + } + + .offset-xxl-5 { + margin-left: 41.6666666667%; + } + + .offset-xxl-6 { + margin-left: 50%; + } + + .offset-xxl-7 { + margin-left: 58.3333333333%; + } + + .offset-xxl-8 { + margin-left: 66.6666666667%; + } + + .offset-xxl-9 { + margin-left: 75%; + } + + .offset-xxl-10 { + margin-left: 83.3333333333%; + } + + .offset-xxl-11 { + margin-left: 91.6666666667%; + } + + .g-xxl-0, +.gx-xxl-0 { + --bs-gutter-x: 0; + } + + .g-xxl-0, +.gy-xxl-0 { + --bs-gutter-y: 0; + } + + .g-xxl-1, +.gx-xxl-1 { + --bs-gutter-x: 0.25rem; + } + + .g-xxl-1, +.gy-xxl-1 { + --bs-gutter-y: 0.25rem; + } + + .g-xxl-2, +.gx-xxl-2 { + --bs-gutter-x: 0.5rem; + } + + .g-xxl-2, +.gy-xxl-2 { + --bs-gutter-y: 0.5rem; + } + + .g-xxl-3, +.gx-xxl-3 { + --bs-gutter-x: 1rem; + } + + .g-xxl-3, +.gy-xxl-3 { + --bs-gutter-y: 1rem; + } + + .g-xxl-4, +.gx-xxl-4 { + --bs-gutter-x: 1.5rem; + } + + .g-xxl-4, +.gy-xxl-4 { + --bs-gutter-y: 1.5rem; + } + + .g-xxl-5, +.gx-xxl-5 { + --bs-gutter-x: 3rem; + } + + .g-xxl-5, +.gy-xxl-5 { + --bs-gutter-y: 3rem; + } +} +.table { + --bs-table-bg: transparent; + --bs-table-accent-bg: transparent; + --bs-table-striped-color: #212529; + --bs-table-striped-bg: rgba(0, 0, 0, 0.05); + --bs-table-active-color: #212529; + --bs-table-active-bg: rgba(0, 0, 0, 0.1); + --bs-table-hover-color: #212529; + --bs-table-hover-bg: rgba(0, 0, 0, 0.075); + width: 100%; + margin-bottom: 1rem; + color: #212529; + vertical-align: top; + border-color: #dee2e6; +} +.table > :not(caption) > * > * { + padding: 0.5rem 0.5rem; + background-color: var(--bs-table-bg); + border-bottom-width: 1px; + box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg); +} +.table > tbody { + vertical-align: inherit; +} +.table > thead { + vertical-align: bottom; +} +.table > :not(:last-child) > :last-child > * { + border-bottom-color: currentColor; +} + +.caption-top { + caption-side: top; +} + +.table-sm > :not(caption) > * > * { + padding: 0.25rem 0.25rem; +} + +.table-bordered > :not(caption) > * { + border-width: 1px 0; +} +.table-bordered > :not(caption) > * > * { + border-width: 0 1px; +} + +.table-borderless > :not(caption) > * > * { + border-bottom-width: 0; +} + +.table-striped > tbody > tr:nth-of-type(odd) { + --bs-table-accent-bg: var(--bs-table-striped-bg); + color: var(--bs-table-striped-color); +} + +.table-active { + --bs-table-accent-bg: var(--bs-table-active-bg); + color: var(--bs-table-active-color); +} + +.table-hover > tbody > tr:hover { + --bs-table-accent-bg: var(--bs-table-hover-bg); + color: var(--bs-table-hover-color); +} + +.table-primary { + --bs-table-bg: #cfe2ff; + --bs-table-striped-bg: #c5d7f2; + --bs-table-striped-color: #000; + --bs-table-active-bg: #bacbe6; + --bs-table-active-color: #000; + --bs-table-hover-bg: #bfd1ec; + --bs-table-hover-color: #000; + color: #000; + border-color: #bacbe6; +} + +.table-secondary { + --bs-table-bg: #e2e3e5; + --bs-table-striped-bg: #d7d8da; + --bs-table-striped-color: #000; + --bs-table-active-bg: #cbccce; + --bs-table-active-color: #000; + --bs-table-hover-bg: #d1d2d4; + --bs-table-hover-color: #000; + color: #000; + border-color: #cbccce; +} + +.table-success { + --bs-table-bg: #d1e7dd; + --bs-table-striped-bg: #c7dbd2; + --bs-table-striped-color: #000; + --bs-table-active-bg: #bcd0c7; + --bs-table-active-color: #000; + --bs-table-hover-bg: #c1d6cc; + --bs-table-hover-color: #000; + color: #000; + border-color: #bcd0c7; +} + +.table-info { + --bs-table-bg: #cff4fc; + --bs-table-striped-bg: #c5e8ef; + --bs-table-striped-color: #000; + --bs-table-active-bg: #badce3; + --bs-table-active-color: #000; + --bs-table-hover-bg: #bfe2e9; + --bs-table-hover-color: #000; + color: #000; + border-color: #badce3; +} + +.table-warning { + --bs-table-bg: #fff3cd; + --bs-table-striped-bg: #f2e7c3; + --bs-table-striped-color: #000; + --bs-table-active-bg: #e6dbb9; + --bs-table-active-color: #000; + --bs-table-hover-bg: #ece1be; + --bs-table-hover-color: #000; + color: #000; + border-color: #e6dbb9; +} + +.table-danger { + --bs-table-bg: #f8d7da; + --bs-table-striped-bg: #eccccf; + --bs-table-striped-color: #000; + --bs-table-active-bg: #dfc2c4; + --bs-table-active-color: #000; + --bs-table-hover-bg: #e5c7ca; + --bs-table-hover-color: #000; + color: #000; + border-color: #dfc2c4; +} + +.table-light { + --bs-table-bg: #f8f9fa; + --bs-table-striped-bg: #ecedee; + --bs-table-striped-color: #000; + --bs-table-active-bg: #dfe0e1; + --bs-table-active-color: #000; + --bs-table-hover-bg: #e5e6e7; + --bs-table-hover-color: #000; + color: #000; + border-color: #dfe0e1; +} + +.table-dark { + --bs-table-bg: #212529; + --bs-table-striped-bg: #2c3034; + --bs-table-striped-color: #fff; + --bs-table-active-bg: #373b3e; + --bs-table-active-color: #fff; + --bs-table-hover-bg: #323539; + --bs-table-hover-color: #fff; + color: #fff; + border-color: #373b3e; +} + +.table-responsive { + overflow-x: auto; + -webkit-overflow-scrolling: touch; +} + +@media (max-width: 575.98px) { + .table-responsive-sm { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +@media (max-width: 767.98px) { + .table-responsive-md { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +@media (max-width: 991.98px) { + .table-responsive-lg { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +@media (max-width: 1199.98px) { + .table-responsive-xl { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +@media (max-width: 1399.98px) { + .table-responsive-xxl { + overflow-x: auto; + -webkit-overflow-scrolling: touch; + } +} +.form-label { + margin-bottom: 0.5rem; +} + +.col-form-label { + padding-top: calc(0.375rem + 1px); + padding-bottom: calc(0.375rem + 1px); + margin-bottom: 0; + font-size: inherit; + line-height: 1.5; +} + +.col-form-label-lg { + padding-top: calc(0.5rem + 1px); + padding-bottom: calc(0.5rem + 1px); + font-size: 1.25rem; +} + +.col-form-label-sm { + padding-top: calc(0.25rem + 1px); + padding-bottom: calc(0.25rem + 1px); + font-size: 0.875rem; +} + +.form-text { + margin-top: 0.25rem; + font-size: 0.875em; + color: #6c757d; +} + +.form-control { + display: block; + width: 100%; + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: 0.25rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-control { + transition: none; + } +} +.form-control[type=file] { + overflow: hidden; +} +.form-control[type=file]:not(:disabled):not([readonly]) { + cursor: pointer; +} +.form-control:focus { + color: #212529; + background-color: #fff; + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-control::-webkit-date-and-time-value { + height: 1.5em; +} +.form-control::-moz-placeholder { + color: #6c757d; + opacity: 1; +} +.form-control::placeholder { + color: #6c757d; + opacity: 1; +} +.form-control:disabled, .form-control[readonly] { + background-color: #e9ecef; + opacity: 1; +} +.form-control::file-selector-button { + padding: 0.375rem 0.75rem; + margin: -0.375rem -0.75rem; + -webkit-margin-end: 0.75rem; + margin-inline-end: 0.75rem; + color: #212529; + background-color: #e9ecef; + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: 1px; + border-radius: 0; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-control::file-selector-button { + transition: none; + } +} +.form-control:hover:not(:disabled):not([readonly])::file-selector-button { + background-color: #dde0e3; +} +.form-control::-webkit-file-upload-button { + padding: 0.375rem 0.75rem; + margin: -0.375rem -0.75rem; + -webkit-margin-end: 0.75rem; + margin-inline-end: 0.75rem; + color: #212529; + background-color: #e9ecef; + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: 1px; + border-radius: 0; + -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-control::-webkit-file-upload-button { + -webkit-transition: none; + transition: none; + } +} +.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button { + background-color: #dde0e3; +} + +.form-control-plaintext { + display: block; + width: 100%; + padding: 0.375rem 0; + margin-bottom: 0; + line-height: 1.5; + color: #212529; + background-color: transparent; + border: solid transparent; + border-width: 1px 0; +} +.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { + padding-right: 0; + padding-left: 0; +} + +.form-control-sm { + min-height: calc(1.5em + 0.5rem + 2px); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: 0.2rem; +} +.form-control-sm::file-selector-button { + padding: 0.25rem 0.5rem; + margin: -0.25rem -0.5rem; + -webkit-margin-end: 0.5rem; + margin-inline-end: 0.5rem; +} +.form-control-sm::-webkit-file-upload-button { + padding: 0.25rem 0.5rem; + margin: -0.25rem -0.5rem; + -webkit-margin-end: 0.5rem; + margin-inline-end: 0.5rem; +} + +.form-control-lg { + min-height: calc(1.5em + 1rem + 2px); + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: 0.3rem; +} +.form-control-lg::file-selector-button { + padding: 0.5rem 1rem; + margin: -0.5rem -1rem; + -webkit-margin-end: 1rem; + margin-inline-end: 1rem; +} +.form-control-lg::-webkit-file-upload-button { + padding: 0.5rem 1rem; + margin: -0.5rem -1rem; + -webkit-margin-end: 1rem; + margin-inline-end: 1rem; +} + +textarea.form-control { + min-height: calc(1.5em + 0.75rem + 2px); +} +textarea.form-control-sm { + min-height: calc(1.5em + 0.5rem + 2px); +} +textarea.form-control-lg { + min-height: calc(1.5em + 1rem + 2px); +} + +.form-control-color { + max-width: 3rem; + height: auto; + padding: 0.375rem; +} +.form-control-color:not(:disabled):not([readonly]) { + cursor: pointer; +} +.form-control-color::-moz-color-swatch { + height: 1.5em; + border-radius: 0.25rem; +} +.form-control-color::-webkit-color-swatch { + height: 1.5em; + border-radius: 0.25rem; +} + +.form-select { + display: block; + width: 100%; + padding: 0.375rem 2.25rem 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right 0.75rem center; + background-size: 16px 12px; + border: 1px solid #ced4da; + border-radius: 0.25rem; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +.form-select:focus { + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-select[multiple], .form-select[size]:not([size="1"]) { + padding-right: 0.75rem; + background-image: none; +} +.form-select:disabled { + background-color: #e9ecef; +} +.form-select:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #212529; +} + +.form-select-sm { + padding-top: 0.25rem; + padding-bottom: 0.25rem; + padding-left: 0.5rem; + font-size: 0.875rem; +} + +.form-select-lg { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + font-size: 1.25rem; +} + +.form-check { + display: block; + min-height: 1.5rem; + padding-left: 1.5em; + margin-bottom: 0.125rem; +} +.form-check .form-check-input { + float: left; + margin-left: -1.5em; +} + +.form-check-input { + width: 1em; + height: 1em; + margin-top: 0.25em; + vertical-align: top; + background-color: #fff; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + border: 1px solid rgba(0, 0, 0, 0.25); + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-print-color-adjust: exact; + color-adjust: exact; +} +.form-check-input[type=checkbox] { + border-radius: 0.25em; +} +.form-check-input[type=radio] { + border-radius: 50%; +} +.form-check-input:active { + filter: brightness(90%); +} +.form-check-input:focus { + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-check-input:checked { + background-color: #0d6efd; + border-color: #0d6efd; +} +.form-check-input:checked[type=checkbox] { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e"); +} +.form-check-input:checked[type=radio] { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e"); +} +.form-check-input[type=checkbox]:indeterminate { + background-color: #0d6efd; + border-color: #0d6efd; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e"); +} +.form-check-input:disabled { + pointer-events: none; + filter: none; + opacity: 0.5; +} +.form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label { + opacity: 0.5; +} + +.form-switch { + padding-left: 2.5em; +} +.form-switch .form-check-input { + width: 2em; + margin-left: -2.5em; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e"); + background-position: left center; + border-radius: 2em; + transition: background-position 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-switch .form-check-input { + transition: none; + } +} +.form-switch .form-check-input:focus { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e"); +} +.form-switch .form-check-input:checked { + background-position: right center; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); +} + +.form-check-inline { + display: inline-block; + margin-right: 1rem; +} + +.btn-check { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.btn-check[disabled] + .btn, .btn-check:disabled + .btn { + pointer-events: none; + filter: none; + opacity: 0.65; +} + +.form-range { + width: 100%; + height: 1.5rem; + padding: 0; + background-color: transparent; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} +.form-range:focus { + outline: 0; +} +.form-range:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-range:focus::-moz-range-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.form-range::-moz-focus-outer { + border: 0; +} +.form-range::-webkit-slider-thumb { + width: 1rem; + height: 1rem; + margin-top: -0.25rem; + background-color: #0d6efd; + border: 0; + border-radius: 1rem; + -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -webkit-appearance: none; + appearance: none; +} +@media (prefers-reduced-motion: reduce) { + .form-range::-webkit-slider-thumb { + -webkit-transition: none; + transition: none; + } +} +.form-range::-webkit-slider-thumb:active { + background-color: #b6d4fe; +} +.form-range::-webkit-slider-runnable-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem; +} +.form-range::-moz-range-thumb { + width: 1rem; + height: 1rem; + background-color: #0d6efd; + border: 0; + border-radius: 1rem; + -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -moz-appearance: none; + appearance: none; +} +@media (prefers-reduced-motion: reduce) { + .form-range::-moz-range-thumb { + -moz-transition: none; + transition: none; + } +} +.form-range::-moz-range-thumb:active { + background-color: #b6d4fe; +} +.form-range::-moz-range-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem; +} +.form-range:disabled { + pointer-events: none; +} +.form-range:disabled::-webkit-slider-thumb { + background-color: #adb5bd; +} +.form-range:disabled::-moz-range-thumb { + background-color: #adb5bd; +} + +.form-floating { + position: relative; +} +.form-floating > .form-control, +.form-floating > .form-select { + height: calc(3.5rem + 2px); + padding: 1rem 0.75rem; +} +.form-floating > label { + position: absolute; + top: 0; + left: 0; + height: 100%; + padding: 1rem 0.75rem; + pointer-events: none; + border: 1px solid transparent; + transform-origin: 0 0; + transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .form-floating > label { + transition: none; + } +} +.form-floating > .form-control::-moz-placeholder { + color: transparent; +} +.form-floating > .form-control::placeholder { + color: transparent; +} +.form-floating > .form-control:not(:-moz-placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-control:focus, .form-floating > .form-control:not(:placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-control:-webkit-autofill { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-select { + padding-top: 1.625rem; + padding-bottom: 0.625rem; +} +.form-floating > .form-control:not(:-moz-placeholder-shown) ~ label { + opacity: 0.65; + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} +.form-floating > .form-control:focus ~ label, +.form-floating > .form-control:not(:placeholder-shown) ~ label, +.form-floating > .form-select ~ label { + opacity: 0.65; + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} +.form-floating > .form-control:-webkit-autofill ~ label { + opacity: 0.65; + transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); +} + +.input-group { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: stretch; + width: 100%; +} +.input-group > .form-control, +.input-group > .form-select { + position: relative; + flex: 1 1 auto; + width: 1%; + min-width: 0; +} +.input-group > .form-control:focus, +.input-group > .form-select:focus { + z-index: 3; +} +.input-group .btn { + position: relative; + z-index: 2; +} +.input-group .btn:focus { + z-index: 3; +} + +.input-group-text { + display: flex; + align-items: center; + padding: 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: center; + white-space: nowrap; + background-color: #e9ecef; + border: 1px solid #ced4da; + border-radius: 0.25rem; +} + +.input-group-lg > .form-control, +.input-group-lg > .form-select, +.input-group-lg > .input-group-text, +.input-group-lg > .btn { + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: 0.3rem; +} + +.input-group-sm > .form-control, +.input-group-sm > .form-select, +.input-group-sm > .input-group-text, +.input-group-sm > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: 0.2rem; +} + +.input-group-lg > .form-select, +.input-group-sm > .form-select { + padding-right: 3rem; +} + +.input-group:not(.has-validation) > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu), +.input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n+3) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group.has-validation > :nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu), +.input-group.has-validation > .dropdown-toggle:nth-last-child(n+4) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { + margin-left: -1px; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.valid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 0.875em; + color: #198754; +} + +.valid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: 0.1rem; + font-size: 0.875rem; + color: #fff; + background-color: rgba(25, 135, 84, 0.9); + border-radius: 0.25rem; +} + +.was-validated :valid ~ .valid-feedback, +.was-validated :valid ~ .valid-tooltip, +.is-valid ~ .valid-feedback, +.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .form-control:valid, .form-control.is-valid { + border-color: #198754; + padding-right: calc(1.5em + 0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(0.375em + 0.1875rem) center; + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} +.was-validated .form-control:valid:focus, .form-control.is-valid:focus { + border-color: #198754; + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); +} + +.was-validated textarea.form-control:valid, textarea.form-control.is-valid { + padding-right: calc(1.5em + 0.75rem); + background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); +} + +.was-validated .form-select:valid, .form-select.is-valid { + border-color: #198754; +} +.was-validated .form-select:valid:not([multiple]):not([size]), .was-validated .form-select:valid:not([multiple])[size="1"], .form-select.is-valid:not([multiple]):not([size]), .form-select.is-valid:not([multiple])[size="1"] { + padding-right: 4.125rem; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-position: right 0.75rem center, center right 2.25rem; + background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} +.was-validated .form-select:valid:focus, .form-select.is-valid:focus { + border-color: #198754; + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); +} + +.was-validated .form-check-input:valid, .form-check-input.is-valid { + border-color: #198754; +} +.was-validated .form-check-input:valid:checked, .form-check-input.is-valid:checked { + background-color: #198754; +} +.was-validated .form-check-input:valid:focus, .form-check-input.is-valid:focus { + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); +} +.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { + color: #198754; +} + +.form-check-inline .form-check-input ~ .valid-feedback { + margin-left: 0.5em; +} + +.was-validated .input-group .form-control:valid, .input-group .form-control.is-valid, +.was-validated .input-group .form-select:valid, +.input-group .form-select.is-valid { + z-index: 1; +} +.was-validated .input-group .form-control:valid:focus, .input-group .form-control.is-valid:focus, +.was-validated .input-group .form-select:valid:focus, +.input-group .form-select.is-valid:focus { + z-index: 3; +} + +.invalid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 0.875em; + color: #dc3545; +} + +.invalid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: 0.1rem; + font-size: 0.875rem; + color: #fff; + background-color: rgba(220, 53, 69, 0.9); + border-radius: 0.25rem; +} + +.was-validated :invalid ~ .invalid-feedback, +.was-validated :invalid ~ .invalid-tooltip, +.is-invalid ~ .invalid-feedback, +.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .form-control:invalid, .form-control.is-invalid { + border-color: #dc3545; + padding-right: calc(1.5em + 0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(0.375em + 0.1875rem) center; + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} +.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); +} + +.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { + padding-right: calc(1.5em + 0.75rem); + background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); +} + +.was-validated .form-select:invalid, .form-select.is-invalid { + border-color: #dc3545; +} +.was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] { + padding-right: 4.125rem; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-position: right 0.75rem center, center right 2.25rem; + background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} +.was-validated .form-select:invalid:focus, .form-select.is-invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); +} + +.was-validated .form-check-input:invalid, .form-check-input.is-invalid { + border-color: #dc3545; +} +.was-validated .form-check-input:invalid:checked, .form-check-input.is-invalid:checked { + background-color: #dc3545; +} +.was-validated .form-check-input:invalid:focus, .form-check-input.is-invalid:focus { + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); +} +.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { + color: #dc3545; +} + +.form-check-inline .form-check-input ~ .invalid-feedback { + margin-left: 0.5em; +} + +.was-validated .input-group .form-control:invalid, .input-group .form-control.is-invalid, +.was-validated .input-group .form-select:invalid, +.input-group .form-select.is-invalid { + z-index: 2; +} +.was-validated .input-group .form-control:invalid:focus, .input-group .form-control.is-invalid:focus, +.was-validated .input-group .form-select:invalid:focus, +.input-group .form-select.is-invalid:focus { + z-index: 3; +} + +.btn { + display: inline-block; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: center; + text-decoration: none; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + background-color: transparent; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 1rem; + border-radius: 0.25rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .btn { + transition: none; + } +} +.btn:hover { + color: #212529; +} +.btn-check:focus + .btn, .btn:focus { + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} +.btn:disabled, .btn.disabled, fieldset:disabled .btn { + pointer-events: none; + opacity: 0.65; +} + +.btn-primary { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} +.btn-primary:hover { + color: #fff; + background-color: #0b5ed7; + border-color: #0a58ca; +} +.btn-check:focus + .btn-primary, .btn-primary:focus { + color: #fff; + background-color: #0b5ed7; + border-color: #0a58ca; + box-shadow: 0 0 0 0.25rem rgba(49, 132, 253, 0.5); +} +.btn-check:checked + .btn-primary, .btn-check:active + .btn-primary, .btn-primary:active, .btn-primary.active, .show > .btn-primary.dropdown-toggle { + color: #fff; + background-color: #0a58ca; + border-color: #0a53be; +} +.btn-check:checked + .btn-primary:focus, .btn-check:active + .btn-primary:focus, .btn-primary:active:focus, .btn-primary.active:focus, .show > .btn-primary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(49, 132, 253, 0.5); +} +.btn-primary:disabled, .btn-primary.disabled { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} + +.btn-secondary { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} +.btn-secondary:hover { + color: #fff; + background-color: #5c636a; + border-color: #565e64; +} +.btn-check:focus + .btn-secondary, .btn-secondary:focus { + color: #fff; + background-color: #5c636a; + border-color: #565e64; + box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5); +} +.btn-check:checked + .btn-secondary, .btn-check:active + .btn-secondary, .btn-secondary:active, .btn-secondary.active, .show > .btn-secondary.dropdown-toggle { + color: #fff; + background-color: #565e64; + border-color: #51585e; +} +.btn-check:checked + .btn-secondary:focus, .btn-check:active + .btn-secondary:focus, .btn-secondary:active:focus, .btn-secondary.active:focus, .show > .btn-secondary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(130, 138, 145, 0.5); +} +.btn-secondary:disabled, .btn-secondary.disabled { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-success { + color: #fff; + background-color: #198754; + border-color: #198754; +} +.btn-success:hover { + color: #fff; + background-color: #157347; + border-color: #146c43; +} +.btn-check:focus + .btn-success, .btn-success:focus { + color: #fff; + background-color: #157347; + border-color: #146c43; + box-shadow: 0 0 0 0.25rem rgba(60, 153, 110, 0.5); +} +.btn-check:checked + .btn-success, .btn-check:active + .btn-success, .btn-success:active, .btn-success.active, .show > .btn-success.dropdown-toggle { + color: #fff; + background-color: #146c43; + border-color: #13653f; +} +.btn-check:checked + .btn-success:focus, .btn-check:active + .btn-success:focus, .btn-success:active:focus, .btn-success.active:focus, .show > .btn-success.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(60, 153, 110, 0.5); +} +.btn-success:disabled, .btn-success.disabled { + color: #fff; + background-color: #198754; + border-color: #198754; +} + +.btn-info { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0; +} +.btn-info:hover { + color: #000; + background-color: #31d2f2; + border-color: #25cff2; +} +.btn-check:focus + .btn-info, .btn-info:focus { + color: #000; + background-color: #31d2f2; + border-color: #25cff2; + box-shadow: 0 0 0 0.25rem rgba(11, 172, 204, 0.5); +} +.btn-check:checked + .btn-info, .btn-check:active + .btn-info, .btn-info:active, .btn-info.active, .show > .btn-info.dropdown-toggle { + color: #000; + background-color: #3dd5f3; + border-color: #25cff2; +} +.btn-check:checked + .btn-info:focus, .btn-check:active + .btn-info:focus, .btn-info:active:focus, .btn-info.active:focus, .show > .btn-info.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(11, 172, 204, 0.5); +} +.btn-info:disabled, .btn-info.disabled { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0; +} + +.btn-warning { + color: #000; + background-color: #ffc107; + border-color: #ffc107; +} +.btn-warning:hover { + color: #000; + background-color: #ffca2c; + border-color: #ffc720; +} +.btn-check:focus + .btn-warning, .btn-warning:focus { + color: #000; + background-color: #ffca2c; + border-color: #ffc720; + box-shadow: 0 0 0 0.25rem rgba(217, 164, 6, 0.5); +} +.btn-check:checked + .btn-warning, .btn-check:active + .btn-warning, .btn-warning:active, .btn-warning.active, .show > .btn-warning.dropdown-toggle { + color: #000; + background-color: #ffcd39; + border-color: #ffc720; +} +.btn-check:checked + .btn-warning:focus, .btn-check:active + .btn-warning:focus, .btn-warning:active:focus, .btn-warning.active:focus, .show > .btn-warning.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(217, 164, 6, 0.5); +} +.btn-warning:disabled, .btn-warning.disabled { + color: #000; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-danger { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} +.btn-danger:hover { + color: #fff; + background-color: #bb2d3b; + border-color: #b02a37; +} +.btn-check:focus + .btn-danger, .btn-danger:focus { + color: #fff; + background-color: #bb2d3b; + border-color: #b02a37; + box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5); +} +.btn-check:checked + .btn-danger, .btn-check:active + .btn-danger, .btn-danger:active, .btn-danger.active, .show > .btn-danger.dropdown-toggle { + color: #fff; + background-color: #b02a37; + border-color: #a52834; +} +.btn-check:checked + .btn-danger:focus, .btn-check:active + .btn-danger:focus, .btn-danger:active:focus, .btn-danger.active:focus, .show > .btn-danger.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(225, 83, 97, 0.5); +} +.btn-danger:disabled, .btn-danger.disabled { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-light { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa; +} +.btn-light:hover { + color: #000; + background-color: #f9fafb; + border-color: #f9fafb; +} +.btn-check:focus + .btn-light, .btn-light:focus { + color: #000; + background-color: #f9fafb; + border-color: #f9fafb; + box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5); +} +.btn-check:checked + .btn-light, .btn-check:active + .btn-light, .btn-light:active, .btn-light.active, .show > .btn-light.dropdown-toggle { + color: #000; + background-color: #f9fafb; + border-color: #f9fafb; +} +.btn-check:checked + .btn-light:focus, .btn-check:active + .btn-light:focus, .btn-light:active:focus, .btn-light.active:focus, .show > .btn-light.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(211, 212, 213, 0.5); +} +.btn-light:disabled, .btn-light.disabled { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-dark { + color: #fff; + background-color: #212529; + border-color: #212529; +} +.btn-dark:hover { + color: #fff; + background-color: #1c1f23; + border-color: #1a1e21; +} +.btn-check:focus + .btn-dark, .btn-dark:focus { + color: #fff; + background-color: #1c1f23; + border-color: #1a1e21; + box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5); +} +.btn-check:checked + .btn-dark, .btn-check:active + .btn-dark, .btn-dark:active, .btn-dark.active, .show > .btn-dark.dropdown-toggle { + color: #fff; + background-color: #1a1e21; + border-color: #191c1f; +} +.btn-check:checked + .btn-dark:focus, .btn-check:active + .btn-dark:focus, .btn-dark:active:focus, .btn-dark.active:focus, .show > .btn-dark.dropdown-toggle:focus { + box-shadow: 0 0 0 0.25rem rgba(66, 70, 73, 0.5); +} +.btn-dark:disabled, .btn-dark.disabled { + color: #fff; + background-color: #212529; + border-color: #212529; +} + +.btn-outline-primary { + color: #0d6efd; + border-color: #0d6efd; +} +.btn-outline-primary:hover { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} +.btn-check:focus + .btn-outline-primary, .btn-outline-primary:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.5); +} +.btn-check:checked + .btn-outline-primary, .btn-check:active + .btn-outline-primary, .btn-outline-primary:active, .btn-outline-primary.active, .btn-outline-primary.dropdown-toggle.show { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} +.btn-check:checked + .btn-outline-primary:focus, .btn-check:active + .btn-outline-primary:focus, .btn-outline-primary:active:focus, .btn-outline-primary.active:focus, .btn-outline-primary.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.5); +} +.btn-outline-primary:disabled, .btn-outline-primary.disabled { + color: #0d6efd; + background-color: transparent; +} + +.btn-outline-secondary { + color: #6c757d; + border-color: #6c757d; +} +.btn-outline-secondary:hover { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} +.btn-check:focus + .btn-outline-secondary, .btn-outline-secondary:focus { + box-shadow: 0 0 0 0.25rem rgba(108, 117, 125, 0.5); +} +.btn-check:checked + .btn-outline-secondary, .btn-check:active + .btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} +.btn-check:checked + .btn-outline-secondary:focus, .btn-check:active + .btn-outline-secondary:focus, .btn-outline-secondary:active:focus, .btn-outline-secondary.active:focus, .btn-outline-secondary.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(108, 117, 125, 0.5); +} +.btn-outline-secondary:disabled, .btn-outline-secondary.disabled { + color: #6c757d; + background-color: transparent; +} + +.btn-outline-success { + color: #198754; + border-color: #198754; +} +.btn-outline-success:hover { + color: #fff; + background-color: #198754; + border-color: #198754; +} +.btn-check:focus + .btn-outline-success, .btn-outline-success:focus { + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.5); +} +.btn-check:checked + .btn-outline-success, .btn-check:active + .btn-outline-success, .btn-outline-success:active, .btn-outline-success.active, .btn-outline-success.dropdown-toggle.show { + color: #fff; + background-color: #198754; + border-color: #198754; +} +.btn-check:checked + .btn-outline-success:focus, .btn-check:active + .btn-outline-success:focus, .btn-outline-success:active:focus, .btn-outline-success.active:focus, .btn-outline-success.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.5); +} +.btn-outline-success:disabled, .btn-outline-success.disabled { + color: #198754; + background-color: transparent; +} + +.btn-outline-info { + color: #0dcaf0; + border-color: #0dcaf0; +} +.btn-outline-info:hover { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0; +} +.btn-check:focus + .btn-outline-info, .btn-outline-info:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.5); +} +.btn-check:checked + .btn-outline-info, .btn-check:active + .btn-outline-info, .btn-outline-info:active, .btn-outline-info.active, .btn-outline-info.dropdown-toggle.show { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0; +} +.btn-check:checked + .btn-outline-info:focus, .btn-check:active + .btn-outline-info:focus, .btn-outline-info:active:focus, .btn-outline-info.active:focus, .btn-outline-info.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(13, 202, 240, 0.5); +} +.btn-outline-info:disabled, .btn-outline-info.disabled { + color: #0dcaf0; + background-color: transparent; +} + +.btn-outline-warning { + color: #ffc107; + border-color: #ffc107; +} +.btn-outline-warning:hover { + color: #000; + background-color: #ffc107; + border-color: #ffc107; +} +.btn-check:focus + .btn-outline-warning, .btn-outline-warning:focus { + box-shadow: 0 0 0 0.25rem rgba(255, 193, 7, 0.5); +} +.btn-check:checked + .btn-outline-warning, .btn-check:active + .btn-outline-warning, .btn-outline-warning:active, .btn-outline-warning.active, .btn-outline-warning.dropdown-toggle.show { + color: #000; + background-color: #ffc107; + border-color: #ffc107; +} +.btn-check:checked + .btn-outline-warning:focus, .btn-check:active + .btn-outline-warning:focus, .btn-outline-warning:active:focus, .btn-outline-warning.active:focus, .btn-outline-warning.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(255, 193, 7, 0.5); +} +.btn-outline-warning:disabled, .btn-outline-warning.disabled { + color: #ffc107; + background-color: transparent; +} + +.btn-outline-danger { + color: #dc3545; + border-color: #dc3545; +} +.btn-outline-danger:hover { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} +.btn-check:focus + .btn-outline-danger, .btn-outline-danger:focus { + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.5); +} +.btn-check:checked + .btn-outline-danger, .btn-check:active + .btn-outline-danger, .btn-outline-danger:active, .btn-outline-danger.active, .btn-outline-danger.dropdown-toggle.show { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} +.btn-check:checked + .btn-outline-danger:focus, .btn-check:active + .btn-outline-danger:focus, .btn-outline-danger:active:focus, .btn-outline-danger.active:focus, .btn-outline-danger.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.5); +} +.btn-outline-danger:disabled, .btn-outline-danger.disabled { + color: #dc3545; + background-color: transparent; +} + +.btn-outline-light { + color: #f8f9fa; + border-color: #f8f9fa; +} +.btn-outline-light:hover { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa; +} +.btn-check:focus + .btn-outline-light, .btn-outline-light:focus { + box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5); +} +.btn-check:checked + .btn-outline-light, .btn-check:active + .btn-outline-light, .btn-outline-light:active, .btn-outline-light.active, .btn-outline-light.dropdown-toggle.show { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa; +} +.btn-check:checked + .btn-outline-light:focus, .btn-check:active + .btn-outline-light:focus, .btn-outline-light:active:focus, .btn-outline-light.active:focus, .btn-outline-light.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(248, 249, 250, 0.5); +} +.btn-outline-light:disabled, .btn-outline-light.disabled { + color: #f8f9fa; + background-color: transparent; +} + +.btn-outline-dark { + color: #212529; + border-color: #212529; +} +.btn-outline-dark:hover { + color: #fff; + background-color: #212529; + border-color: #212529; +} +.btn-check:focus + .btn-outline-dark, .btn-outline-dark:focus { + box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5); +} +.btn-check:checked + .btn-outline-dark, .btn-check:active + .btn-outline-dark, .btn-outline-dark:active, .btn-outline-dark.active, .btn-outline-dark.dropdown-toggle.show { + color: #fff; + background-color: #212529; + border-color: #212529; +} +.btn-check:checked + .btn-outline-dark:focus, .btn-check:active + .btn-outline-dark:focus, .btn-outline-dark:active:focus, .btn-outline-dark.active:focus, .btn-outline-dark.dropdown-toggle.show:focus { + box-shadow: 0 0 0 0.25rem rgba(33, 37, 41, 0.5); +} +.btn-outline-dark:disabled, .btn-outline-dark.disabled { + color: #212529; + background-color: transparent; +} + +.btn-link { + font-weight: 400; + color: #0d6efd; + text-decoration: underline; +} +.btn-link:hover { + color: #0a58ca; +} +.btn-link:disabled, .btn-link.disabled { + color: #6c757d; +} + +.btn-lg, .btn-group-lg > .btn { + padding: 0.5rem 1rem; + font-size: 1.25rem; + border-radius: 0.3rem; +} + +.btn-sm, .btn-group-sm > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + border-radius: 0.2rem; +} + +.fade { + transition: opacity 0.15s linear; +} +@media (prefers-reduced-motion: reduce) { + .fade { + transition: none; + } +} +.fade:not(.show) { + opacity: 0; +} + +.collapse:not(.show) { + display: none; +} + +.collapsing { + height: 0; + overflow: hidden; + transition: height 0.35s ease; +} +@media (prefers-reduced-motion: reduce) { + .collapsing { + transition: none; + } +} + +.dropup, +.dropend, +.dropdown, +.dropstart { + position: relative; +} + +.dropdown-toggle { + white-space: nowrap; +} +.dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid; + border-right: 0.3em solid transparent; + border-bottom: 0; + border-left: 0.3em solid transparent; +} +.dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropdown-menu { + position: absolute; + z-index: 1000; + display: none; + min-width: 10rem; + padding: 0.5rem 0; + margin: 0; + font-size: 1rem; + color: #212529; + text-align: left; + list-style: none; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 0.25rem; +} +.dropdown-menu[data-bs-popper] { + top: 100%; + left: 0; + margin-top: 0.125rem; +} + +.dropdown-menu-start { + --bs-position: start; +} +.dropdown-menu-start[data-bs-popper] { + right: auto ; + left: 0 ; +} + +.dropdown-menu-end { + --bs-position: end; +} +.dropdown-menu-end[data-bs-popper] { + right: 0 ; + left: auto ; +} + +@media (min-width: 576px) { + .dropdown-menu-sm-start { + --bs-position: start; + } + .dropdown-menu-sm-start[data-bs-popper] { + right: auto ; + left: 0 ; + } + + .dropdown-menu-sm-end { + --bs-position: end; + } + .dropdown-menu-sm-end[data-bs-popper] { + right: 0 ; + left: auto ; + } +} +@media (min-width: 768px) { + .dropdown-menu-md-start { + --bs-position: start; + } + .dropdown-menu-md-start[data-bs-popper] { + right: auto ; + left: 0 ; + } + + .dropdown-menu-md-end { + --bs-position: end; + } + .dropdown-menu-md-end[data-bs-popper] { + right: 0 ; + left: auto ; + } +} +@media (min-width: 992px) { + .dropdown-menu-lg-start { + --bs-position: start; + } + .dropdown-menu-lg-start[data-bs-popper] { + right: auto ; + left: 0 ; + } + + .dropdown-menu-lg-end { + --bs-position: end; + } + .dropdown-menu-lg-end[data-bs-popper] { + right: 0 ; + left: auto ; + } +} +@media (min-width: 1200px) { + .dropdown-menu-xl-start { + --bs-position: start; + } + .dropdown-menu-xl-start[data-bs-popper] { + right: auto ; + left: 0 ; + } + + .dropdown-menu-xl-end { + --bs-position: end; + } + .dropdown-menu-xl-end[data-bs-popper] { + right: 0 ; + left: auto ; + } +} +@media (min-width: 1400px) { + .dropdown-menu-xxl-start { + --bs-position: start; + } + .dropdown-menu-xxl-start[data-bs-popper] { + right: auto ; + left: 0 ; + } + + .dropdown-menu-xxl-end { + --bs-position: end; + } + .dropdown-menu-xxl-end[data-bs-popper] { + right: 0 ; + left: auto ; + } +} +.dropup .dropdown-menu[data-bs-popper] { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 0.125rem; +} +.dropup .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0; + border-right: 0.3em solid transparent; + border-bottom: 0.3em solid; + border-left: 0.3em solid transparent; +} +.dropup .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropend .dropdown-menu[data-bs-popper] { + top: 0; + right: auto; + left: 100%; + margin-top: 0; + margin-left: 0.125rem; +} +.dropend .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0; + border-bottom: 0.3em solid transparent; + border-left: 0.3em solid; +} +.dropend .dropdown-toggle:empty::after { + margin-left: 0; +} +.dropend .dropdown-toggle::after { + vertical-align: 0; +} + +.dropstart .dropdown-menu[data-bs-popper] { + top: 0; + right: 100%; + left: auto; + margin-top: 0; + margin-right: 0.125rem; +} +.dropstart .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; +} +.dropstart .dropdown-toggle::after { + display: none; +} +.dropstart .dropdown-toggle::before { + display: inline-block; + margin-right: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0.3em solid; + border-bottom: 0.3em solid transparent; +} +.dropstart .dropdown-toggle:empty::after { + margin-left: 0; +} +.dropstart .dropdown-toggle::before { + vertical-align: 0; +} + +.dropdown-divider { + height: 0; + margin: 0.5rem 0; + overflow: hidden; + border-top: 1px solid rgba(0, 0, 0, 0.15); +} + +.dropdown-item { + display: block; + padding: 0.25rem 1rem; + clear: both; + font-weight: 400; + color: #212529; + text-align: inherit; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border: 0; +} +.dropdown-item:hover, .dropdown-item:focus { + color: #1e2125; + background-color: #e9ecef; +} +.dropdown-item.active, .dropdown-item:active { + color: #fff; + text-decoration: none; + background-color: #0d6efd; +} +.dropdown-item.disabled, .dropdown-item:disabled { + color: #adb5bd; + pointer-events: none; + background-color: transparent; +} + +.dropdown-menu.show { + display: block; +} + +.dropdown-header { + display: block; + padding: 0.5rem 1rem; + margin-bottom: 0; + font-size: 0.875rem; + color: #6c757d; + white-space: nowrap; +} + +.dropdown-item-text { + display: block; + padding: 0.25rem 1rem; + color: #212529; +} + +.dropdown-menu-dark { + color: #dee2e6; + background-color: #343a40; + border-color: rgba(0, 0, 0, 0.15); +} +.dropdown-menu-dark .dropdown-item { + color: #dee2e6; +} +.dropdown-menu-dark .dropdown-item:hover, .dropdown-menu-dark .dropdown-item:focus { + color: #fff; + background-color: rgba(255, 255, 255, 0.15); +} +.dropdown-menu-dark .dropdown-item.active, .dropdown-menu-dark .dropdown-item:active { + color: #fff; + background-color: #0d6efd; +} +.dropdown-menu-dark .dropdown-item.disabled, .dropdown-menu-dark .dropdown-item:disabled { + color: #adb5bd; +} +.dropdown-menu-dark .dropdown-divider { + border-color: rgba(0, 0, 0, 0.15); +} +.dropdown-menu-dark .dropdown-item-text { + color: #dee2e6; +} +.dropdown-menu-dark .dropdown-header { + color: #adb5bd; +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-flex; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + flex: 1 1 auto; +} +.btn-group > .btn-check:checked + .btn, +.btn-group > .btn-check:focus + .btn, +.btn-group > .btn:hover, +.btn-group > .btn:focus, +.btn-group > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn-check:checked + .btn, +.btn-group-vertical > .btn-check:focus + .btn, +.btn-group-vertical > .btn:hover, +.btn-group-vertical > .btn:focus, +.btn-group-vertical > .btn:active, +.btn-group-vertical > .btn.active { + z-index: 1; +} + +.btn-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; +} +.btn-toolbar .input-group { + width: auto; +} + +.btn-group > .btn:not(:first-child), +.btn-group > .btn-group:not(:first-child) { + margin-left: -1px; +} +.btn-group > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:nth-child(n+3), +.btn-group > :not(.btn-check) + .btn, +.btn-group > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.dropdown-toggle-split { + padding-right: 0.5625rem; + padding-left: 0.5625rem; +} +.dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after, .dropend .dropdown-toggle-split::after { + margin-left: 0; +} +.dropstart .dropdown-toggle-split::before { + margin-right: 0; +} + +.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { + padding-right: 0.375rem; + padding-left: 0.375rem; +} + +.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { + padding-right: 0.75rem; + padding-left: 0.75rem; +} + +.btn-group-vertical { + flex-direction: column; + align-items: flex-start; + justify-content: center; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group { + width: 100%; +} +.btn-group-vertical > .btn:not(:first-child), +.btn-group-vertical > .btn-group:not(:first-child) { + margin-top: -1px; +} +.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group-vertical > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn ~ .btn, +.btn-group-vertical > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav { + display: flex; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.nav-link { + display: block; + padding: 0.5rem 1rem; + color: #0d6efd; + text-decoration: none; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .nav-link { + transition: none; + } +} +.nav-link:hover, .nav-link:focus { + color: #0a58ca; +} +.nav-link.disabled { + color: #6c757d; + pointer-events: none; + cursor: default; +} + +.nav-tabs { + border-bottom: 1px solid #dee2e6; +} +.nav-tabs .nav-link { + margin-bottom: -1px; + background: none; + border: 1px solid transparent; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} +.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { + border-color: #e9ecef #e9ecef #dee2e6; + isolation: isolate; +} +.nav-tabs .nav-link.disabled { + color: #6c757d; + background-color: transparent; + border-color: transparent; +} +.nav-tabs .nav-link.active, +.nav-tabs .nav-item.show .nav-link { + color: #495057; + background-color: #fff; + border-color: #dee2e6 #dee2e6 #fff; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav-pills .nav-link { + background: none; + border: 0; + border-radius: 0.25rem; +} +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: #fff; + background-color: #0d6efd; +} + +.nav-fill > .nav-link, +.nav-fill .nav-item { + flex: 1 1 auto; + text-align: center; +} + +.nav-justified > .nav-link, +.nav-justified .nav-item { + flex-basis: 0; + flex-grow: 1; + text-align: center; +} + +.nav-fill .nav-item .nav-link, +.nav-justified .nav-item .nav-link { + width: 100%; +} + +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} + +.navbar { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} +.navbar > .container, +.navbar > .container-fluid, +.navbar > .container-sm, +.navbar > .container-md, +.navbar > .container-lg, +.navbar > .container-xl, +.navbar > .container-xxl { + display: flex; + flex-wrap: inherit; + align-items: center; + justify-content: space-between; +} +.navbar-brand { + padding-top: 0.3125rem; + padding-bottom: 0.3125rem; + margin-right: 1rem; + font-size: 1.25rem; + text-decoration: none; + white-space: nowrap; +} +.navbar-nav { + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.navbar-nav .nav-link { + padding-right: 0; + padding-left: 0; +} +.navbar-nav .dropdown-menu { + position: static; +} + +.navbar-text { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.navbar-collapse { + flex-basis: 100%; + flex-grow: 1; + align-items: center; +} + +.navbar-toggler { + padding: 0.25rem 0.75rem; + font-size: 1.25rem; + line-height: 1; + background-color: transparent; + border: 1px solid transparent; + border-radius: 0.25rem; + transition: box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .navbar-toggler { + transition: none; + } +} +.navbar-toggler:hover { + text-decoration: none; +} +.navbar-toggler:focus { + text-decoration: none; + outline: 0; + box-shadow: 0 0 0 0.25rem; +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + background-repeat: no-repeat; + background-position: center; + background-size: 100%; +} + +.navbar-nav-scroll { + max-height: var(--bs-scroll-height, 75vh); + overflow-y: auto; +} + +@media (min-width: 576px) { + .navbar-expand-sm { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-sm .navbar-nav { + flex-direction: row; + } + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-sm .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-sm .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-sm .navbar-toggler { + display: none; + } +} +@media (min-width: 768px) { + .navbar-expand-md { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-md .navbar-nav { + flex-direction: row; + } + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-md .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-md .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-md .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-md .navbar-toggler { + display: none; + } +} +@media (min-width: 992px) { + .navbar-expand-lg { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-lg .navbar-nav { + flex-direction: row; + } + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-lg .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-lg .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-lg .navbar-toggler { + display: none; + } +} +@media (min-width: 1200px) { + .navbar-expand-xl { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-xl .navbar-nav { + flex-direction: row; + } + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-xl .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-xl .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-xl .navbar-toggler { + display: none; + } +} +@media (min-width: 1400px) { + .navbar-expand-xxl { + flex-wrap: nowrap; + justify-content: flex-start; + } + .navbar-expand-xxl .navbar-nav { + flex-direction: row; + } + .navbar-expand-xxl .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-xxl .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-xxl .navbar-nav-scroll { + overflow: visible; + } + .navbar-expand-xxl .navbar-collapse { + display: flex !important; + flex-basis: auto; + } + .navbar-expand-xxl .navbar-toggler { + display: none; + } +} +.navbar-expand { + flex-wrap: nowrap; + justify-content: flex-start; +} +.navbar-expand .navbar-nav { + flex-direction: row; +} +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute; +} +.navbar-expand .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; +} +.navbar-expand .navbar-nav-scroll { + overflow: visible; +} +.navbar-expand .navbar-collapse { + display: flex !important; + flex-basis: auto; +} +.navbar-expand .navbar-toggler { + display: none; +} + +.navbar-light .navbar-brand { + color: rgba(0, 0, 0, 0.9); +} +.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus { + color: rgba(0, 0, 0, 0.9); +} +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, 0.55); +} +.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus { + color: rgba(0, 0, 0, 0.7); +} +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 0, 0, 0.3); +} +.navbar-light .navbar-nav .show > .nav-link, +.navbar-light .navbar-nav .nav-link.active { + color: rgba(0, 0, 0, 0.9); +} +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, 0.55); + border-color: rgba(0, 0, 0, 0.1); +} +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} +.navbar-light .navbar-text { + color: rgba(0, 0, 0, 0.55); +} +.navbar-light .navbar-text a, +.navbar-light .navbar-text a:hover, +.navbar-light .navbar-text a:focus { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-dark .navbar-brand { + color: #fff; +} +.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus { + color: #fff; +} +.navbar-dark .navbar-nav .nav-link { + color: rgba(255, 255, 255, 0.55); +} +.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus { + color: rgba(255, 255, 255, 0.75); +} +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, 0.25); +} +.navbar-dark .navbar-nav .show > .nav-link, +.navbar-dark .navbar-nav .nav-link.active { + color: #fff; +} +.navbar-dark .navbar-toggler { + color: rgba(255, 255, 255, 0.55); + border-color: rgba(255, 255, 255, 0.1); +} +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); +} +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, 0.55); +} +.navbar-dark .navbar-text a, +.navbar-dark .navbar-text a:hover, +.navbar-dark .navbar-text a:focus { + color: #fff; +} + +.card { + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-color: #fff; + background-clip: border-box; + border: 1px solid rgba(0, 0, 0, 0.125); + border-radius: 0.25rem; +} +.card > hr { + margin-right: 0; + margin-left: 0; +} +.card > .list-group { + border-top: inherit; + border-bottom: inherit; +} +.card > .list-group:first-child { + border-top-width: 0; + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} +.card > .list-group:last-child { + border-bottom-width: 0; + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} +.card > .card-header + .list-group, +.card > .list-group + .card-footer { + border-top: 0; +} + +.card-body { + flex: 1 1 auto; + padding: 1rem 1rem; +} + +.card-title { + margin-bottom: 0.5rem; +} + +.card-subtitle { + margin-top: -0.25rem; + margin-bottom: 0; +} + +.card-text:last-child { + margin-bottom: 0; +} + +.card-link:hover { + text-decoration: none; +} +.card-link + .card-link { + margin-left: 1rem; +} + +.card-header { + padding: 0.5rem 1rem; + margin-bottom: 0; + background-color: rgba(0, 0, 0, 0.03); + border-bottom: 1px solid rgba(0, 0, 0, 0.125); +} +.card-header:first-child { + border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; +} + +.card-footer { + padding: 0.5rem 1rem; + background-color: rgba(0, 0, 0, 0.03); + border-top: 1px solid rgba(0, 0, 0, 0.125); +} +.card-footer:last-child { + border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); +} + +.card-header-tabs { + margin-right: -0.5rem; + margin-bottom: -0.5rem; + margin-left: -0.5rem; + border-bottom: 0; +} + +.card-header-pills { + margin-right: -0.5rem; + margin-left: -0.5rem; +} + +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: 1rem; + border-radius: calc(0.25rem - 1px); +} + +.card-img, +.card-img-top, +.card-img-bottom { + width: 100%; +} + +.card-img, +.card-img-top { + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} + +.card-img, +.card-img-bottom { + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} + +.card-group > .card { + margin-bottom: 0.75rem; +} +@media (min-width: 576px) { + .card-group { + display: flex; + flex-flow: row wrap; + } + .card-group > .card { + flex: 1 0 0%; + margin-bottom: 0; + } + .card-group > .card + .card { + margin-left: 0; + border-left: 0; + } + .card-group > .card:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + .card-group > .card:not(:last-child) .card-img-top, +.card-group > .card:not(:last-child) .card-header { + border-top-right-radius: 0; + } + .card-group > .card:not(:last-child) .card-img-bottom, +.card-group > .card:not(:last-child) .card-footer { + border-bottom-right-radius: 0; + } + .card-group > .card:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .card-group > .card:not(:first-child) .card-img-top, +.card-group > .card:not(:first-child) .card-header { + border-top-left-radius: 0; + } + .card-group > .card:not(:first-child) .card-img-bottom, +.card-group > .card:not(:first-child) .card-footer { + border-bottom-left-radius: 0; + } +} + +.accordion-button { + position: relative; + display: flex; + align-items: center; + width: 100%; + padding: 1rem 1.25rem; + font-size: 1rem; + color: #212529; + text-align: left; + background-color: #fff; + border: 0; + border-radius: 0; + overflow-anchor: none; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease; +} +@media (prefers-reduced-motion: reduce) { + .accordion-button { + transition: none; + } +} +.accordion-button:not(.collapsed) { + color: #0c63e4; + background-color: #e7f1ff; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.125); +} +.accordion-button:not(.collapsed)::after { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + transform: rotate(-180deg); +} +.accordion-button::after { + flex-shrink: 0; + width: 1.25rem; + height: 1.25rem; + margin-left: auto; + content: ""; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-size: 1.25rem; + transition: transform 0.2s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .accordion-button::after { + transition: none; + } +} +.accordion-button:hover { + z-index: 2; +} +.accordion-button:focus { + z-index: 3; + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} + +.accordion-header { + margin-bottom: 0; +} + +.accordion-item { + background-color: #fff; + border: 1px solid rgba(0, 0, 0, 0.125); +} +.accordion-item:first-of-type { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} +.accordion-item:first-of-type .accordion-button { + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} +.accordion-item:not(:first-of-type) { + border-top: 0; +} +.accordion-item:last-of-type { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} +.accordion-item:last-of-type .accordion-button.collapsed { + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} +.accordion-item:last-of-type .accordion-collapse { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.accordion-body { + padding: 1rem 1.25rem; +} + +.accordion-flush .accordion-collapse { + border-width: 0; +} +.accordion-flush .accordion-item { + border-right: 0; + border-left: 0; + border-radius: 0; +} +.accordion-flush .accordion-item:first-child { + border-top: 0; +} +.accordion-flush .accordion-item:last-child { + border-bottom: 0; +} +.accordion-flush .accordion-item .accordion-button { + border-radius: 0; +} + +.breadcrumb { + display: flex; + flex-wrap: wrap; + padding: 0 0; + margin-bottom: 1rem; + list-style: none; +} + +.breadcrumb-item + .breadcrumb-item { + padding-left: 0.5rem; +} +.breadcrumb-item + .breadcrumb-item::before { + float: left; + padding-right: 0.5rem; + color: #6c757d; + content: var(--bs-breadcrumb-divider, "/") ; +} +.breadcrumb-item.active { + color: #6c757d; +} + +.pagination { + display: flex; + padding-left: 0; + list-style: none; +} + +.page-link { + position: relative; + display: block; + color: #0d6efd; + text-decoration: none; + background-color: #fff; + border: 1px solid #dee2e6; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .page-link { + transition: none; + } +} +.page-link:hover { + z-index: 2; + color: #0a58ca; + background-color: #e9ecef; + border-color: #dee2e6; +} +.page-link:focus { + z-index: 3; + color: #0a58ca; + background-color: #e9ecef; + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); +} + +.page-item:not(:first-child) .page-link { + margin-left: -1px; +} +.page-item.active .page-link { + z-index: 3; + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} +.page-item.disabled .page-link { + color: #6c757d; + pointer-events: none; + background-color: #fff; + border-color: #dee2e6; +} + +.page-link { + padding: 0.375rem 0.75rem; +} + +.page-item:first-child .page-link { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} +.page-item:last-child .page-link { + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.pagination-lg .page-link { + padding: 0.75rem 1.5rem; + font-size: 1.25rem; +} +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; +} +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: 0.3rem; + border-bottom-right-radius: 0.3rem; +} + +.pagination-sm .page-link { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; +} +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; +} +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; +} + +.badge { + display: inline-block; + padding: 0.35em 0.65em; + font-size: 0.75em; + font-weight: 700; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25rem; +} +.badge:empty { + display: none; +} + +.btn .badge { + position: relative; + top: -1px; +} + +.alert { + position: relative; + padding: 1rem 1rem; + margin-bottom: 1rem; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.alert-heading { + color: inherit; +} + +.alert-link { + font-weight: 700; +} + +.alert-dismissible { + padding-right: 3rem; +} +.alert-dismissible .btn-close { + position: absolute; + top: 0; + right: 0; + z-index: 2; + padding: 1.25rem 1rem; +} + +.alert-primary { + color: #084298; + background-color: #cfe2ff; + border-color: #b6d4fe; +} +.alert-primary .alert-link { + color: #06357a; +} + +.alert-secondary { + color: #41464b; + background-color: #e2e3e5; + border-color: #d3d6d8; +} +.alert-secondary .alert-link { + color: #34383c; +} + +.alert-success { + color: #0f5132; + background-color: #d1e7dd; + border-color: #badbcc; +} +.alert-success .alert-link { + color: #0c4128; +} + +.alert-info { + color: #055160; + background-color: #cff4fc; + border-color: #b6effb; +} +.alert-info .alert-link { + color: #04414d; +} + +.alert-warning { + color: #664d03; + background-color: #fff3cd; + border-color: #ffecb5; +} +.alert-warning .alert-link { + color: #523e02; +} + +.alert-danger { + color: #842029; + background-color: #f8d7da; + border-color: #f5c2c7; +} +.alert-danger .alert-link { + color: #6a1a21; +} + +.alert-light { + color: #636464; + background-color: #fefefe; + border-color: #fdfdfe; +} +.alert-light .alert-link { + color: #4f5050; +} + +.alert-dark { + color: #141619; + background-color: #d3d3d4; + border-color: #bcbebf; +} +.alert-dark .alert-link { + color: #101214; +} + +@-webkit-keyframes progress-bar-stripes { + 0% { + background-position-x: 1rem; + } +} + +@keyframes progress-bar-stripes { + 0% { + background-position-x: 1rem; + } +} +.progress { + display: flex; + height: 1rem; + overflow: hidden; + font-size: 0.75rem; + background-color: #e9ecef; + border-radius: 0.25rem; +} + +.progress-bar { + display: flex; + flex-direction: column; + justify-content: center; + overflow: hidden; + color: #fff; + text-align: center; + white-space: nowrap; + background-color: #0d6efd; + transition: width 0.6s ease; +} +@media (prefers-reduced-motion: reduce) { + .progress-bar { + transition: none; + } +} + +.progress-bar-striped { + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 1rem 1rem; +} + +.progress-bar-animated { + -webkit-animation: 1s linear infinite progress-bar-stripes; + animation: 1s linear infinite progress-bar-stripes; +} +@media (prefers-reduced-motion: reduce) { + .progress-bar-animated { + -webkit-animation: none; + animation: none; + } +} + +.list-group { + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + border-radius: 0.25rem; +} + +.list-group-numbered { + list-style-type: none; + counter-reset: section; +} +.list-group-numbered > li::before { + content: counters(section, ".") ". "; + counter-increment: section; +} + +.list-group-item-action { + width: 100%; + color: #495057; + text-align: inherit; +} +.list-group-item-action:hover, .list-group-item-action:focus { + z-index: 1; + color: #495057; + text-decoration: none; + background-color: #f8f9fa; +} +.list-group-item-action:active { + color: #212529; + background-color: #e9ecef; +} + +.list-group-item { + position: relative; + display: block; + padding: 0.5rem 1rem; + color: #212529; + text-decoration: none; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, 0.125); +} +.list-group-item:first-child { + border-top-left-radius: inherit; + border-top-right-radius: inherit; +} +.list-group-item:last-child { + border-bottom-right-radius: inherit; + border-bottom-left-radius: inherit; +} +.list-group-item.disabled, .list-group-item:disabled { + color: #6c757d; + pointer-events: none; + background-color: #fff; +} +.list-group-item.active { + z-index: 2; + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd; +} +.list-group-item + .list-group-item { + border-top-width: 0; +} +.list-group-item + .list-group-item.active { + margin-top: -1px; + border-top-width: 1px; +} + +.list-group-horizontal { + flex-direction: row; +} +.list-group-horizontal > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; +} +.list-group-horizontal > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; +} +.list-group-horizontal > .list-group-item.active { + margin-top: 0; +} +.list-group-horizontal > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; +} +.list-group-horizontal > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; +} + +@media (min-width: 576px) { + .list-group-horizontal-sm { + flex-direction: row; + } + .list-group-horizontal-sm > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-sm > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + .list-group-horizontal-sm > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-sm > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + .list-group-horizontal-sm > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} +@media (min-width: 768px) { + .list-group-horizontal-md { + flex-direction: row; + } + .list-group-horizontal-md > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-md > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + .list-group-horizontal-md > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-md > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + .list-group-horizontal-md > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} +@media (min-width: 992px) { + .list-group-horizontal-lg { + flex-direction: row; + } + .list-group-horizontal-lg > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-lg > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + .list-group-horizontal-lg > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-lg > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + .list-group-horizontal-lg > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} +@media (min-width: 1200px) { + .list-group-horizontal-xl { + flex-direction: row; + } + .list-group-horizontal-xl > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-xl > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + .list-group-horizontal-xl > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-xl > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + .list-group-horizontal-xl > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} +@media (min-width: 1400px) { + .list-group-horizontal-xxl { + flex-direction: row; + } + .list-group-horizontal-xxl > .list-group-item:first-child { + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-xxl > .list-group-item:last-child { + border-top-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } + .list-group-horizontal-xxl > .list-group-item.active { + margin-top: 0; + } + .list-group-horizontal-xxl > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0; + } + .list-group-horizontal-xxl > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px; + } +} +.list-group-flush { + border-radius: 0; +} +.list-group-flush > .list-group-item { + border-width: 0 0 1px; +} +.list-group-flush > .list-group-item:last-child { + border-bottom-width: 0; +} + +.list-group-item-primary { + color: #084298; + background-color: #cfe2ff; +} +.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { + color: #084298; + background-color: #bacbe6; +} +.list-group-item-primary.list-group-item-action.active { + color: #fff; + background-color: #084298; + border-color: #084298; +} + +.list-group-item-secondary { + color: #41464b; + background-color: #e2e3e5; +} +.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { + color: #41464b; + background-color: #cbccce; +} +.list-group-item-secondary.list-group-item-action.active { + color: #fff; + background-color: #41464b; + border-color: #41464b; +} + +.list-group-item-success { + color: #0f5132; + background-color: #d1e7dd; +} +.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus { + color: #0f5132; + background-color: #bcd0c7; +} +.list-group-item-success.list-group-item-action.active { + color: #fff; + background-color: #0f5132; + border-color: #0f5132; +} + +.list-group-item-info { + color: #055160; + background-color: #cff4fc; +} +.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { + color: #055160; + background-color: #badce3; +} +.list-group-item-info.list-group-item-action.active { + color: #fff; + background-color: #055160; + border-color: #055160; +} + +.list-group-item-warning { + color: #664d03; + background-color: #fff3cd; +} +.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { + color: #664d03; + background-color: #e6dbb9; +} +.list-group-item-warning.list-group-item-action.active { + color: #fff; + background-color: #664d03; + border-color: #664d03; +} + +.list-group-item-danger { + color: #842029; + background-color: #f8d7da; +} +.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus { + color: #842029; + background-color: #dfc2c4; +} +.list-group-item-danger.list-group-item-action.active { + color: #fff; + background-color: #842029; + border-color: #842029; +} + +.list-group-item-light { + color: #636464; + background-color: #fefefe; +} +.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { + color: #636464; + background-color: #e5e5e5; +} +.list-group-item-light.list-group-item-action.active { + color: #fff; + background-color: #636464; + border-color: #636464; +} + +.list-group-item-dark { + color: #141619; + background-color: #d3d3d4; +} +.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus { + color: #141619; + background-color: #bebebf; +} +.list-group-item-dark.list-group-item-action.active { + color: #fff; + background-color: #141619; + border-color: #141619; +} + +.btn-close { + box-sizing: content-box; + width: 1em; + height: 1em; + padding: 0.25em 0.25em; + color: #000; + background: transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat; + border: 0; + border-radius: 0.25rem; + opacity: 0.5; +} +.btn-close:hover { + color: #000; + text-decoration: none; + opacity: 0.75; +} +.btn-close:focus { + outline: 0; + box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); + opacity: 1; +} +.btn-close:disabled, .btn-close.disabled { + pointer-events: none; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + opacity: 0.25; +} + +.btn-close-white { + filter: invert(1) grayscale(100%) brightness(200%); +} + +.toast { + width: 350px; + max-width: 100%; + font-size: 0.875rem; + pointer-events: auto; + background-color: rgba(255, 255, 255, 0.85); + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.1); + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + border-radius: 0.25rem; +} +.toast:not(.showing):not(.show) { + opacity: 0; +} +.toast.hide { + display: none; +} + +.toast-container { + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; + max-width: 100%; + pointer-events: none; +} +.toast-container > :not(:last-child) { + margin-bottom: 0.75rem; +} + +.toast-header { + display: flex; + align-items: center; + padding: 0.5rem 0.75rem; + color: #6c757d; + background-color: rgba(255, 255, 255, 0.85); + background-clip: padding-box; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} +.toast-header .btn-close { + margin-right: -0.375rem; + margin-left: 0.75rem; +} + +.toast-body { + padding: 0.75rem; + word-wrap: break-word; +} + +.modal { + position: fixed; + top: 0; + left: 0; + z-index: 1060; + display: none; + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + outline: 0; +} + +.modal-dialog { + position: relative; + width: auto; + margin: 0.5rem; + pointer-events: none; +} +.modal.fade .modal-dialog { + transition: transform 0.3s ease-out; + transform: translate(0, -50px); +} +@media (prefers-reduced-motion: reduce) { + .modal.fade .modal-dialog { + transition: none; + } +} +.modal.show .modal-dialog { + transform: none; +} +.modal.modal-static .modal-dialog { + transform: scale(1.02); +} + +.modal-dialog-scrollable { + height: calc(100% - 1rem); +} +.modal-dialog-scrollable .modal-content { + max-height: 100%; + overflow: hidden; +} +.modal-dialog-scrollable .modal-body { + overflow-y: auto; +} + +.modal-dialog-centered { + display: flex; + align-items: center; + min-height: calc(100% - 1rem); +} + +.modal-content { + position: relative; + display: flex; + flex-direction: column; + width: 100%; + pointer-events: auto; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; + outline: 0; +} + +.modal-backdrop { + position: fixed; + top: 0; + left: 0; + z-index: 1040; + width: 100vw; + height: 100vh; + background-color: #000; +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop.show { + opacity: 0.5; +} + +.modal-header { + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: space-between; + padding: 1rem 1rem; + border-bottom: 1px solid #dee2e6; + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); +} +.modal-header .btn-close { + padding: 0.5rem 0.5rem; + margin: -0.5rem -0.5rem -0.5rem auto; +} + +.modal-title { + margin-bottom: 0; + line-height: 1.5; +} + +.modal-body { + position: relative; + flex: 1 1 auto; + padding: 1rem; +} + +.modal-footer { + display: flex; + flex-wrap: wrap; + flex-shrink: 0; + align-items: center; + justify-content: flex-end; + padding: 0.75rem; + border-top: 1px solid #dee2e6; + border-bottom-right-radius: calc(0.3rem - 1px); + border-bottom-left-radius: calc(0.3rem - 1px); +} +.modal-footer > * { + margin: 0.25rem; +} + +@media (min-width: 576px) { + .modal-dialog { + max-width: 500px; + margin: 1.75rem auto; + } + + .modal-dialog-scrollable { + height: calc(100% - 3.5rem); + } + + .modal-dialog-centered { + min-height: calc(100% - 3.5rem); + } + + .modal-sm { + max-width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg, +.modal-xl { + max-width: 800px; + } +} +@media (min-width: 1200px) { + .modal-xl { + max-width: 1140px; + } +} +.modal-fullscreen { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; +} +.modal-fullscreen .modal-content { + height: 100%; + border: 0; + border-radius: 0; +} +.modal-fullscreen .modal-header { + border-radius: 0; +} +.modal-fullscreen .modal-body { + overflow-y: auto; +} +.modal-fullscreen .modal-footer { + border-radius: 0; +} + +@media (max-width: 575.98px) { + .modal-fullscreen-sm-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-sm-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-sm-down .modal-header { + border-radius: 0; + } + .modal-fullscreen-sm-down .modal-body { + overflow-y: auto; + } + .modal-fullscreen-sm-down .modal-footer { + border-radius: 0; + } +} +@media (max-width: 767.98px) { + .modal-fullscreen-md-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-md-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-md-down .modal-header { + border-radius: 0; + } + .modal-fullscreen-md-down .modal-body { + overflow-y: auto; + } + .modal-fullscreen-md-down .modal-footer { + border-radius: 0; + } +} +@media (max-width: 991.98px) { + .modal-fullscreen-lg-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-lg-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-lg-down .modal-header { + border-radius: 0; + } + .modal-fullscreen-lg-down .modal-body { + overflow-y: auto; + } + .modal-fullscreen-lg-down .modal-footer { + border-radius: 0; + } +} +@media (max-width: 1199.98px) { + .modal-fullscreen-xl-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-xl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-xl-down .modal-header { + border-radius: 0; + } + .modal-fullscreen-xl-down .modal-body { + overflow-y: auto; + } + .modal-fullscreen-xl-down .modal-footer { + border-radius: 0; + } +} +@media (max-width: 1399.98px) { + .modal-fullscreen-xxl-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0; + } + .modal-fullscreen-xxl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0; + } + .modal-fullscreen-xxl-down .modal-header { + border-radius: 0; + } + .modal-fullscreen-xxl-down .modal-body { + overflow-y: auto; + } + .modal-fullscreen-xxl-down .modal-footer { + border-radius: 0; + } +} +.tooltip { + position: absolute; + z-index: 1080; + display: block; + margin: 0; + font-family: var(--bs-font-sans-serif); + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.875rem; + word-wrap: break-word; + opacity: 0; +} +.tooltip.show { + opacity: 0.9; +} +.tooltip .tooltip-arrow { + position: absolute; + display: block; + width: 0.8rem; + height: 0.4rem; +} +.tooltip .tooltip-arrow::before { + position: absolute; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-tooltip-top, .bs-tooltip-auto[data-popper-placement^=top] { + padding: 0.4rem 0; +} +.bs-tooltip-top .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow { + bottom: 0; +} +.bs-tooltip-top .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before { + top: -1px; + border-width: 0.4rem 0.4rem 0; + border-top-color: #000; +} + +.bs-tooltip-end, .bs-tooltip-auto[data-popper-placement^=right] { + padding: 0 0.4rem; +} +.bs-tooltip-end .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow { + left: 0; + width: 0.4rem; + height: 0.8rem; +} +.bs-tooltip-end .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before { + right: -1px; + border-width: 0.4rem 0.4rem 0.4rem 0; + border-right-color: #000; +} + +.bs-tooltip-bottom, .bs-tooltip-auto[data-popper-placement^=bottom] { + padding: 0.4rem 0; +} +.bs-tooltip-bottom .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow { + top: 0; +} +.bs-tooltip-bottom .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before { + bottom: -1px; + border-width: 0 0.4rem 0.4rem; + border-bottom-color: #000; +} + +.bs-tooltip-start, .bs-tooltip-auto[data-popper-placement^=left] { + padding: 0 0.4rem; +} +.bs-tooltip-start .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow { + right: 0; + width: 0.4rem; + height: 0.8rem; +} +.bs-tooltip-start .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before { + left: -1px; + border-width: 0.4rem 0 0.4rem 0.4rem; + border-left-color: #000; +} + +.tooltip-inner { + max-width: 200px; + padding: 0.25rem 0.5rem; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 0.25rem; +} + +.popover { + position: absolute; + top: 0; + left: 0 ; + z-index: 1070; + display: block; + max-width: 276px; + font-family: var(--bs-font-sans-serif); + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.875rem; + word-wrap: break-word; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; +} +.popover .popover-arrow { + position: absolute; + display: block; + width: 1rem; + height: 0.5rem; +} +.popover .popover-arrow::before, .popover .popover-arrow::after { + position: absolute; + display: block; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-popover-top > .popover-arrow, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow { + bottom: calc(-0.5rem - 1px); +} +.bs-popover-top > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::before { + bottom: 0; + border-width: 0.5rem 0.5rem 0; + border-top-color: rgba(0, 0, 0, 0.25); +} +.bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::after { + bottom: 1px; + border-width: 0.5rem 0.5rem 0; + border-top-color: #fff; +} + +.bs-popover-end > .popover-arrow, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow { + left: calc(-0.5rem - 1px); + width: 0.5rem; + height: 1rem; +} +.bs-popover-end > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::before { + left: 0; + border-width: 0.5rem 0.5rem 0.5rem 0; + border-right-color: rgba(0, 0, 0, 0.25); +} +.bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::after { + left: 1px; + border-width: 0.5rem 0.5rem 0.5rem 0; + border-right-color: #fff; +} + +.bs-popover-bottom > .popover-arrow, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow { + top: calc(-0.5rem - 1px); +} +.bs-popover-bottom > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::before { + top: 0; + border-width: 0 0.5rem 0.5rem 0.5rem; + border-bottom-color: rgba(0, 0, 0, 0.25); +} +.bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::after { + top: 1px; + border-width: 0 0.5rem 0.5rem 0.5rem; + border-bottom-color: #fff; +} +.bs-popover-bottom .popover-header::before, .bs-popover-auto[data-popper-placement^=bottom] .popover-header::before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: 1rem; + margin-left: -0.5rem; + content: ""; + border-bottom: 1px solid #f0f0f0; +} + +.bs-popover-start > .popover-arrow, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow { + right: calc(-0.5rem - 1px); + width: 0.5rem; + height: 1rem; +} +.bs-popover-start > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::before { + right: 0; + border-width: 0.5rem 0 0.5rem 0.5rem; + border-left-color: rgba(0, 0, 0, 0.25); +} +.bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::after { + right: 1px; + border-width: 0.5rem 0 0.5rem 0.5rem; + border-left-color: #fff; +} + +.popover-header { + padding: 0.5rem 1rem; + margin-bottom: 0; + font-size: 1rem; + background-color: #f0f0f0; + border-bottom: 1px solid #d8d8d8; + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); +} +.popover-header:empty { + display: none; +} + +.popover-body { + padding: 1rem 1rem; + color: #212529; +} + +.carousel { + position: relative; +} + +.carousel.pointer-event { + touch-action: pan-y; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner::after { + display: block; + clear: both; + content: ""; +} + +.carousel-item { + position: relative; + display: none; + float: left; + width: 100%; + margin-right: -100%; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transition: transform 0.6s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .carousel-item { + transition: none; + } +} + +.carousel-item.active, +.carousel-item-next, +.carousel-item-prev { + display: block; +} + + +.carousel-item-next:not(.carousel-item-start), +.active.carousel-item-end { + transform: translateX(100%); +} + +.carousel-item-prev:not(.carousel-item-end), +.active.carousel-item-start { + transform: translateX(-100%); +} + + +.carousel-fade .carousel-item { + opacity: 0; + transition-property: opacity; + transform: none; +} +.carousel-fade .carousel-item.active, +.carousel-fade .carousel-item-next.carousel-item-start, +.carousel-fade .carousel-item-prev.carousel-item-end { + z-index: 1; + opacity: 1; +} +.carousel-fade .active.carousel-item-start, +.carousel-fade .active.carousel-item-end { + z-index: 0; + opacity: 0; + transition: opacity 0s 0.6s; +} +@media (prefers-reduced-motion: reduce) { + .carousel-fade .active.carousel-item-start, +.carousel-fade .active.carousel-item-end { + transition: none; + } +} + +.carousel-control-prev, +.carousel-control-next { + position: absolute; + top: 0; + bottom: 0; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + width: 15%; + padding: 0; + color: #fff; + text-align: center; + background: none; + border: 0; + opacity: 0.5; + transition: opacity 0.15s ease; +} +@media (prefers-reduced-motion: reduce) { + .carousel-control-prev, +.carousel-control-next { + transition: none; + } +} +.carousel-control-prev:hover, .carousel-control-prev:focus, +.carousel-control-next:hover, +.carousel-control-next:focus { + color: #fff; + text-decoration: none; + outline: 0; + opacity: 0.9; +} + +.carousel-control-prev { + left: 0; +} + +.carousel-control-next { + right: 0; +} + +.carousel-control-prev-icon, +.carousel-control-next-icon { + display: inline-block; + width: 2rem; + height: 2rem; + background-repeat: no-repeat; + background-position: 50%; + background-size: 100% 100%; +} + + +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e"); +} + +.carousel-control-next-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); +} + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 2; + display: flex; + justify-content: center; + padding: 0; + margin-right: 15%; + margin-bottom: 1rem; + margin-left: 15%; + list-style: none; +} +.carousel-indicators [data-bs-target] { + box-sizing: content-box; + flex: 0 1 auto; + width: 30px; + height: 3px; + padding: 0; + margin-right: 3px; + margin-left: 3px; + text-indent: -999px; + cursor: pointer; + background-color: #fff; + background-clip: padding-box; + border: 0; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; + opacity: 0.5; + transition: opacity 0.6s ease; +} +@media (prefers-reduced-motion: reduce) { + .carousel-indicators [data-bs-target] { + transition: none; + } +} +.carousel-indicators .active { + opacity: 1; +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 1.25rem; + left: 15%; + padding-top: 1.25rem; + padding-bottom: 1.25rem; + color: #fff; + text-align: center; +} + +.carousel-dark .carousel-control-prev-icon, +.carousel-dark .carousel-control-next-icon { + filter: invert(1) grayscale(100); +} +.carousel-dark .carousel-indicators [data-bs-target] { + background-color: #000; +} +.carousel-dark .carousel-caption { + color: #000; +} + +@-webkit-keyframes spinner-border { + to { + transform: rotate(360deg) ; + } +} + +@keyframes spinner-border { + to { + transform: rotate(360deg) ; + } +} +.spinner-border { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: -0.125em; + border: 0.25em solid currentColor; + border-right-color: transparent; + border-radius: 50%; + -webkit-animation: 0.75s linear infinite spinner-border; + animation: 0.75s linear infinite spinner-border; +} + +.spinner-border-sm { + width: 1rem; + height: 1rem; + border-width: 0.2em; +} + +@-webkit-keyframes spinner-grow { + 0% { + transform: scale(0); + } + 50% { + opacity: 1; + transform: none; + } +} + +@keyframes spinner-grow { + 0% { + transform: scale(0); + } + 50% { + opacity: 1; + transform: none; + } +} +.spinner-grow { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: -0.125em; + background-color: currentColor; + border-radius: 50%; + opacity: 0; + -webkit-animation: 0.75s linear infinite spinner-grow; + animation: 0.75s linear infinite spinner-grow; +} + +.spinner-grow-sm { + width: 1rem; + height: 1rem; +} + +@media (prefers-reduced-motion: reduce) { + .spinner-border, +.spinner-grow { + -webkit-animation-duration: 1.5s; + animation-duration: 1.5s; + } +} +.offcanvas { + position: fixed; + bottom: 0; + z-index: 1050; + display: flex; + flex-direction: column; + max-width: 100%; + visibility: hidden; + background-color: #fff; + background-clip: padding-box; + outline: 0; + transition: transform 0.3s ease-in-out; +} +@media (prefers-reduced-motion: reduce) { + .offcanvas { + transition: none; + } +} + +.offcanvas-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 1rem; +} +.offcanvas-header .btn-close { + padding: 0.5rem 0.5rem; + margin: -0.5rem -0.5rem -0.5rem auto; +} + +.offcanvas-title { + margin-bottom: 0; + line-height: 1.5; +} + +.offcanvas-body { + flex-grow: 1; + padding: 1rem 1rem; + overflow-y: auto; +} + +.offcanvas-start { + top: 0; + left: 0; + width: 400px; + border-right: 1px solid rgba(0, 0, 0, 0.2); + transform: translateX(-100%); +} + +.offcanvas-end { + top: 0; + right: 0; + width: 400px; + border-left: 1px solid rgba(0, 0, 0, 0.2); + transform: translateX(100%); +} + +.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: 30vh; + max-height: 100%; + border-bottom: 1px solid rgba(0, 0, 0, 0.2); + transform: translateY(-100%); +} + +.offcanvas-bottom { + right: 0; + left: 0; + height: 30vh; + max-height: 100%; + border-top: 1px solid rgba(0, 0, 0, 0.2); + transform: translateY(100%); +} + +.offcanvas.show { + transform: none; +} + +.clearfix::after { + display: block; + clear: both; + content: ""; +} + +.link-primary { + color: #0d6efd; +} +.link-primary:hover, .link-primary:focus { + color: #0a58ca; +} + +.link-secondary { + color: #6c757d; +} +.link-secondary:hover, .link-secondary:focus { + color: #565e64; +} + +.link-success { + color: #198754; +} +.link-success:hover, .link-success:focus { + color: #146c43; +} + +.link-info { + color: #0dcaf0; +} +.link-info:hover, .link-info:focus { + color: #3dd5f3; +} + +.link-warning { + color: #ffc107; +} +.link-warning:hover, .link-warning:focus { + color: #ffcd39; +} + +.link-danger { + color: #dc3545; +} +.link-danger:hover, .link-danger:focus { + color: #b02a37; +} + +.link-light { + color: #f8f9fa; +} +.link-light:hover, .link-light:focus { + color: #f9fafb; +} + +.link-dark { + color: #212529; +} +.link-dark:hover, .link-dark:focus { + color: #1a1e21; +} + +.ratio { + position: relative; + width: 100%; +} +.ratio::before { + display: block; + padding-top: var(--bs-aspect-ratio); + content: ""; +} +.ratio > * { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.ratio-1x1 { + --bs-aspect-ratio: 100%; +} + +.ratio-4x3 { + --bs-aspect-ratio: calc(3 / 4 * 100%); +} + +.ratio-16x9 { + --bs-aspect-ratio: calc(9 / 16 * 100%); +} + +.ratio-21x9 { + --bs-aspect-ratio: calc(9 / 21 * 100%); +} + +.fixed-top { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; +} + +.fixed-bottom { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; +} + +.sticky-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; +} + +@media (min-width: 576px) { + .sticky-sm-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} +@media (min-width: 768px) { + .sticky-md-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} +@media (min-width: 992px) { + .sticky-lg-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} +@media (min-width: 1200px) { + .sticky-xl-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} +@media (min-width: 1400px) { + .sticky-xxl-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} +.visually-hidden, +.visually-hidden-focusable:not(:focus):not(:focus-within) { + position: absolute !important; + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + white-space: nowrap !important; + border: 0 !important; +} + +.stretched-link::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + content: ""; +} + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.align-baseline { + vertical-align: baseline !important; +} + +.align-top { + vertical-align: top !important; +} + +.align-middle { + vertical-align: middle !important; +} + +.align-bottom { + vertical-align: bottom !important; +} + +.align-text-bottom { + vertical-align: text-bottom !important; +} + +.align-text-top { + vertical-align: text-top !important; +} + +.float-start { + float: left !important; +} + +.float-end { + float: right !important; +} + +.float-none { + float: none !important; +} + +.overflow-auto { + overflow: auto !important; +} + +.overflow-hidden { + overflow: hidden !important; +} + +.overflow-visible { + overflow: visible !important; +} + +.overflow-scroll { + overflow: scroll !important; +} + +.d-inline { + display: inline !important; +} + +.d-inline-block { + display: inline-block !important; +} + +.d-block { + display: block !important; +} + +.d-grid { + display: grid !important; +} + +.d-table { + display: table !important; +} + +.d-table-row { + display: table-row !important; +} + +.d-table-cell { + display: table-cell !important; +} + +.d-flex { + display: flex !important; +} + +.d-inline-flex { + display: inline-flex !important; +} + +.d-none { + display: none !important; +} + +.shadow { + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; +} + +.shadow-sm { + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; +} + +.shadow-lg { + box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; +} + +.shadow-none { + box-shadow: none !important; +} + +.position-static { + position: static !important; +} + +.position-relative { + position: relative !important; +} + +.position-absolute { + position: absolute !important; +} + +.position-fixed { + position: fixed !important; +} + +.position-sticky { + position: -webkit-sticky !important; + position: sticky !important; +} + +.top-0 { + top: 0 !important; +} + +.top-50 { + top: 50% !important; +} + +.top-100 { + top: 100% !important; +} + +.bottom-0 { + bottom: 0 !important; +} + +.bottom-50 { + bottom: 50% !important; +} + +.bottom-100 { + bottom: 100% !important; +} + +.start-0 { + left: 0 !important; +} + +.start-50 { + left: 50% !important; +} + +.start-100 { + left: 100% !important; +} + +.end-0 { + right: 0 !important; +} + +.end-50 { + right: 50% !important; +} + +.end-100 { + right: 100% !important; +} + +.translate-middle { + transform: translate(-50%, -50%) !important; +} + +.translate-middle-x { + transform: translateX(-50%) !important; +} + +.translate-middle-y { + transform: translateY(-50%) !important; +} + +.border { + border: 1px solid #dee2e6 !important; +} + +.border-0 { + border: 0 !important; +} + +.border-top { + border-top: 1px solid #dee2e6 !important; +} + +.border-top-0 { + border-top: 0 !important; +} + +.border-end { + border-right: 1px solid #dee2e6 !important; +} + +.border-end-0 { + border-right: 0 !important; +} + +.border-bottom { + border-bottom: 1px solid #dee2e6 !important; +} + +.border-bottom-0 { + border-bottom: 0 !important; +} + +.border-start { + border-left: 1px solid #dee2e6 !important; +} + +.border-start-0 { + border-left: 0 !important; +} + +.border-primary { + border-color: #0d6efd !important; +} + +.border-secondary { + border-color: #6c757d !important; +} + +.border-success { + border-color: #198754 !important; +} + +.border-info { + border-color: #0dcaf0 !important; +} + +.border-warning { + border-color: #ffc107 !important; +} + +.border-danger { + border-color: #dc3545 !important; +} + +.border-light { + border-color: #f8f9fa !important; +} + +.border-dark { + border-color: #212529 !important; +} + +.border-white { + border-color: #fff !important; +} + +.border-1 { + border-width: 1px !important; +} + +.border-2 { + border-width: 2px !important; +} + +.border-3 { + border-width: 3px !important; +} + +.border-4 { + border-width: 4px !important; +} + +.border-5 { + border-width: 5px !important; +} + +.w-25 { + width: 25% !important; +} + +.w-50 { + width: 50% !important; +} + +.w-75 { + width: 75% !important; +} + +.w-100 { + width: 100% !important; +} + +.w-auto { + width: auto !important; +} + +.mw-100 { + max-width: 100% !important; +} + +.vw-100 { + width: 100vw !important; +} + +.min-vw-100 { + min-width: 100vw !important; +} + +.h-25 { + height: 25% !important; +} + +.h-50 { + height: 50% !important; +} + +.h-75 { + height: 75% !important; +} + +.h-100 { + height: 100% !important; +} + +.h-auto { + height: auto !important; +} + +.mh-100 { + max-height: 100% !important; +} + +.vh-100 { + height: 100vh !important; +} + +.min-vh-100 { + min-height: 100vh !important; +} + +.flex-fill { + flex: 1 1 auto !important; +} + +.flex-row { + flex-direction: row !important; +} + +.flex-column { + flex-direction: column !important; +} + +.flex-row-reverse { + flex-direction: row-reverse !important; +} + +.flex-column-reverse { + flex-direction: column-reverse !important; +} + +.flex-grow-0 { + flex-grow: 0 !important; +} + +.flex-grow-1 { + flex-grow: 1 !important; +} + +.flex-shrink-0 { + flex-shrink: 0 !important; +} + +.flex-shrink-1 { + flex-shrink: 1 !important; +} + +.flex-wrap { + flex-wrap: wrap !important; +} + +.flex-nowrap { + flex-wrap: nowrap !important; +} + +.flex-wrap-reverse { + flex-wrap: wrap-reverse !important; +} + +.gap-0 { + gap: 0 !important; +} + +.gap-1 { + gap: 0.25rem !important; +} + +.gap-2 { + gap: 0.5rem !important; +} + +.gap-3 { + gap: 1rem !important; +} + +.gap-4 { + gap: 1.5rem !important; +} + +.gap-5 { + gap: 3rem !important; +} + +.justify-content-start { + justify-content: flex-start !important; +} + +.justify-content-end { + justify-content: flex-end !important; +} + +.justify-content-center { + justify-content: center !important; +} + +.justify-content-between { + justify-content: space-between !important; +} + +.justify-content-around { + justify-content: space-around !important; +} + +.justify-content-evenly { + justify-content: space-evenly !important; +} + +.align-items-start { + align-items: flex-start !important; +} + +.align-items-end { + align-items: flex-end !important; +} + +.align-items-center { + align-items: center !important; +} + +.align-items-baseline { + align-items: baseline !important; +} + +.align-items-stretch { + align-items: stretch !important; +} + +.align-content-start { + align-content: flex-start !important; +} + +.align-content-end { + align-content: flex-end !important; +} + +.align-content-center { + align-content: center !important; +} + +.align-content-between { + align-content: space-between !important; +} + +.align-content-around { + align-content: space-around !important; +} + +.align-content-stretch { + align-content: stretch !important; +} + +.align-self-auto { + align-self: auto !important; +} + +.align-self-start { + align-self: flex-start !important; +} + +.align-self-end { + align-self: flex-end !important; +} + +.align-self-center { + align-self: center !important; +} + +.align-self-baseline { + align-self: baseline !important; +} + +.align-self-stretch { + align-self: stretch !important; +} + +.order-first { + order: -1 !important; +} + +.order-0 { + order: 0 !important; +} + +.order-1 { + order: 1 !important; +} + +.order-2 { + order: 2 !important; +} + +.order-3 { + order: 3 !important; +} + +.order-4 { + order: 4 !important; +} + +.order-5 { + order: 5 !important; +} + +.order-last { + order: 6 !important; +} + +.m-0 { + margin: 0 !important; +} + +.m-1 { + margin: 0.25rem !important; +} + +.m-2 { + margin: 0.5rem !important; +} + +.m-3 { + margin: 1rem !important; +} + +.m-4 { + margin: 1.5rem !important; +} + +.m-5 { + margin: 3rem !important; +} + +.m-auto { + margin: auto !important; +} + +.mx-0 { + margin-right: 0 !important; + margin-left: 0 !important; +} + +.mx-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; +} + +.mx-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; +} + +.mx-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; +} + +.mx-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; +} + +.mx-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; +} + +.mx-auto { + margin-right: auto !important; + margin-left: auto !important; +} + +.my-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +.my-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; +} + +.my-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; +} + +.my-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; +} + +.my-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; +} + +.my-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; +} + +.my-auto { + margin-top: auto !important; + margin-bottom: auto !important; +} + +.mt-0 { + margin-top: 0 !important; +} + +.mt-1 { + margin-top: 0.25rem !important; +} + +.mt-2 { + margin-top: 0.5rem !important; +} + +.mt-3 { + margin-top: 1rem !important; +} + +.mt-4 { + margin-top: 1.5rem !important; +} + +.mt-5 { + margin-top: 3rem !important; +} + +.mt-auto { + margin-top: auto !important; +} + +.me-0 { + margin-right: 0 !important; +} + +.me-1 { + margin-right: 0.25rem !important; +} + +.me-2 { + margin-right: 0.5rem !important; +} + +.me-3 { + margin-right: 1rem !important; +} + +.me-4 { + margin-right: 1.5rem !important; +} + +.me-5 { + margin-right: 3rem !important; +} + +.me-auto { + margin-right: auto !important; +} + +.mb-0 { + margin-bottom: 0 !important; +} + +.mb-1 { + margin-bottom: 0.25rem !important; +} + +.mb-2 { + margin-bottom: 0.5rem !important; +} + +.mb-3 { + margin-bottom: 1rem !important; +} + +.mb-4 { + margin-bottom: 1.5rem !important; +} + +.mb-5 { + margin-bottom: 3rem !important; +} + +.mb-auto { + margin-bottom: auto !important; +} + +.ms-0 { + margin-left: 0 !important; +} + +.ms-1 { + margin-left: 0.25rem !important; +} + +.ms-2 { + margin-left: 0.5rem !important; +} + +.ms-3 { + margin-left: 1rem !important; +} + +.ms-4 { + margin-left: 1.5rem !important; +} + +.ms-5 { + margin-left: 3rem !important; +} + +.ms-auto { + margin-left: auto !important; +} + +.p-0 { + padding: 0 !important; +} + +.p-1 { + padding: 0.25rem !important; +} + +.p-2 { + padding: 0.5rem !important; +} + +.p-3 { + padding: 1rem !important; +} + +.p-4 { + padding: 1.5rem !important; +} + +.p-5 { + padding: 3rem !important; +} + +.px-0 { + padding-right: 0 !important; + padding-left: 0 !important; +} + +.px-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; +} + +.px-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; +} + +.px-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; +} + +.px-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; +} + +.px-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; +} + +.py-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.py-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; +} + +.py-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; +} + +.py-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; +} + +.py-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; +} + +.py-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; +} + +.pt-0 { + padding-top: 0 !important; +} + +.pt-1 { + padding-top: 0.25rem !important; +} + +.pt-2 { + padding-top: 0.5rem !important; +} + +.pt-3 { + padding-top: 1rem !important; +} + +.pt-4 { + padding-top: 1.5rem !important; +} + +.pt-5 { + padding-top: 3rem !important; +} + +.pe-0 { + padding-right: 0 !important; +} + +.pe-1 { + padding-right: 0.25rem !important; +} + +.pe-2 { + padding-right: 0.5rem !important; +} + +.pe-3 { + padding-right: 1rem !important; +} + +.pe-4 { + padding-right: 1.5rem !important; +} + +.pe-5 { + padding-right: 3rem !important; +} + +.pb-0 { + padding-bottom: 0 !important; +} + +.pb-1 { + padding-bottom: 0.25rem !important; +} + +.pb-2 { + padding-bottom: 0.5rem !important; +} + +.pb-3 { + padding-bottom: 1rem !important; +} + +.pb-4 { + padding-bottom: 1.5rem !important; +} + +.pb-5 { + padding-bottom: 3rem !important; +} + +.ps-0 { + padding-left: 0 !important; +} + +.ps-1 { + padding-left: 0.25rem !important; +} + +.ps-2 { + padding-left: 0.5rem !important; +} + +.ps-3 { + padding-left: 1rem !important; +} + +.ps-4 { + padding-left: 1.5rem !important; +} + +.ps-5 { + padding-left: 3rem !important; +} + +.font-monospace { + font-family: var(--bs-font-monospace) !important; +} + +.fs-1 { + font-size: calc(1.375rem + 1.5vw) !important; +} + +.fs-2 { + font-size: calc(1.325rem + 0.9vw) !important; +} + +.fs-3 { + font-size: calc(1.3rem + 0.6vw) !important; +} + +.fs-4 { + font-size: calc(1.275rem + 0.3vw) !important; +} + +.fs-5 { + font-size: 1.25rem !important; +} + +.fs-6 { + font-size: 1rem !important; +} + +.fst-italic { + font-style: italic !important; +} + +.fst-normal { + font-style: normal !important; +} + +.fw-light { + font-weight: 300 !important; +} + +.fw-lighter { + font-weight: lighter !important; +} + +.fw-normal { + font-weight: 400 !important; +} + +.fw-bold { + font-weight: 700 !important; +} + +.fw-bolder { + font-weight: bolder !important; +} + +.lh-1 { + line-height: 1 !important; +} + +.lh-sm { + line-height: 1.25 !important; +} + +.lh-base { + line-height: 1.5 !important; +} + +.lh-lg { + line-height: 2 !important; +} + +.text-start { + text-align: left !important; +} + +.text-end { + text-align: right !important; +} + +.text-center { + text-align: center !important; +} + +.text-decoration-none { + text-decoration: none !important; +} + +.text-decoration-underline { + text-decoration: underline !important; +} + +.text-decoration-line-through { + text-decoration: line-through !important; +} + +.text-lowercase { + text-transform: lowercase !important; +} + +.text-uppercase { + text-transform: uppercase !important; +} + +.text-capitalize { + text-transform: capitalize !important; +} + +.text-wrap { + white-space: normal !important; +} + +.text-nowrap { + white-space: nowrap !important; +} + + +.text-break { + word-wrap: break-word !important; + word-break: break-word !important; +} + + +.text-primary { + color: #0d6efd !important; +} + +.text-secondary { + color: #6c757d !important; +} + +.text-success { + color: #198754 !important; +} + +.text-info { + color: #0dcaf0 !important; +} + +.text-warning { + color: #ffc107 !important; +} + +.text-danger { + color: #dc3545 !important; +} + +.text-light { + color: #f8f9fa !important; +} + +.text-dark { + color: #212529 !important; +} + +.text-white { + color: #fff !important; +} + +.text-body { + color: #212529 !important; +} + +.text-muted { + color: #6c757d !important; +} + +.text-black-50 { + color: rgba(0, 0, 0, 0.5) !important; +} + +.text-white-50 { + color: rgba(255, 255, 255, 0.5) !important; +} + +.text-reset { + color: inherit !important; +} + +.bg-primary { + background-color: #0d6efd !important; +} + +.bg-secondary { + background-color: #6c757d !important; +} + +.bg-success { + background-color: #198754 !important; +} + +.bg-info { + background-color: #0dcaf0 !important; +} + +.bg-warning { + background-color: #ffc107 !important; +} + +.bg-danger { + background-color: #dc3545 !important; +} + +.bg-light { + background-color: #f8f9fa !important; +} + +.bg-dark { + background-color: #212529 !important; +} + +.bg-body { + background-color: #fff !important; +} + +.bg-white { + background-color: #fff !important; +} + +.bg-transparent { + background-color: transparent !important; +} + +.bg-gradient { + background-image: var(--bs-gradient) !important; +} + +.user-select-all { + -webkit-user-select: all !important; + -moz-user-select: all !important; + user-select: all !important; +} + +.user-select-auto { + -webkit-user-select: auto !important; + -moz-user-select: auto !important; + user-select: auto !important; +} + +.user-select-none { + -webkit-user-select: none !important; + -moz-user-select: none !important; + user-select: none !important; +} + +.pe-none { + pointer-events: none !important; +} + +.pe-auto { + pointer-events: auto !important; +} + +.rounded { + border-radius: 0.25rem !important; +} + +.rounded-0 { + border-radius: 0 !important; +} + +.rounded-1 { + border-radius: 0.2rem !important; +} + +.rounded-2 { + border-radius: 0.25rem !important; +} + +.rounded-3 { + border-radius: 0.3rem !important; +} + +.rounded-circle { + border-radius: 50% !important; +} + +.rounded-pill { + border-radius: 50rem !important; +} + +.rounded-top { + border-top-left-radius: 0.25rem !important; + border-top-right-radius: 0.25rem !important; +} + +.rounded-end { + border-top-right-radius: 0.25rem !important; + border-bottom-right-radius: 0.25rem !important; +} + +.rounded-bottom { + border-bottom-right-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} + +.rounded-start { + border-bottom-left-radius: 0.25rem !important; + border-top-left-radius: 0.25rem !important; +} + +.visible { + visibility: visible !important; +} + +.invisible { + visibility: hidden !important; +} + +@media (min-width: 576px) { + .float-sm-start { + float: left !important; + } + + .float-sm-end { + float: right !important; + } + + .float-sm-none { + float: none !important; + } + + .d-sm-inline { + display: inline !important; + } + + .d-sm-inline-block { + display: inline-block !important; + } + + .d-sm-block { + display: block !important; + } + + .d-sm-grid { + display: grid !important; + } + + .d-sm-table { + display: table !important; + } + + .d-sm-table-row { + display: table-row !important; + } + + .d-sm-table-cell { + display: table-cell !important; + } + + .d-sm-flex { + display: flex !important; + } + + .d-sm-inline-flex { + display: inline-flex !important; + } + + .d-sm-none { + display: none !important; + } + + .flex-sm-fill { + flex: 1 1 auto !important; + } + + .flex-sm-row { + flex-direction: row !important; + } + + .flex-sm-column { + flex-direction: column !important; + } + + .flex-sm-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-sm-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-sm-grow-0 { + flex-grow: 0 !important; + } + + .flex-sm-grow-1 { + flex-grow: 1 !important; + } + + .flex-sm-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-sm-shrink-1 { + flex-shrink: 1 !important; + } + + .flex-sm-wrap { + flex-wrap: wrap !important; + } + + .flex-sm-nowrap { + flex-wrap: nowrap !important; + } + + .flex-sm-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .gap-sm-0 { + gap: 0 !important; + } + + .gap-sm-1 { + gap: 0.25rem !important; + } + + .gap-sm-2 { + gap: 0.5rem !important; + } + + .gap-sm-3 { + gap: 1rem !important; + } + + .gap-sm-4 { + gap: 1.5rem !important; + } + + .gap-sm-5 { + gap: 3rem !important; + } + + .justify-content-sm-start { + justify-content: flex-start !important; + } + + .justify-content-sm-end { + justify-content: flex-end !important; + } + + .justify-content-sm-center { + justify-content: center !important; + } + + .justify-content-sm-between { + justify-content: space-between !important; + } + + .justify-content-sm-around { + justify-content: space-around !important; + } + + .justify-content-sm-evenly { + justify-content: space-evenly !important; + } + + .align-items-sm-start { + align-items: flex-start !important; + } + + .align-items-sm-end { + align-items: flex-end !important; + } + + .align-items-sm-center { + align-items: center !important; + } + + .align-items-sm-baseline { + align-items: baseline !important; + } + + .align-items-sm-stretch { + align-items: stretch !important; + } + + .align-content-sm-start { + align-content: flex-start !important; + } + + .align-content-sm-end { + align-content: flex-end !important; + } + + .align-content-sm-center { + align-content: center !important; + } + + .align-content-sm-between { + align-content: space-between !important; + } + + .align-content-sm-around { + align-content: space-around !important; + } + + .align-content-sm-stretch { + align-content: stretch !important; + } + + .align-self-sm-auto { + align-self: auto !important; + } + + .align-self-sm-start { + align-self: flex-start !important; + } + + .align-self-sm-end { + align-self: flex-end !important; + } + + .align-self-sm-center { + align-self: center !important; + } + + .align-self-sm-baseline { + align-self: baseline !important; + } + + .align-self-sm-stretch { + align-self: stretch !important; + } + + .order-sm-first { + order: -1 !important; + } + + .order-sm-0 { + order: 0 !important; + } + + .order-sm-1 { + order: 1 !important; + } + + .order-sm-2 { + order: 2 !important; + } + + .order-sm-3 { + order: 3 !important; + } + + .order-sm-4 { + order: 4 !important; + } + + .order-sm-5 { + order: 5 !important; + } + + .order-sm-last { + order: 6 !important; + } + + .m-sm-0 { + margin: 0 !important; + } + + .m-sm-1 { + margin: 0.25rem !important; + } + + .m-sm-2 { + margin: 0.5rem !important; + } + + .m-sm-3 { + margin: 1rem !important; + } + + .m-sm-4 { + margin: 1.5rem !important; + } + + .m-sm-5 { + margin: 3rem !important; + } + + .m-sm-auto { + margin: auto !important; + } + + .mx-sm-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + + .mx-sm-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + + .mx-sm-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + + .mx-sm-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + + .mx-sm-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + + .mx-sm-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + + .mx-sm-auto { + margin-right: auto !important; + margin-left: auto !important; + } + + .my-sm-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + + .my-sm-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + + .my-sm-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + + .my-sm-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + + .my-sm-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + + .my-sm-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + + .my-sm-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + + .mt-sm-0 { + margin-top: 0 !important; + } + + .mt-sm-1 { + margin-top: 0.25rem !important; + } + + .mt-sm-2 { + margin-top: 0.5rem !important; + } + + .mt-sm-3 { + margin-top: 1rem !important; + } + + .mt-sm-4 { + margin-top: 1.5rem !important; + } + + .mt-sm-5 { + margin-top: 3rem !important; + } + + .mt-sm-auto { + margin-top: auto !important; + } + + .me-sm-0 { + margin-right: 0 !important; + } + + .me-sm-1 { + margin-right: 0.25rem !important; + } + + .me-sm-2 { + margin-right: 0.5rem !important; + } + + .me-sm-3 { + margin-right: 1rem !important; + } + + .me-sm-4 { + margin-right: 1.5rem !important; + } + + .me-sm-5 { + margin-right: 3rem !important; + } + + .me-sm-auto { + margin-right: auto !important; + } + + .mb-sm-0 { + margin-bottom: 0 !important; + } + + .mb-sm-1 { + margin-bottom: 0.25rem !important; + } + + .mb-sm-2 { + margin-bottom: 0.5rem !important; + } + + .mb-sm-3 { + margin-bottom: 1rem !important; + } + + .mb-sm-4 { + margin-bottom: 1.5rem !important; + } + + .mb-sm-5 { + margin-bottom: 3rem !important; + } + + .mb-sm-auto { + margin-bottom: auto !important; + } + + .ms-sm-0 { + margin-left: 0 !important; + } + + .ms-sm-1 { + margin-left: 0.25rem !important; + } + + .ms-sm-2 { + margin-left: 0.5rem !important; + } + + .ms-sm-3 { + margin-left: 1rem !important; + } + + .ms-sm-4 { + margin-left: 1.5rem !important; + } + + .ms-sm-5 { + margin-left: 3rem !important; + } + + .ms-sm-auto { + margin-left: auto !important; + } + + .p-sm-0 { + padding: 0 !important; + } + + .p-sm-1 { + padding: 0.25rem !important; + } + + .p-sm-2 { + padding: 0.5rem !important; + } + + .p-sm-3 { + padding: 1rem !important; + } + + .p-sm-4 { + padding: 1.5rem !important; + } + + .p-sm-5 { + padding: 3rem !important; + } + + .px-sm-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + + .px-sm-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + + .px-sm-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + + .px-sm-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + + .px-sm-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + + .px-sm-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + + .py-sm-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + + .py-sm-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + + .py-sm-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + + .py-sm-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + + .py-sm-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + + .py-sm-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + + .pt-sm-0 { + padding-top: 0 !important; + } + + .pt-sm-1 { + padding-top: 0.25rem !important; + } + + .pt-sm-2 { + padding-top: 0.5rem !important; + } + + .pt-sm-3 { + padding-top: 1rem !important; + } + + .pt-sm-4 { + padding-top: 1.5rem !important; + } + + .pt-sm-5 { + padding-top: 3rem !important; + } + + .pe-sm-0 { + padding-right: 0 !important; + } + + .pe-sm-1 { + padding-right: 0.25rem !important; + } + + .pe-sm-2 { + padding-right: 0.5rem !important; + } + + .pe-sm-3 { + padding-right: 1rem !important; + } + + .pe-sm-4 { + padding-right: 1.5rem !important; + } + + .pe-sm-5 { + padding-right: 3rem !important; + } + + .pb-sm-0 { + padding-bottom: 0 !important; + } + + .pb-sm-1 { + padding-bottom: 0.25rem !important; + } + + .pb-sm-2 { + padding-bottom: 0.5rem !important; + } + + .pb-sm-3 { + padding-bottom: 1rem !important; + } + + .pb-sm-4 { + padding-bottom: 1.5rem !important; + } + + .pb-sm-5 { + padding-bottom: 3rem !important; + } + + .ps-sm-0 { + padding-left: 0 !important; + } + + .ps-sm-1 { + padding-left: 0.25rem !important; + } + + .ps-sm-2 { + padding-left: 0.5rem !important; + } + + .ps-sm-3 { + padding-left: 1rem !important; + } + + .ps-sm-4 { + padding-left: 1.5rem !important; + } + + .ps-sm-5 { + padding-left: 3rem !important; + } + + .text-sm-start { + text-align: left !important; + } + + .text-sm-end { + text-align: right !important; + } + + .text-sm-center { + text-align: center !important; + } +} +@media (min-width: 768px) { + .float-md-start { + float: left !important; + } + + .float-md-end { + float: right !important; + } + + .float-md-none { + float: none !important; + } + + .d-md-inline { + display: inline !important; + } + + .d-md-inline-block { + display: inline-block !important; + } + + .d-md-block { + display: block !important; + } + + .d-md-grid { + display: grid !important; + } + + .d-md-table { + display: table !important; + } + + .d-md-table-row { + display: table-row !important; + } + + .d-md-table-cell { + display: table-cell !important; + } + + .d-md-flex { + display: flex !important; + } + + .d-md-inline-flex { + display: inline-flex !important; + } + + .d-md-none { + display: none !important; + } + + .flex-md-fill { + flex: 1 1 auto !important; + } + + .flex-md-row { + flex-direction: row !important; + } + + .flex-md-column { + flex-direction: column !important; + } + + .flex-md-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-md-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-md-grow-0 { + flex-grow: 0 !important; + } + + .flex-md-grow-1 { + flex-grow: 1 !important; + } + + .flex-md-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-md-shrink-1 { + flex-shrink: 1 !important; + } + + .flex-md-wrap { + flex-wrap: wrap !important; + } + + .flex-md-nowrap { + flex-wrap: nowrap !important; + } + + .flex-md-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .gap-md-0 { + gap: 0 !important; + } + + .gap-md-1 { + gap: 0.25rem !important; + } + + .gap-md-2 { + gap: 0.5rem !important; + } + + .gap-md-3 { + gap: 1rem !important; + } + + .gap-md-4 { + gap: 1.5rem !important; + } + + .gap-md-5 { + gap: 3rem !important; + } + + .justify-content-md-start { + justify-content: flex-start !important; + } + + .justify-content-md-end { + justify-content: flex-end !important; + } + + .justify-content-md-center { + justify-content: center !important; + } + + .justify-content-md-between { + justify-content: space-between !important; + } + + .justify-content-md-around { + justify-content: space-around !important; + } + + .justify-content-md-evenly { + justify-content: space-evenly !important; + } + + .align-items-md-start { + align-items: flex-start !important; + } + + .align-items-md-end { + align-items: flex-end !important; + } + + .align-items-md-center { + align-items: center !important; + } + + .align-items-md-baseline { + align-items: baseline !important; + } + + .align-items-md-stretch { + align-items: stretch !important; + } + + .align-content-md-start { + align-content: flex-start !important; + } + + .align-content-md-end { + align-content: flex-end !important; + } + + .align-content-md-center { + align-content: center !important; + } + + .align-content-md-between { + align-content: space-between !important; + } + + .align-content-md-around { + align-content: space-around !important; + } + + .align-content-md-stretch { + align-content: stretch !important; + } + + .align-self-md-auto { + align-self: auto !important; + } + + .align-self-md-start { + align-self: flex-start !important; + } + + .align-self-md-end { + align-self: flex-end !important; + } + + .align-self-md-center { + align-self: center !important; + } + + .align-self-md-baseline { + align-self: baseline !important; + } + + .align-self-md-stretch { + align-self: stretch !important; + } + + .order-md-first { + order: -1 !important; + } + + .order-md-0 { + order: 0 !important; + } + + .order-md-1 { + order: 1 !important; + } + + .order-md-2 { + order: 2 !important; + } + + .order-md-3 { + order: 3 !important; + } + + .order-md-4 { + order: 4 !important; + } + + .order-md-5 { + order: 5 !important; + } + + .order-md-last { + order: 6 !important; + } + + .m-md-0 { + margin: 0 !important; + } + + .m-md-1 { + margin: 0.25rem !important; + } + + .m-md-2 { + margin: 0.5rem !important; + } + + .m-md-3 { + margin: 1rem !important; + } + + .m-md-4 { + margin: 1.5rem !important; + } + + .m-md-5 { + margin: 3rem !important; + } + + .m-md-auto { + margin: auto !important; + } + + .mx-md-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + + .mx-md-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + + .mx-md-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + + .mx-md-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + + .mx-md-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + + .mx-md-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + + .mx-md-auto { + margin-right: auto !important; + margin-left: auto !important; + } + + .my-md-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + + .my-md-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + + .my-md-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + + .my-md-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + + .my-md-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + + .my-md-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + + .my-md-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + + .mt-md-0 { + margin-top: 0 !important; + } + + .mt-md-1 { + margin-top: 0.25rem !important; + } + + .mt-md-2 { + margin-top: 0.5rem !important; + } + + .mt-md-3 { + margin-top: 1rem !important; + } + + .mt-md-4 { + margin-top: 1.5rem !important; + } + + .mt-md-5 { + margin-top: 3rem !important; + } + + .mt-md-auto { + margin-top: auto !important; + } + + .me-md-0 { + margin-right: 0 !important; + } + + .me-md-1 { + margin-right: 0.25rem !important; + } + + .me-md-2 { + margin-right: 0.5rem !important; + } + + .me-md-3 { + margin-right: 1rem !important; + } + + .me-md-4 { + margin-right: 1.5rem !important; + } + + .me-md-5 { + margin-right: 3rem !important; + } + + .me-md-auto { + margin-right: auto !important; + } + + .mb-md-0 { + margin-bottom: 0 !important; + } + + .mb-md-1 { + margin-bottom: 0.25rem !important; + } + + .mb-md-2 { + margin-bottom: 0.5rem !important; + } + + .mb-md-3 { + margin-bottom: 1rem !important; + } + + .mb-md-4 { + margin-bottom: 1.5rem !important; + } + + .mb-md-5 { + margin-bottom: 3rem !important; + } + + .mb-md-auto { + margin-bottom: auto !important; + } + + .ms-md-0 { + margin-left: 0 !important; + } + + .ms-md-1 { + margin-left: 0.25rem !important; + } + + .ms-md-2 { + margin-left: 0.5rem !important; + } + + .ms-md-3 { + margin-left: 1rem !important; + } + + .ms-md-4 { + margin-left: 1.5rem !important; + } + + .ms-md-5 { + margin-left: 3rem !important; + } + + .ms-md-auto { + margin-left: auto !important; + } + + .p-md-0 { + padding: 0 !important; + } + + .p-md-1 { + padding: 0.25rem !important; + } + + .p-md-2 { + padding: 0.5rem !important; + } + + .p-md-3 { + padding: 1rem !important; + } + + .p-md-4 { + padding: 1.5rem !important; + } + + .p-md-5 { + padding: 3rem !important; + } + + .px-md-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + + .px-md-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + + .px-md-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + + .px-md-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + + .px-md-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + + .px-md-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + + .py-md-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + + .py-md-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + + .py-md-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + + .py-md-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + + .py-md-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + + .py-md-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + + .pt-md-0 { + padding-top: 0 !important; + } + + .pt-md-1 { + padding-top: 0.25rem !important; + } + + .pt-md-2 { + padding-top: 0.5rem !important; + } + + .pt-md-3 { + padding-top: 1rem !important; + } + + .pt-md-4 { + padding-top: 1.5rem !important; + } + + .pt-md-5 { + padding-top: 3rem !important; + } + + .pe-md-0 { + padding-right: 0 !important; + } + + .pe-md-1 { + padding-right: 0.25rem !important; + } + + .pe-md-2 { + padding-right: 0.5rem !important; + } + + .pe-md-3 { + padding-right: 1rem !important; + } + + .pe-md-4 { + padding-right: 1.5rem !important; + } + + .pe-md-5 { + padding-right: 3rem !important; + } + + .pb-md-0 { + padding-bottom: 0 !important; + } + + .pb-md-1 { + padding-bottom: 0.25rem !important; + } + + .pb-md-2 { + padding-bottom: 0.5rem !important; + } + + .pb-md-3 { + padding-bottom: 1rem !important; + } + + .pb-md-4 { + padding-bottom: 1.5rem !important; + } + + .pb-md-5 { + padding-bottom: 3rem !important; + } + + .ps-md-0 { + padding-left: 0 !important; + } + + .ps-md-1 { + padding-left: 0.25rem !important; + } + + .ps-md-2 { + padding-left: 0.5rem !important; + } + + .ps-md-3 { + padding-left: 1rem !important; + } + + .ps-md-4 { + padding-left: 1.5rem !important; + } + + .ps-md-5 { + padding-left: 3rem !important; + } + + .text-md-start { + text-align: left !important; + } + + .text-md-end { + text-align: right !important; + } + + .text-md-center { + text-align: center !important; + } +} +@media (min-width: 992px) { + .float-lg-start { + float: left !important; + } + + .float-lg-end { + float: right !important; + } + + .float-lg-none { + float: none !important; + } + + .d-lg-inline { + display: inline !important; + } + + .d-lg-inline-block { + display: inline-block !important; + } + + .d-lg-block { + display: block !important; + } + + .d-lg-grid { + display: grid !important; + } + + .d-lg-table { + display: table !important; + } + + .d-lg-table-row { + display: table-row !important; + } + + .d-lg-table-cell { + display: table-cell !important; + } + + .d-lg-flex { + display: flex !important; + } + + .d-lg-inline-flex { + display: inline-flex !important; + } + + .d-lg-none { + display: none !important; + } + + .flex-lg-fill { + flex: 1 1 auto !important; + } + + .flex-lg-row { + flex-direction: row !important; + } + + .flex-lg-column { + flex-direction: column !important; + } + + .flex-lg-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-lg-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-lg-grow-0 { + flex-grow: 0 !important; + } + + .flex-lg-grow-1 { + flex-grow: 1 !important; + } + + .flex-lg-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-lg-shrink-1 { + flex-shrink: 1 !important; + } + + .flex-lg-wrap { + flex-wrap: wrap !important; + } + + .flex-lg-nowrap { + flex-wrap: nowrap !important; + } + + .flex-lg-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .gap-lg-0 { + gap: 0 !important; + } + + .gap-lg-1 { + gap: 0.25rem !important; + } + + .gap-lg-2 { + gap: 0.5rem !important; + } + + .gap-lg-3 { + gap: 1rem !important; + } + + .gap-lg-4 { + gap: 1.5rem !important; + } + + .gap-lg-5 { + gap: 3rem !important; + } + + .justify-content-lg-start { + justify-content: flex-start !important; + } + + .justify-content-lg-end { + justify-content: flex-end !important; + } + + .justify-content-lg-center { + justify-content: center !important; + } + + .justify-content-lg-between { + justify-content: space-between !important; + } + + .justify-content-lg-around { + justify-content: space-around !important; + } + + .justify-content-lg-evenly { + justify-content: space-evenly !important; + } + + .align-items-lg-start { + align-items: flex-start !important; + } + + .align-items-lg-end { + align-items: flex-end !important; + } + + .align-items-lg-center { + align-items: center !important; + } + + .align-items-lg-baseline { + align-items: baseline !important; + } + + .align-items-lg-stretch { + align-items: stretch !important; + } + + .align-content-lg-start { + align-content: flex-start !important; + } + + .align-content-lg-end { + align-content: flex-end !important; + } + + .align-content-lg-center { + align-content: center !important; + } + + .align-content-lg-between { + align-content: space-between !important; + } + + .align-content-lg-around { + align-content: space-around !important; + } + + .align-content-lg-stretch { + align-content: stretch !important; + } + + .align-self-lg-auto { + align-self: auto !important; + } + + .align-self-lg-start { + align-self: flex-start !important; + } + + .align-self-lg-end { + align-self: flex-end !important; + } + + .align-self-lg-center { + align-self: center !important; + } + + .align-self-lg-baseline { + align-self: baseline !important; + } + + .align-self-lg-stretch { + align-self: stretch !important; + } + + .order-lg-first { + order: -1 !important; + } + + .order-lg-0 { + order: 0 !important; + } + + .order-lg-1 { + order: 1 !important; + } + + .order-lg-2 { + order: 2 !important; + } + + .order-lg-3 { + order: 3 !important; + } + + .order-lg-4 { + order: 4 !important; + } + + .order-lg-5 { + order: 5 !important; + } + + .order-lg-last { + order: 6 !important; + } + + .m-lg-0 { + margin: 0 !important; + } + + .m-lg-1 { + margin: 0.25rem !important; + } + + .m-lg-2 { + margin: 0.5rem !important; + } + + .m-lg-3 { + margin: 1rem !important; + } + + .m-lg-4 { + margin: 1.5rem !important; + } + + .m-lg-5 { + margin: 3rem !important; + } + + .m-lg-auto { + margin: auto !important; + } + + .mx-lg-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + + .mx-lg-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + + .mx-lg-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + + .mx-lg-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + + .mx-lg-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + + .mx-lg-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + + .mx-lg-auto { + margin-right: auto !important; + margin-left: auto !important; + } + + .my-lg-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + + .my-lg-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + + .my-lg-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + + .my-lg-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + + .my-lg-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + + .my-lg-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + + .my-lg-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + + .mt-lg-0 { + margin-top: 0 !important; + } + + .mt-lg-1 { + margin-top: 0.25rem !important; + } + + .mt-lg-2 { + margin-top: 0.5rem !important; + } + + .mt-lg-3 { + margin-top: 1rem !important; + } + + .mt-lg-4 { + margin-top: 1.5rem !important; + } + + .mt-lg-5 { + margin-top: 3rem !important; + } + + .mt-lg-auto { + margin-top: auto !important; + } + + .me-lg-0 { + margin-right: 0 !important; + } + + .me-lg-1 { + margin-right: 0.25rem !important; + } + + .me-lg-2 { + margin-right: 0.5rem !important; + } + + .me-lg-3 { + margin-right: 1rem !important; + } + + .me-lg-4 { + margin-right: 1.5rem !important; + } + + .me-lg-5 { + margin-right: 3rem !important; + } + + .me-lg-auto { + margin-right: auto !important; + } + + .mb-lg-0 { + margin-bottom: 0 !important; + } + + .mb-lg-1 { + margin-bottom: 0.25rem !important; + } + + .mb-lg-2 { + margin-bottom: 0.5rem !important; + } + + .mb-lg-3 { + margin-bottom: 1rem !important; + } + + .mb-lg-4 { + margin-bottom: 1.5rem !important; + } + + .mb-lg-5 { + margin-bottom: 3rem !important; + } + + .mb-lg-auto { + margin-bottom: auto !important; + } + + .ms-lg-0 { + margin-left: 0 !important; + } + + .ms-lg-1 { + margin-left: 0.25rem !important; + } + + .ms-lg-2 { + margin-left: 0.5rem !important; + } + + .ms-lg-3 { + margin-left: 1rem !important; + } + + .ms-lg-4 { + margin-left: 1.5rem !important; + } + + .ms-lg-5 { + margin-left: 3rem !important; + } + + .ms-lg-auto { + margin-left: auto !important; + } + + .p-lg-0 { + padding: 0 !important; + } + + .p-lg-1 { + padding: 0.25rem !important; + } + + .p-lg-2 { + padding: 0.5rem !important; + } + + .p-lg-3 { + padding: 1rem !important; + } + + .p-lg-4 { + padding: 1.5rem !important; + } + + .p-lg-5 { + padding: 3rem !important; + } + + .px-lg-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + + .px-lg-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + + .px-lg-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + + .px-lg-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + + .px-lg-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + + .px-lg-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + + .py-lg-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + + .py-lg-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + + .py-lg-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + + .py-lg-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + + .py-lg-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + + .py-lg-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + + .pt-lg-0 { + padding-top: 0 !important; + } + + .pt-lg-1 { + padding-top: 0.25rem !important; + } + + .pt-lg-2 { + padding-top: 0.5rem !important; + } + + .pt-lg-3 { + padding-top: 1rem !important; + } + + .pt-lg-4 { + padding-top: 1.5rem !important; + } + + .pt-lg-5 { + padding-top: 3rem !important; + } + + .pe-lg-0 { + padding-right: 0 !important; + } + + .pe-lg-1 { + padding-right: 0.25rem !important; + } + + .pe-lg-2 { + padding-right: 0.5rem !important; + } + + .pe-lg-3 { + padding-right: 1rem !important; + } + + .pe-lg-4 { + padding-right: 1.5rem !important; + } + + .pe-lg-5 { + padding-right: 3rem !important; + } + + .pb-lg-0 { + padding-bottom: 0 !important; + } + + .pb-lg-1 { + padding-bottom: 0.25rem !important; + } + + .pb-lg-2 { + padding-bottom: 0.5rem !important; + } + + .pb-lg-3 { + padding-bottom: 1rem !important; + } + + .pb-lg-4 { + padding-bottom: 1.5rem !important; + } + + .pb-lg-5 { + padding-bottom: 3rem !important; + } + + .ps-lg-0 { + padding-left: 0 !important; + } + + .ps-lg-1 { + padding-left: 0.25rem !important; + } + + .ps-lg-2 { + padding-left: 0.5rem !important; + } + + .ps-lg-3 { + padding-left: 1rem !important; + } + + .ps-lg-4 { + padding-left: 1.5rem !important; + } + + .ps-lg-5 { + padding-left: 3rem !important; + } + + .text-lg-start { + text-align: left !important; + } + + .text-lg-end { + text-align: right !important; + } + + .text-lg-center { + text-align: center !important; + } +} +@media (min-width: 1200px) { + .float-xl-start { + float: left !important; + } + + .float-xl-end { + float: right !important; + } + + .float-xl-none { + float: none !important; + } + + .d-xl-inline { + display: inline !important; + } + + .d-xl-inline-block { + display: inline-block !important; + } + + .d-xl-block { + display: block !important; + } + + .d-xl-grid { + display: grid !important; + } + + .d-xl-table { + display: table !important; + } + + .d-xl-table-row { + display: table-row !important; + } + + .d-xl-table-cell { + display: table-cell !important; + } + + .d-xl-flex { + display: flex !important; + } + + .d-xl-inline-flex { + display: inline-flex !important; + } + + .d-xl-none { + display: none !important; + } + + .flex-xl-fill { + flex: 1 1 auto !important; + } + + .flex-xl-row { + flex-direction: row !important; + } + + .flex-xl-column { + flex-direction: column !important; + } + + .flex-xl-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-xl-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-xl-grow-0 { + flex-grow: 0 !important; + } + + .flex-xl-grow-1 { + flex-grow: 1 !important; + } + + .flex-xl-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-xl-shrink-1 { + flex-shrink: 1 !important; + } + + .flex-xl-wrap { + flex-wrap: wrap !important; + } + + .flex-xl-nowrap { + flex-wrap: nowrap !important; + } + + .flex-xl-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .gap-xl-0 { + gap: 0 !important; + } + + .gap-xl-1 { + gap: 0.25rem !important; + } + + .gap-xl-2 { + gap: 0.5rem !important; + } + + .gap-xl-3 { + gap: 1rem !important; + } + + .gap-xl-4 { + gap: 1.5rem !important; + } + + .gap-xl-5 { + gap: 3rem !important; + } + + .justify-content-xl-start { + justify-content: flex-start !important; + } + + .justify-content-xl-end { + justify-content: flex-end !important; + } + + .justify-content-xl-center { + justify-content: center !important; + } + + .justify-content-xl-between { + justify-content: space-between !important; + } + + .justify-content-xl-around { + justify-content: space-around !important; + } + + .justify-content-xl-evenly { + justify-content: space-evenly !important; + } + + .align-items-xl-start { + align-items: flex-start !important; + } + + .align-items-xl-end { + align-items: flex-end !important; + } + + .align-items-xl-center { + align-items: center !important; + } + + .align-items-xl-baseline { + align-items: baseline !important; + } + + .align-items-xl-stretch { + align-items: stretch !important; + } + + .align-content-xl-start { + align-content: flex-start !important; + } + + .align-content-xl-end { + align-content: flex-end !important; + } + + .align-content-xl-center { + align-content: center !important; + } + + .align-content-xl-between { + align-content: space-between !important; + } + + .align-content-xl-around { + align-content: space-around !important; + } + + .align-content-xl-stretch { + align-content: stretch !important; + } + + .align-self-xl-auto { + align-self: auto !important; + } + + .align-self-xl-start { + align-self: flex-start !important; + } + + .align-self-xl-end { + align-self: flex-end !important; + } + + .align-self-xl-center { + align-self: center !important; + } + + .align-self-xl-baseline { + align-self: baseline !important; + } + + .align-self-xl-stretch { + align-self: stretch !important; + } + + .order-xl-first { + order: -1 !important; + } + + .order-xl-0 { + order: 0 !important; + } + + .order-xl-1 { + order: 1 !important; + } + + .order-xl-2 { + order: 2 !important; + } + + .order-xl-3 { + order: 3 !important; + } + + .order-xl-4 { + order: 4 !important; + } + + .order-xl-5 { + order: 5 !important; + } + + .order-xl-last { + order: 6 !important; + } + + .m-xl-0 { + margin: 0 !important; + } + + .m-xl-1 { + margin: 0.25rem !important; + } + + .m-xl-2 { + margin: 0.5rem !important; + } + + .m-xl-3 { + margin: 1rem !important; + } + + .m-xl-4 { + margin: 1.5rem !important; + } + + .m-xl-5 { + margin: 3rem !important; + } + + .m-xl-auto { + margin: auto !important; + } + + .mx-xl-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + + .mx-xl-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + + .mx-xl-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + + .mx-xl-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + + .mx-xl-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + + .mx-xl-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + + .mx-xl-auto { + margin-right: auto !important; + margin-left: auto !important; + } + + .my-xl-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + + .my-xl-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + + .my-xl-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + + .my-xl-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + + .my-xl-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + + .my-xl-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + + .my-xl-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + + .mt-xl-0 { + margin-top: 0 !important; + } + + .mt-xl-1 { + margin-top: 0.25rem !important; + } + + .mt-xl-2 { + margin-top: 0.5rem !important; + } + + .mt-xl-3 { + margin-top: 1rem !important; + } + + .mt-xl-4 { + margin-top: 1.5rem !important; + } + + .mt-xl-5 { + margin-top: 3rem !important; + } + + .mt-xl-auto { + margin-top: auto !important; + } + + .me-xl-0 { + margin-right: 0 !important; + } + + .me-xl-1 { + margin-right: 0.25rem !important; + } + + .me-xl-2 { + margin-right: 0.5rem !important; + } + + .me-xl-3 { + margin-right: 1rem !important; + } + + .me-xl-4 { + margin-right: 1.5rem !important; + } + + .me-xl-5 { + margin-right: 3rem !important; + } + + .me-xl-auto { + margin-right: auto !important; + } + + .mb-xl-0 { + margin-bottom: 0 !important; + } + + .mb-xl-1 { + margin-bottom: 0.25rem !important; + } + + .mb-xl-2 { + margin-bottom: 0.5rem !important; + } + + .mb-xl-3 { + margin-bottom: 1rem !important; + } + + .mb-xl-4 { + margin-bottom: 1.5rem !important; + } + + .mb-xl-5 { + margin-bottom: 3rem !important; + } + + .mb-xl-auto { + margin-bottom: auto !important; + } + + .ms-xl-0 { + margin-left: 0 !important; + } + + .ms-xl-1 { + margin-left: 0.25rem !important; + } + + .ms-xl-2 { + margin-left: 0.5rem !important; + } + + .ms-xl-3 { + margin-left: 1rem !important; + } + + .ms-xl-4 { + margin-left: 1.5rem !important; + } + + .ms-xl-5 { + margin-left: 3rem !important; + } + + .ms-xl-auto { + margin-left: auto !important; + } + + .p-xl-0 { + padding: 0 !important; + } + + .p-xl-1 { + padding: 0.25rem !important; + } + + .p-xl-2 { + padding: 0.5rem !important; + } + + .p-xl-3 { + padding: 1rem !important; + } + + .p-xl-4 { + padding: 1.5rem !important; + } + + .p-xl-5 { + padding: 3rem !important; + } + + .px-xl-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + + .px-xl-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + + .px-xl-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + + .px-xl-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + + .px-xl-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + + .px-xl-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + + .py-xl-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + + .py-xl-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + + .py-xl-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + + .py-xl-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + + .py-xl-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + + .py-xl-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + + .pt-xl-0 { + padding-top: 0 !important; + } + + .pt-xl-1 { + padding-top: 0.25rem !important; + } + + .pt-xl-2 { + padding-top: 0.5rem !important; + } + + .pt-xl-3 { + padding-top: 1rem !important; + } + + .pt-xl-4 { + padding-top: 1.5rem !important; + } + + .pt-xl-5 { + padding-top: 3rem !important; + } + + .pe-xl-0 { + padding-right: 0 !important; + } + + .pe-xl-1 { + padding-right: 0.25rem !important; + } + + .pe-xl-2 { + padding-right: 0.5rem !important; + } + + .pe-xl-3 { + padding-right: 1rem !important; + } + + .pe-xl-4 { + padding-right: 1.5rem !important; + } + + .pe-xl-5 { + padding-right: 3rem !important; + } + + .pb-xl-0 { + padding-bottom: 0 !important; + } + + .pb-xl-1 { + padding-bottom: 0.25rem !important; + } + + .pb-xl-2 { + padding-bottom: 0.5rem !important; + } + + .pb-xl-3 { + padding-bottom: 1rem !important; + } + + .pb-xl-4 { + padding-bottom: 1.5rem !important; + } + + .pb-xl-5 { + padding-bottom: 3rem !important; + } + + .ps-xl-0 { + padding-left: 0 !important; + } + + .ps-xl-1 { + padding-left: 0.25rem !important; + } + + .ps-xl-2 { + padding-left: 0.5rem !important; + } + + .ps-xl-3 { + padding-left: 1rem !important; + } + + .ps-xl-4 { + padding-left: 1.5rem !important; + } + + .ps-xl-5 { + padding-left: 3rem !important; + } + + .text-xl-start { + text-align: left !important; + } + + .text-xl-end { + text-align: right !important; + } + + .text-xl-center { + text-align: center !important; + } +} +@media (min-width: 1400px) { + .float-xxl-start { + float: left !important; + } + + .float-xxl-end { + float: right !important; + } + + .float-xxl-none { + float: none !important; + } + + .d-xxl-inline { + display: inline !important; + } + + .d-xxl-inline-block { + display: inline-block !important; + } + + .d-xxl-block { + display: block !important; + } + + .d-xxl-grid { + display: grid !important; + } + + .d-xxl-table { + display: table !important; + } + + .d-xxl-table-row { + display: table-row !important; + } + + .d-xxl-table-cell { + display: table-cell !important; + } + + .d-xxl-flex { + display: flex !important; + } + + .d-xxl-inline-flex { + display: inline-flex !important; + } + + .d-xxl-none { + display: none !important; + } + + .flex-xxl-fill { + flex: 1 1 auto !important; + } + + .flex-xxl-row { + flex-direction: row !important; + } + + .flex-xxl-column { + flex-direction: column !important; + } + + .flex-xxl-row-reverse { + flex-direction: row-reverse !important; + } + + .flex-xxl-column-reverse { + flex-direction: column-reverse !important; + } + + .flex-xxl-grow-0 { + flex-grow: 0 !important; + } + + .flex-xxl-grow-1 { + flex-grow: 1 !important; + } + + .flex-xxl-shrink-0 { + flex-shrink: 0 !important; + } + + .flex-xxl-shrink-1 { + flex-shrink: 1 !important; + } + + .flex-xxl-wrap { + flex-wrap: wrap !important; + } + + .flex-xxl-nowrap { + flex-wrap: nowrap !important; + } + + .flex-xxl-wrap-reverse { + flex-wrap: wrap-reverse !important; + } + + .gap-xxl-0 { + gap: 0 !important; + } + + .gap-xxl-1 { + gap: 0.25rem !important; + } + + .gap-xxl-2 { + gap: 0.5rem !important; + } + + .gap-xxl-3 { + gap: 1rem !important; + } + + .gap-xxl-4 { + gap: 1.5rem !important; + } + + .gap-xxl-5 { + gap: 3rem !important; + } + + .justify-content-xxl-start { + justify-content: flex-start !important; + } + + .justify-content-xxl-end { + justify-content: flex-end !important; + } + + .justify-content-xxl-center { + justify-content: center !important; + } + + .justify-content-xxl-between { + justify-content: space-between !important; + } + + .justify-content-xxl-around { + justify-content: space-around !important; + } + + .justify-content-xxl-evenly { + justify-content: space-evenly !important; + } + + .align-items-xxl-start { + align-items: flex-start !important; + } + + .align-items-xxl-end { + align-items: flex-end !important; + } + + .align-items-xxl-center { + align-items: center !important; + } + + .align-items-xxl-baseline { + align-items: baseline !important; + } + + .align-items-xxl-stretch { + align-items: stretch !important; + } + + .align-content-xxl-start { + align-content: flex-start !important; + } + + .align-content-xxl-end { + align-content: flex-end !important; + } + + .align-content-xxl-center { + align-content: center !important; + } + + .align-content-xxl-between { + align-content: space-between !important; + } + + .align-content-xxl-around { + align-content: space-around !important; + } + + .align-content-xxl-stretch { + align-content: stretch !important; + } + + .align-self-xxl-auto { + align-self: auto !important; + } + + .align-self-xxl-start { + align-self: flex-start !important; + } + + .align-self-xxl-end { + align-self: flex-end !important; + } + + .align-self-xxl-center { + align-self: center !important; + } + + .align-self-xxl-baseline { + align-self: baseline !important; + } + + .align-self-xxl-stretch { + align-self: stretch !important; + } + + .order-xxl-first { + order: -1 !important; + } + + .order-xxl-0 { + order: 0 !important; + } + + .order-xxl-1 { + order: 1 !important; + } + + .order-xxl-2 { + order: 2 !important; + } + + .order-xxl-3 { + order: 3 !important; + } + + .order-xxl-4 { + order: 4 !important; + } + + .order-xxl-5 { + order: 5 !important; + } + + .order-xxl-last { + order: 6 !important; + } + + .m-xxl-0 { + margin: 0 !important; + } + + .m-xxl-1 { + margin: 0.25rem !important; + } + + .m-xxl-2 { + margin: 0.5rem !important; + } + + .m-xxl-3 { + margin: 1rem !important; + } + + .m-xxl-4 { + margin: 1.5rem !important; + } + + .m-xxl-5 { + margin: 3rem !important; + } + + .m-xxl-auto { + margin: auto !important; + } + + .mx-xxl-0 { + margin-right: 0 !important; + margin-left: 0 !important; + } + + .mx-xxl-1 { + margin-right: 0.25rem !important; + margin-left: 0.25rem !important; + } + + .mx-xxl-2 { + margin-right: 0.5rem !important; + margin-left: 0.5rem !important; + } + + .mx-xxl-3 { + margin-right: 1rem !important; + margin-left: 1rem !important; + } + + .mx-xxl-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important; + } + + .mx-xxl-5 { + margin-right: 3rem !important; + margin-left: 3rem !important; + } + + .mx-xxl-auto { + margin-right: auto !important; + margin-left: auto !important; + } + + .my-xxl-0 { + margin-top: 0 !important; + margin-bottom: 0 !important; + } + + .my-xxl-1 { + margin-top: 0.25rem !important; + margin-bottom: 0.25rem !important; + } + + .my-xxl-2 { + margin-top: 0.5rem !important; + margin-bottom: 0.5rem !important; + } + + .my-xxl-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important; + } + + .my-xxl-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important; + } + + .my-xxl-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important; + } + + .my-xxl-auto { + margin-top: auto !important; + margin-bottom: auto !important; + } + + .mt-xxl-0 { + margin-top: 0 !important; + } + + .mt-xxl-1 { + margin-top: 0.25rem !important; + } + + .mt-xxl-2 { + margin-top: 0.5rem !important; + } + + .mt-xxl-3 { + margin-top: 1rem !important; + } + + .mt-xxl-4 { + margin-top: 1.5rem !important; + } + + .mt-xxl-5 { + margin-top: 3rem !important; + } + + .mt-xxl-auto { + margin-top: auto !important; + } + + .me-xxl-0 { + margin-right: 0 !important; + } + + .me-xxl-1 { + margin-right: 0.25rem !important; + } + + .me-xxl-2 { + margin-right: 0.5rem !important; + } + + .me-xxl-3 { + margin-right: 1rem !important; + } + + .me-xxl-4 { + margin-right: 1.5rem !important; + } + + .me-xxl-5 { + margin-right: 3rem !important; + } + + .me-xxl-auto { + margin-right: auto !important; + } + + .mb-xxl-0 { + margin-bottom: 0 !important; + } + + .mb-xxl-1 { + margin-bottom: 0.25rem !important; + } + + .mb-xxl-2 { + margin-bottom: 0.5rem !important; + } + + .mb-xxl-3 { + margin-bottom: 1rem !important; + } + + .mb-xxl-4 { + margin-bottom: 1.5rem !important; + } + + .mb-xxl-5 { + margin-bottom: 3rem !important; + } + + .mb-xxl-auto { + margin-bottom: auto !important; + } + + .ms-xxl-0 { + margin-left: 0 !important; + } + + .ms-xxl-1 { + margin-left: 0.25rem !important; + } + + .ms-xxl-2 { + margin-left: 0.5rem !important; + } + + .ms-xxl-3 { + margin-left: 1rem !important; + } + + .ms-xxl-4 { + margin-left: 1.5rem !important; + } + + .ms-xxl-5 { + margin-left: 3rem !important; + } + + .ms-xxl-auto { + margin-left: auto !important; + } + + .p-xxl-0 { + padding: 0 !important; + } + + .p-xxl-1 { + padding: 0.25rem !important; + } + + .p-xxl-2 { + padding: 0.5rem !important; + } + + .p-xxl-3 { + padding: 1rem !important; + } + + .p-xxl-4 { + padding: 1.5rem !important; + } + + .p-xxl-5 { + padding: 3rem !important; + } + + .px-xxl-0 { + padding-right: 0 !important; + padding-left: 0 !important; + } + + .px-xxl-1 { + padding-right: 0.25rem !important; + padding-left: 0.25rem !important; + } + + .px-xxl-2 { + padding-right: 0.5rem !important; + padding-left: 0.5rem !important; + } + + .px-xxl-3 { + padding-right: 1rem !important; + padding-left: 1rem !important; + } + + .px-xxl-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important; + } + + .px-xxl-5 { + padding-right: 3rem !important; + padding-left: 3rem !important; + } + + .py-xxl-0 { + padding-top: 0 !important; + padding-bottom: 0 !important; + } + + .py-xxl-1 { + padding-top: 0.25rem !important; + padding-bottom: 0.25rem !important; + } + + .py-xxl-2 { + padding-top: 0.5rem !important; + padding-bottom: 0.5rem !important; + } + + .py-xxl-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important; + } + + .py-xxl-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important; + } + + .py-xxl-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important; + } + + .pt-xxl-0 { + padding-top: 0 !important; + } + + .pt-xxl-1 { + padding-top: 0.25rem !important; + } + + .pt-xxl-2 { + padding-top: 0.5rem !important; + } + + .pt-xxl-3 { + padding-top: 1rem !important; + } + + .pt-xxl-4 { + padding-top: 1.5rem !important; + } + + .pt-xxl-5 { + padding-top: 3rem !important; + } + + .pe-xxl-0 { + padding-right: 0 !important; + } + + .pe-xxl-1 { + padding-right: 0.25rem !important; + } + + .pe-xxl-2 { + padding-right: 0.5rem !important; + } + + .pe-xxl-3 { + padding-right: 1rem !important; + } + + .pe-xxl-4 { + padding-right: 1.5rem !important; + } + + .pe-xxl-5 { + padding-right: 3rem !important; + } + + .pb-xxl-0 { + padding-bottom: 0 !important; + } + + .pb-xxl-1 { + padding-bottom: 0.25rem !important; + } + + .pb-xxl-2 { + padding-bottom: 0.5rem !important; + } + + .pb-xxl-3 { + padding-bottom: 1rem !important; + } + + .pb-xxl-4 { + padding-bottom: 1.5rem !important; + } + + .pb-xxl-5 { + padding-bottom: 3rem !important; + } + + .ps-xxl-0 { + padding-left: 0 !important; + } + + .ps-xxl-1 { + padding-left: 0.25rem !important; + } + + .ps-xxl-2 { + padding-left: 0.5rem !important; + } + + .ps-xxl-3 { + padding-left: 1rem !important; + } + + .ps-xxl-4 { + padding-left: 1.5rem !important; + } + + .ps-xxl-5 { + padding-left: 3rem !important; + } + + .text-xxl-start { + text-align: left !important; + } + + .text-xxl-end { + text-align: right !important; + } + + .text-xxl-center { + text-align: center !important; + } +} +@media (min-width: 1200px) { + .fs-1 { + font-size: 2.5rem !important; + } + + .fs-2 { + font-size: 2rem !important; + } + + .fs-3 { + font-size: 1.75rem !important; + } + + .fs-4 { + font-size: 1.5rem !important; + } +} +@media print { + .d-print-inline { + display: inline !important; + } + + .d-print-inline-block { + display: inline-block !important; + } + + .d-print-block { + display: block !important; + } + + .d-print-grid { + display: grid !important; + } + + .d-print-table { + display: table !important; + } + + .d-print-table-row { + display: table-row !important; + } + + .d-print-table-cell { + display: table-cell !important; + } + + .d-print-flex { + display: flex !important; + } + + .d-print-inline-flex { + display: inline-flex !important; + } + + .d-print-none { + display: none !important; + } +} + diff --git a/assets/css/hesabix-admin.css b/assets/css/hesabix-admin.css new file mode 100644 index 0000000..f5212b0 --- /dev/null +++ b/assets/css/hesabix-admin.css @@ -0,0 +1,2816 @@ +/* + * Hesabix Admin CSS + * + * @package Hesabix + * @author Mohammad Rezai + * @author URI https://pirouz.xyz + * @since 1.0.0 + */ + +*, +.rtl h1, +.rtl h2, +.rtl h3, +.rtl h4, +.rtl h5, +.rtl h6 { + box-sizing: border-box; + font-family: 'IRANYekanWeb'; +} + + +.hesabix-stats-loading { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 2rem; + grid-column: 1 / -1; +} + +.hesabix-spinner { + width: 40px; + height: 40px; + border: 4px solid #e3e6ea; + border-top: 4px solid #007cba; + border-radius: 50%; + animation: hesabix-spin 1s linear infinite; + margin-bottom: 1rem; +} + +@keyframes hesabix-spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + + +.hesabix-stats-loading { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 60px 20px; + text-align: center; +} + +.hesabix-stats-loading .hesabix-spinner { + width: 40px; + height: 40px; + border: 4px solid #f3f3f3; + border-top: 4px solid #0073aa; + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 20px; +} + +.hesabix-stats-loading p { + color: #666; + font-size: 16px; + margin: 0; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + + + +.hesabix-feature-card.not-connected .hesabix-feature-icon svg { + color: #dc3545; +} + +.hesabix-feature-card.not-connected .hesabix-feature-icon { + background: rgba(220, 53, 69, 0.1) !important; +} + +.hesabix-feature-card.connected .hesabix-feature-icon svg { + animation: hesabix-pulse 1.2s infinite; + color: #667eea; + border-radius: 50%; +} + +@keyframes hesabix-pulse { + 0% { + box-shadow: 0 0 0 0 #667eea; + opacity: 1; + } + + 70% { + box-shadow: 0 0 0 10px rgba(40, 167, 69, 0.5); + } + + 100% { + box-shadow: 0 0 0 0 rgba(40, 167, 69, 0); + } +} + +body.hesabix-admin { + font-family: 'IRANYekanWeb'; + background: #f8f9fa; + margin: 0; + padding: 0; + direction: rtl; + text-align: right; + line-height: 1.6; + color: #333; +} + + +.hesabix-container { + max-width: 1400px; + margin: 0 auto; + padding: 20px; +} + +.hesabix-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 20px; + margin-bottom: 40px; + padding: 30px; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + border-radius: 15px; + color: white; + box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3); +} + +.hesabix-info { + flex: 1; +} + +.hesabix-actions { + display: flex; + gap: 10px; + flex-wrap: wrap; +} + +.hesabix-logo { + width: 80px; + height: 80px; + background: rgba(255, 255, 255, 0.2); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.hesabix-logo img { + width: 50px; + height: 50px; + filter: brightness(0) invert(1); +} + +.hesabix-title { + margin: 0 0 10px 0; + font-size: 2.5rem; + font-weight: 700; +} + +.hesabix-subtitle { + font-size: 1.1rem; + margin: 0 0 15px 0; + opacity: 0.9; +} + +.hesabix-badges { + display: flex; + gap: 10px; +} + +.hesabix-badge { + padding: 5px 12px; + border-radius: 20px; + font-size: 0.9rem; + font-weight: 600; + display: flex; + align-items: center; + gap: 8px; +} + +.hesabix-badge.version { + background: rgba(255, 255, 255, 0.2); +} + +.hesabix-badge.status { + background: #28a745; + color: white; + border: 1px solid #28a745; +} + +.hesabix-badge.warning { + background: #ffc107; + color: #212529; + border: 1px solid #ffc107; +} + +.hesabix-badge.danger { + background: #dc3545; + color: white; + border: 1px solid #dc3545; +} + +.hesabix-badge.info { + background: #17a2b8; +} + +.hesabix-update-badge { + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 8px; + background: rgba(102, 126, 234, 0.1); + color: #667eea; + border: 1px solid rgba(102, 126, 234, 0.2); +} + +.hesabix-update-badge:hover { + background: rgba(102, 126, 234, 0.15); + transform: translateY(-1px); + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.2); +} + +.hesabix-update-badge:disabled { + opacity: 0.6; + cursor: not-allowed; + transform: none; +} + + +.hesabix-badge.status { + cursor: default; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 8px; +} + +.hesabix-badge.warning { + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 8px; +} + +.hesabix-badge.warning:hover { + background: #e0a800; + transform: translateY(-1px); + box-shadow: 0 2px 8px rgba(255, 193, 7, 0.3); +} + +.hesabix-badge.danger { + cursor: default; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 8px; +} + +.hesabix-spinner-small { + width: 12px; + height: 12px; + border: 2px solid #e3e6ea; + border-top: 2px solid #667eea; + border-radius: 50%; + animation: hesabix-spin 1s linear infinite; +} + + +.hesabix-card { + background: white; + border-radius: 15px; + padding: 30px; + margin-bottom: 30px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.hesabix-card:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); +} + +.hesabix-card-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 25px; + padding-bottom: 15px; + border-bottom: 3px solid #667eea; +} + +.hesabix-card-title { + margin: 0; + font-size: 1.8rem; + color: #333; + font-weight: 700; +} + +.hesabix-card-subtitle { + margin: 5px 0 0 0; + color: #666; + font-size: 1rem; +} + + +.hesabix-grid { + display: grid; + gap: 25px; +} + +.hesabix-grid-2 { + grid-template-columns: repeat(2, 1fr); +} + +.hesabix-grid-3 { + grid-template-columns: repeat(3, 1fr); +} + +.hesabix-grid-4 { + grid-template-columns: repeat(4, 1fr); +} + + +.hesabix-feature-card { + padding: 25px; + border-radius: 12px; + background: #f8f9fa; + border-left: 4px solid #667eea; + transition: transform 0.3s ease, box-shadow 0.3s ease; + text-align: center; +} + +.hesabix-feature-card:hover { + transform: translateY(-5px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); +} + +.hesabix-feature-icon { + font-size: 2.5rem; + color: #667eea; + margin-bottom: 15px; + width: 80px; + height: 80px; + display: flex; + align-items: center; + justify-content: center; + background: rgba(102, 126, 234, 0.1); + border-radius: 50%; + margin: 0 auto 15px auto; +} + +.hesabix-feature-card h3 { + margin: 0 0 10px 0; + font-size: 1.3rem; + color: #333; +} + +.hesabix-feature-card p { + margin: 0; + color: #666; + line-height: 1.6; +} + + +.hesabix-btn { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 12px 24px; + border-radius: 8px; + text-decoration: none; + font-weight: 600; + transition: all 0.3s ease; + border: none; + cursor: pointer; + font-size: 0.95rem; + text-align: center; + justify-content: center; + min-width: 120px; +} + +.hesabix-btn:hover { + transform: translateY(-2px); + text-decoration: none; +} + +.hesabix-btn-primary { + background: #667eea; + color: white; +} + +.hesabix-btn-primary:hover { + background: #5a6fd8; + color: white; +} + +.hesabix-btn-success { + background: #28a745; + color: white; +} + +.hesabix-btn-success:hover { + background: #218838; + color: white; +} + +.hesabix-btn-warning { + background: #ffc107; + color: #212529; +} + +.hesabix-btn-warning:hover { + background: #e0a800; + color: #212529; +} + +.hesabix-btn-danger { + background: #dc3545; + color: white; +} + +.hesabix-btn-danger:hover { + background: #c82333; + color: white; +} + +.hesabix-btn-info { + background: #17a2b8; + color: white; +} + +.hesabix-btn-info:hover { + background: #138496; + color: white; +} + +.hesabix-btn-secondary { + background: #6c757d; + color: white; +} + +.hesabix-btn-secondary:hover { + background: #5a6268; + color: white; +} + +.hesabix-btn-outline { + background: transparent; + border: 2px solid #667eea; + color: #667eea; +} + +.hesabix-btn-outline:hover { + background: #667eea; + color: white; +} + +.hesabix-btn-sm { + padding: 8px 16px; + font-size: 0.85rem; + min-width: 80px; +} + +.hesabix-btn-lg { + padding: 15px 30px; + font-size: 1.1rem; + min-width: 150px; +} + +.hesabix-btn-group { + display: flex; + gap: 10px; + flex-wrap: wrap; +} + + +.hesabix-form-actions { + display: flex; + justify-content: flex-end; + gap: 15px; + margin-top: 30px; + padding-top: 20px; + border-top: 2px solid #e9ecef; +} + + +.hesabix-form-group { + margin-bottom: 28px; +} + +.hesabix-form-label { + margin-bottom: 10px; + font-size: 1rem; + font-weight: 600; + color: #374151; +} + +.hesabix-form-control { + width: 100%; + padding: 12px 15px; + border: 2px solid #e9ecef; + border-radius: 8px; + font-size: 1rem; + transition: border-color 0.3s ease, box-shadow 0.3s ease; + background: white; +} + +.hesabix-form-control:focus { + outline: none; + border-color: #667eea; + box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); +} + +.hesabix-form-control.error { + border-color: #dc3545; +} + +.hesabix-form-control.success { + border-color: #28a745; +} + +.hesabix-form-text { + display: block; + margin-top: 10px; + color: #6c757d; + font-size: 0.95rem; + background: #f8fafc; + border-radius: 6px; + padding: 10px 14px; + border-right: 3px solid #667eea; + font-weight: 500; + line-height: 1.7; +} + +.hesabix-form-text.error { + color: #dc3545; +} + +.hesabix-form-text.success { + color: #28a745; +} + + +.hesabix-table { + width: 100%; + border-collapse: collapse; + background: white; + border-radius: 12px; + overflow: hidden; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + margin-bottom: 20px; +} + +.hesabix-table th { + background: #667eea; + color: white; + padding: 15px; + text-align: right; + font-weight: 600; + font-size: 0.95rem; +} + +.hesabix-table td { + padding: 12px 15px; + text-align: right; + border-bottom: 1px solid #e9ecef; + vertical-align: middle; +} + +.hesabix-table tr:hover { + background: #f8f9fa; +} + +.hesabix-table tr:last-child td { + border-bottom: none; +} + + +.hesabix-table-container { + overflow-x: auto; + border-radius: 12px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + background: white; + margin-bottom: 20px; +} + +.hesabix-table-container .hesabix-table { + margin-bottom: 0; + box-shadow: none; + border-radius: 0; +} + + +@media (max-width: 768px) { + .hesabix-table-container { + border-radius: 8px; + margin: 0 -10px 20px -10px; + } + + .hesabix-table-container .hesabix-table { + min-width: 600px; + } + + .hesabix-table-container .hesabix-table th, + .hesabix-table-container .hesabix-table td { + padding: 10px 8px; + font-size: 0.9rem; + } + + .hesabix-table-container .hesabix-table th { + font-size: 0.85rem; + padding: 12px 8px; + } + + + .hesabix-table-container .hesabix-switch { + transform: scale(0.9); + margin: 0 auto; + display: block; + } + + + .hesabix-table-container .hesabix-input { + font-size: 0.85rem; + padding: 6px 8px; + min-width: 80px; + } +} + +@media (max-width: 480px) { + .hesabix-table-container { + margin: 0 -15px 20px -15px; + border-radius: 6px; + } + + .hesabix-table-container .hesabix-table { + min-width: 500px; + } + + .hesabix-table-container .hesabix-table th, + .hesabix-table-container .hesabix-table td { + padding: 8px 6px; + font-size: 0.8rem; + } + + .hesabix-table-container .hesabix-table th { + font-size: 0.8rem; + padding: 10px 6px; + } + + .hesabix-table-container .hesabix-switch { + transform: scale(0.8); + } + + .hesabix-table-container .hesabix-input { + font-size: 0.8rem; + padding: 4px 6px; + min-width: 60px; + } +} + + +.hesabix-section:has(.hesabix-table-container) { + background: #f8f9fa; + border-radius: 12px; + padding: 20px; + margin-bottom: 30px; +} + +.hesabix-section:has(.hesabix-table-container) .hesabix-section-title { + margin-bottom: 15px; + color: #495057; + font-size: 1.1rem; +} + +.hesabix-section:has(.hesabix-table-container) .hesabix-section-description { + margin-bottom: 20px; + color: #6c757d; + font-size: 0.95rem; + line-height: 1.5; +} + + +.hesabix-field-group { + margin-bottom: 25px; + padding: 15px; + background: white; + border-radius: 8px; + border: 1px solid #e9ecef; +} + +.hesabix-field-label { + display: block; + font-weight: 600; + color: #495057; + margin-bottom: 10px; + font-size: 0.95rem; +} + +.hesabix-radio-group { + display: flex; + flex-direction: column; + gap: 12px; +} + +.hesabix-radio { + display: flex; + align-items: center; + gap: 10px; + padding: 10px; + border-radius: 6px; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.hesabix-radio:hover { + background: #f8f9fa; +} + +.hesabix-radio input[type="radio"] { + margin: 0; +} + +.hesabix-radio-custom { + width: 18px; + height: 18px; + border: 2px solid #dee2e6; + border-radius: 50%; + position: relative; + transition: all 0.2s ease; +} + +.hesabix-radio input[type="radio"]:checked+.hesabix-radio-custom { + border-color: #667eea; + background: #667eea; +} + +.hesabix-radio input[type="radio"]:checked+.hesabix-radio-custom::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 6px; + height: 6px; + background: white; + border-radius: 50%; +} + + +@media (max-width: 768px) { + .hesabix-field-group { + padding: 12px; + margin-bottom: 20px; + } + + .hesabix-field-label { + font-size: 0.9rem; + margin-bottom: 8px; + } + + .hesabix-radio { + padding: 8px; + font-size: 0.9rem; + } + + .hesabix-radio-custom { + width: 16px; + height: 16px; + } + + .hesabix-radio input[type="radio"]:checked+.hesabix-radio-custom::after { + width: 5px; + height: 5px; + } +} + +@media (max-width: 480px) { + .hesabix-field-group { + padding: 10px; + margin-bottom: 15px; + } + + .hesabix-field-label { + font-size: 0.85rem; + margin-bottom: 6px; + } + + .hesabix-radio { + padding: 6px; + font-size: 0.85rem; + } + + .hesabix-radio-custom { + width: 14px; + height: 14px; + } + + .hesabix-radio input[type="radio"]:checked+.hesabix-radio-custom::after { + width: 4px; + height: 4px; + } +} + + +.hesabix-alert { + padding: 15px 20px; + border-radius: 10px; + margin-bottom: 20px; + border: 1px solid transparent; + display: flex; + align-items: center; + gap: 10px; +} + +.hesabix-alert-success { + background: #d4edda; + border-color: #c3e6cb !important; + color: #155724; +} + +.hesabix-alert-danger { + background: #f8d7da; + border-color: #f5c6cb !important; + color: #721c24; +} + +.hesabix-alert-warning { + background: #fff3cd; + border-color: #ffeaa7 !important; + color: #856404; +} + +.hesabix-alert-info { + background: #d1ecf1; + border-color: #bee5eb !important; + color: #0c5460; +} + +.hesabix-alert-primary { + background: #cce7ff; + border-color: #b3d9ff !important; + color: #004085; +} + + +.hesabix-progress { + width: 100%; + height: 20px; + background: #e9ecef; + border-radius: 10px; + overflow: hidden; + margin: 10px 0; +} + +.hesabix-progress-bar { + height: 100%; + background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); + border-radius: 10px; + transition: width 0.3s ease; + display: flex; + align-items: center; + justify-content: center; + color: white; + font-size: 0.8rem; + font-weight: 600; +} + + +.hesabix-tabs { + display: flex; + border-bottom: 2px solid #e9ecef; + margin-bottom: 30px; + overflow-x: auto; + justify-content: flex-start; + text-align: right; + gap: 5px; + padding: 0 10px; +} + +.hesabix-tab { + padding: 15px 20px; + background: none; + border: none; + cursor: pointer; + font-weight: 600; + color: #6c757d; + transition: all 0.3s ease; + white-space: nowrap; + border-bottom: 3px solid transparent; + border-radius: 8px 8px 0 0; + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; + min-height: 50px; +} + +.hesabix-tab:hover { + color: #667eea; + background: rgba(102, 126, 234, 0.08); + transform: translateY(-2px); +} + +.hesabix-tab.active { + color: #667eea; + border-bottom-color: #667eea; + background: rgba(102, 126, 234, 0.12); + box-shadow: 0 2px 8px rgba(102, 126, 234, 0.15); + transform: none !important; +} + +.hesabix-tab-content { + display: none; +} + +.hesabix-tab-content.active { + display: block; +} + + +.hesabix-modal { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + z-index: 9999; + align-items: center; + justify-content: center; +} + +.hesabix-modal.show { + display: flex; +} + +.hesabix-modal-content { + background: white; + border-radius: 15px; + padding: 30px; + max-width: 600px; + width: 90%; + max-height: 80vh; + overflow-y: auto; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); +} + +.hesabix-modal-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; + padding-bottom: 15px; + border-bottom: 2px solid #e9ecef; +} + +.hesabix-modal-title { + margin: 0; + font-size: 1.5rem; + color: #333; +} + +.hesabix-modal-close { + background: none; + border: none; + font-size: 1.5rem; + cursor: pointer; + color: #6c757d; + padding: 0; + width: 30px; + height: 30px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + transition: all 0.3s ease; +} + +.hesabix-modal-close:hover { + background: #f8f9fa; + color: #333; +} + + +.hesabix-loading { + display: inline-block; + width: 20px; + height: 20px; + border: 3px solid #f3f3f3; + border-top: 3px solid #667eea; + border-radius: 50%; + animation: hesabix-spin 1s linear infinite; +} + +@keyframes hesabix-spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + + +.hesabix-text-center { + text-align: center; +} + +.hesabix-text-right { + text-align: right; +} + +.hesabix-text-left { + text-align: left; +} + +.hesabix-mt-0 { + margin-top: 0; +} + +.hesabix-mt-1 { + margin-top: 0.25rem; +} + +.hesabix-mt-2 { + margin-top: 0.5rem; +} + +.hesabix-mt-3 { + margin-top: 1rem; +} + +.hesabix-mt-4 { + margin-top: 1.5rem; +} + +.hesabix-mt-5 { + margin-top: 3rem; +} + +.hesabix-mb-0 { + margin-bottom: 0; +} + +.hesabix-mb-1 { + margin-bottom: 0.25rem; +} + +.hesabix-mb-2 { + margin-bottom: 0.5rem; +} + +.hesabix-mb-3 { + margin-bottom: 1rem; +} + +.hesabix-mb-4 { + margin-bottom: 1.5rem; +} + +.hesabix-mb-5 { + margin-bottom: 3rem; +} + +.hesabix-p-0 { + padding: 0; +} + +.hesabix-p-1 { + padding: 0.25rem; +} + +.hesabix-p-2 { + padding: 0.5rem; +} + +.hesabix-p-3 { + padding: 1rem; +} + +.hesabix-p-4 { + padding: 1.5rem; +} + +.hesabix-p-5 { + padding: 3rem; +} + +.hesabix-d-none { + display: none; +} + +.hesabix-d-block { + display: block; +} + +.hesabix-d-flex { + display: flex; +} + +.hesabix-d-grid { + display: grid; +} + +.hesabix-w-100 { + width: 100%; +} + +.hesabix-h-100 { + height: 100%; +} + + +@media (max-width: 768px) { + .hesabix-container { + padding: 15px; + } + + .hesabix-header { + flex-direction: column; + text-align: center; + padding: 20px; + gap: 15px; + } + + .hesabix-logo { + width: 60px; + height: 60px; + } + + .hesabix-title { + font-size: 1.8rem; + } + + .hesabix-subtitle { + font-size: 1rem; + } + + .hesabix-card { + padding: 20px; + } + + .hesabix-grid-2, + .hesabix-grid-3, + .hesabix-grid-4 { + grid-template-columns: 1fr; + gap: 20px; + } + + .hesabix-feature-card { + padding: 20px; + } + + .hesabix-feature-icon { + width: 60px; + height: 60px; + font-size: 2rem; + } + + .hesabix-btn-group { + flex-direction: column; + } + + .hesabix-btn { + width: 100%; + } + + .hesabix-tabs { + flex-direction: column; + gap: 2px; + } + + .hesabix-tab { + text-align: center; + border-bottom: none; + border-right: 3px solid transparent; + border-radius: 0 8px 8px 0; + min-height: 45px; + } + + .hesabix-tab.active { + border-right-color: #667eea; + border-bottom-color: transparent; + } + + #hesabix_sync_orders { + flex-direction: column; + gap: 10px; + } + + .order-sync-card { + grid-column: 1/1 !important; + } +} + +@media (max-width: 480px) { + .hesabix-container { + padding: 10px; + } + + .hesabix-header { + padding: 15px; + } + + .hesabix-title { + font-size: 1.5rem; + } + + .hesabix-subtitle { + font-size: 0.9rem; + } + + .hesabix-card-title { + font-size: 1.4rem; + } + + .hesabix-feature-card h3 { + font-size: 1.1rem; + } +} + + +.wp-admin .hesabix-admin { + margin-top: 32px; +} + +.wp-admin .hesabix-admin .hesabix-container { + margin-top: 20px; +} + + +.hesabix-admin ::-webkit-scrollbar { + width: 8px; +} + +.hesabix-admin ::-webkit-scrollbar-track { + background: #f1f1f1; + border-radius: 4px; +} + +.hesabix-admin ::-webkit-scrollbar-thumb { + background: #667eea; + border-radius: 4px; +} + +.hesabix-admin ::-webkit-scrollbar-thumb:hover { + background: #5a6fd8; +} + + +@keyframes hesabix-fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +.hesabix-fade-in { + animation: hesabix-fadeIn 0.5s ease-out; +} + + +@media print { + .hesabix-admin { + background: white; + } + + .hesabix-card { + box-shadow: none; + border: 1px solid #ddd; + } + + .hesabix-btn { + display: none; + } +} + + +.hesabix-setup-steps { + display: flex; + flex-direction: column; + gap: 20px; +} + +.hesabix-setup-step { + display: flex; + align-items: flex-start; + gap: 20px; + padding: 20px; + background: #f8f9fa; + border-radius: 12px; + border-left: 4px solid #667eea; + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.hesabix-setup-step:hover { + transform: translateX(-5px); + box-shadow: 0 4px 15px rgba(102, 126, 234, 0.2); +} + +.hesabix-step-number { + width: 40px; + height: 40px; + background: #667eea; + color: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + font-size: 1.2rem; + flex-shrink: 0; +} + +.hesabix-step-content h4 { + margin: 0 0 8px 0; + color: #333; + font-size: 1.2rem; + font-weight: 600; +} + +.hesabix-step-content p { + margin: 0; + color: #666; + line-height: 1.6; +} + + +.hand { + cursor: pointer; +} + +.hesabix-tab-icon { + width: 18px; + height: 18px; + opacity: 0.8; + transition: opacity 0.3s ease; +} + +.hesabix-tab:hover .hesabix-tab-icon { + opacity: 1; +} + +.hesabix-tab.active .hesabix-tab-icon { + opacity: 1; +} + +.hesabix-bold { + font-weight: bold; +} + +.hesabix-plugin-tutorial-chapter { + color: #667eea; + font-weight: bold; + border-bottom: 1px solid #e9ecef; + margin-bottom: 5px; + padding-bottom: 10px; + margin-top: 10px; + transition: color 0.3s ease; +} + +.hesabix-plugin-tutorial-chapter:hover { + color: #5a6fd8; + cursor: pointer; +} + + +.hesabix-section { + margin-bottom: 32px; + padding-bottom: 24px; + +} + +.hesabix-section:last-child { + border-bottom: none; + margin-bottom: 0; + padding-bottom: 0; +} + +.hesabix-section-title { + font-size: 18px; + font-weight: 600; + color: #374151; + margin-bottom: 16px; + padding-bottom: 8px; + border-bottom: 2px solid #e5e7eb; +} + + +.hesabix-card form table { + width: 100%; + border-collapse: collapse; + margin-bottom: 0; +} + +.hesabix-card form table th { + padding: 10px 12px; + text-align: right; + font-weight: 600; + color: #374151; + + width: 20%; + vertical-align: middle; + font-size: 15px; + position: relative; + + font-family: 'IRANYekanWeb'; +} + +.hesabix-card form table th label { + font-weight: 600; + color: #374151; + font-size: 15px; + margin: 0; + display: block; + line-height: 1.5; + text-align: right; + padding: 0; + background: none; + border: none; + box-shadow: none; + font-family: 'IRANYekanWeb'; +} + +.hesabix-card form table th label:focus { + outline: none; + box-shadow: none; + border: none; +} + +.hesabix-card form table td { + padding: 20px; + border-bottom: 1px solid #e2e8f0; + vertical-align: top; + display: flex; + flex-direction: column; + background: white; + position: relative; +} + +.hesabix-card form input[type="text"], +.hesabix-card form input[type="password"], +.hesabix-card form input[type="email"], +.hesabix-card form input[type="number"], +.hesabix-card form select, +.hesabix-card form textarea { + width: 100%; + max-width: 450px; + padding: 14px 18px; + border: 2px solid #e2e8f0; + border-radius: 10px; + font-size: 14px; + transition: all 0.3s ease; + background: white; + font-family: 'IRANYekanWeb'; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.hesabix-card form input[type="text"]:focus, +.hesabix-card form input[type="password"]:focus, +.hesabix-card form input[type="email"]:focus, +.hesabix-card form input[type="number"]:focus, +.hesabix-card form select:focus, +.hesabix-card form textarea:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15), 0 4px 12px rgba(59, 130, 246, 0.1); + transform: translateY(-1px); +} + +.hesabix-card form input[type="checkbox"] { + width: 18px; + height: 18px; + border: 2px solid #d1d5db; + border-radius: 4px; + cursor: pointer; +} + +.hesabix-card form input[type="radio"] { + width: 18px; + height: 18px; + border: 2px solid #d1d5db; + cursor: pointer; +} + +.hesabix-card form label { + font-weight: 500; + color: #374151; + display: block; +} + +.hesabix-card form .description { + color: #64748b; + font-size: 13px; + margin-top: 8px; + line-height: 1.5; + padding: 8px 12px; + background: #f8fafc; + border-radius: 6px; + border-right: 3px solid #3b82f6; + font-weight: 500; + display: inline-block; + max-width: 450px; +} + + +.hesabix-btn.loading { + position: relative; + color: transparent; +} + +.hesabix-btn.loading::after { + content: ''; + color: white !important; + position: absolute; + top: 50%; + left: 50%; + width: 16px; + height: 16px; + margin: -8px 0 0 -8px; + border: 2px solid transparent; + border-top: 2px solid currentColor; + border-radius: 50%; + animation: hesabix-spin 1s linear infinite; +} + +.hesabix-message { + padding: 12px 16px; + border-radius: 6px; + font-size: 14px; + font-weight: 500; + margin-top: 16px; + border: 1px solid; +} + +.hesabix-message.success { + background-color: #f0fdf4; + border-color: #22c55e; + color: #166534; +} + +.hesabix-message.error { + background-color: #fef2f2; + border-color: #ef4444; + color: #991b1b; +} + +.hesabix-message svg { + flex-shrink: 0; +} + + +.hesabix-message { + padding: 12px 16px; + border-radius: 8px; + margin-bottom: 16px; + font-weight: 500; +} + +.hesabix-message.success { + background: #d1fae5; + color: #065f46; + border: 1px solid #a7f3d0; + padding: 12px 16px; +} + +.hesabix-message.error { + background: #fee2e2; + color: #991b1b; + border: 1px solid #fecaca; + padding: 12px 16px; +} + +.hesabix-message.warning { + background: #fef3c7; + color: #92400e; + border: 1px solid #fde68a; + padding: 12px 16px; +} + + +.hesabix-switch { + position: relative; + display: inline-block; + width: 46px; + height: 24px; + vertical-align: middle; + margin-left: 10px; +} + +.hesabix-switch input { + opacity: 0; + width: 0; + height: 0; +} + +.hesabix-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + transition: .4s; + border-radius: 24px; +} + +.hesabix-slider:before { + position: absolute; + content: ""; + height: 18px; + width: 18px; + left: 3px; + bottom: 3px; + background-color: white; + transition: .4s; + border-radius: 50%; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15); +} + +.hesabix-switch input:checked+.hesabix-slider { + background-color: #667eea; +} + +.hesabix-switch input:checked+.hesabix-slider:before { + transform: translateX(22px); +} + +.hesabix-switch .hesabix-slider { + box-shadow: 0 2px 4px rgba(102, 126, 234, 0.08); +} + + +#log-history-list { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)) !important; + gap: 10px !important; + margin-top: 12px !important; +} + +.log-date-btn { + position: relative !important; + border: 2px solid #e1e5e9 !important; + border-radius: 6px !important; + padding: 12px 16px !important; + background: #fff !important; + cursor: pointer !important; + transition: all 0.3s ease !important; + display: flex !important; + align-items: center !important; + gap: 10px !important; + font-size: 13px !important; + font-weight: 500 !important; + color: #23282d !important; + text-decoration: none !important; +} + +.log-date-btn:hover { + border-color: #0073aa !important; + box-shadow: 0 2px 6px rgba(0, 115, 170, 0.12) !important; + transform: translateY(-1px) !important; + color: #23282d !important; +} + +.log-date-btn.active { + border-color: #0073aa !important; + background: #f0f8ff !important; + box-shadow: 0 2px 6px rgba(0, 115, 170, 0.18) !important; + color: #23282d !important; + padding-right: 44px !important; +} + +.log-date-btn:focus { + outline: none !important; + box-shadow: 0 0 0 3px rgba(0, 115, 170, 0.1) !important; +} + +.log-date-btn.active::after { + content: '📄' !important; + position: absolute !important; + right: 16px !important; + top: 50% !important; + transform: translateY(-50%) !important; + width: 20px !important; + border-radius: 50% !important; + background: #0073aa !important; + color: #fff !important; + font-size: 10px !important; + font-weight: bold !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + padding: 2px !important; + padding-top: 4px !important; +} + +.hesabix-btn:disabled, +.hesabix-btn[disabled] { + opacity: 0.5 !important; + pointer-events: none !important; + filter: grayscale(0.3); + cursor: not-allowed !important; +} + +.hesabix-version-card { + direction: rtl !important; + background: linear-gradient(135deg, #374896 0%, #422361 50%, #5d495f 100%) !important; + color: #fff; + box-shadow: 0 8px 32px rgba(102, 126, 234, 0.25), 0 4px 16px rgba(240, 147, 251, 0.15); + border-radius: 24px; + padding: 40px; + margin-bottom: 32px; + display: flex; + align-items: center; + gap: 32px; + position: relative; + overflow: hidden; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.hesabix-version-card:hover { + box-shadow: 0 12px 40px rgba(102, 126, 234, 0.35), 0 8px 24px rgba(240, 147, 251, 0.25); +} + +.hesabix-version-card .hesabix-version-icon { + width: 40px; + height: 40px; + background: rgba(255, 255, 255, 0.15); + backdrop-filter: blur(10px); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7); + animation: hesabix-pulse 2s infinite cubic-bezier(0.66, 0, 0, 1); + margin-left: 24px; + position: relative; + z-index: 2; + border: 2px solid rgba(255, 255, 255, 0.2); +} + +.hesabix-version-card .hesabix-version-icon svg { + width: 20px; + height: 20px; + color: #fff; + filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1)); +} + +@keyframes hesabix-pulse { + 0% { + box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7); + transform: scale(1); + } + + 50% { + box-shadow: 0 0 0 20px rgba(255, 255, 255, 0); + transform: scale(1.05); + } + + 100% { + box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); + transform: scale(1); + } +} + +@keyframes hesabix-shimmer { + + 0%, + 100% { + transform: rotate(0deg); + } + + 50% { + transform: rotate(180deg); + } +} + +@keyframes hesabix-glow { + + 0%, + 100% { + opacity: 0.3; + } + + 50% { + opacity: 0.7; + } +} + +.hesabix-version-card .hesabix-version-info { + display: flex; + flex-direction: column; + gap: 12px; + position: relative; + z-index: 2; + flex: 1; +} + +.hesabix-version-card .hesabix-version-title { + font-size: 1.5rem; + font-weight: 800; + margin-bottom: 4px; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + letter-spacing: -0.5px; +} + +.hesabix-version-card .hesabix-version-row { + font-size: 1.1rem; + font-weight: 500; + margin-bottom: 4px; + opacity: 0.95; + display: flex; + align-items: center; + gap: 8px; + padding: 8px 16px; + background: rgba(255, 255, 255, 0.1); + border-radius: 12px; + backdrop-filter: blur(5px); + border: 1px solid rgba(255, 255, 255, 0.1); + transition: all 0.3s ease; +} + +.hesabix-version-card .hesabix-version-row:hover { + background: rgba(255, 255, 255, 0.15); + transform: translateX(-4px); +} + +.hesabix-version-card .hesabix-version-row::before { + content: '•'; + width: 10px; + height: 12px; + color: #fff; + font-weight: bold; + font-size: 1.2rem; + margin-top: auto; + margin-bottom: auto; +} + +.hesabix-version-section { + margin-bottom: 20px; + padding: 16px; + background: rgba(255, 255, 255, 0.08); + border-radius: 12px; + border: 1px solid rgba(255, 255, 255, 0.1); + backdrop-filter: blur(10px); +} + +.hesabix-version-section:last-child { + margin-bottom: 0; +} + +.hesabix-version-section-title { + font-size: 1.1rem; + font-weight: 700; + color: #fff; + margin-bottom: 12px; + padding-bottom: 8px; + border-bottom: 2px solid rgba(255, 255, 255, 0.2); + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.hesabix-version-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 8px; +} + +.hesabix-version-row { + display: flex; + justify-content: center; + align-items: center; + padding: 8px 12px; + background: rgba(255, 255, 255, 0.05); + border-radius: 8px; + border: 1px solid rgba(255, 255, 255, 0.1); + transition: all 0.3s ease; +} + +.hesabix-version-row:hover { + background: rgba(255, 255, 255, 0.1); + transform: translateX(-2px); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.hesabix-version-label { + font-weight: 600; + color: rgba(255, 255, 255, 0.9); + font-size: 0.95rem; +} + +.hesabix-version-value { + font-weight: 500; + color: #fff; + font-size: 0.95rem; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); +} + + +@media (max-width: 768px) { + .hesabix-version-card { + flex-direction: column; + text-align: center; + padding: 30px 24px; + gap: 24px; + } + + .hesabix-version-card .hesabix-version-icon { + margin-left: 10px; + width: 40px; + height: 40px; + } + + .hesabix-version-card .hesabix-version-icon svg { + width: 20px; + height: 20px; + } + + .hesabix-version-card .hesabix-version-title { + font-size: 0.8rem; + } + + .hesabix-version-card .hesabix-version-row { + font-size: 1rem; + padding: 6px 12px; + } + + .hesabix-version-grid { + grid-template-columns: 1fr; + } + + .hesabix-version-section { + padding: 12px; + } + + .hesabix-version-section-title { + font-size: 1rem; + } + + .hesabix-version-label, + .hesabix-version-value { + font-size: 0.9rem; + } +} + +.wp-die-message, +p { + margin-top: 0.25em !important; +} + +.signature-button { + position: relative; + overflow: hidden; +} + +.signature-button::before { + content: ''; + position: absolute; + top: 0; + left: -75%; + width: 30%; + height: 100%; + background: linear-gradient(100deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.1) 25%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.1) 75%, rgba(255, 255, 255, 0) 100%); + transform: skewX(-18deg); + animation: shine-anim 5s infinite; + pointer-events: none; +} + +@keyframes shine-anim { + 0% { + left: -75%; + } + + 100% { + left: 130%; + } +} + +@media screen and (max-width: 782px) { + .hesabix-logo img { + width: 35px !important; + height: 35px !important; + } +} + + +.hesabix-status-selector { + margin: 20px 0; +} + +.hesabix-status-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 12px; + margin-top: 12px; +} + +.hesabix-status-item { + position: relative; + border: 2px solid #e1e5e9; + border-radius: 8px; + padding: 16px; + background: #fff; + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 12px; +} + +.hesabix-status-item:hover { + border-color: #0073aa; + box-shadow: 0 2px 8px rgba(0, 115, 170, 0.15); + transform: translateY(-1px); +} + +.hesabix-status-item.selected { + border-color: #0073aa; + background: #f0f8ff; + box-shadow: 0 2px 8px rgba(0, 115, 170, 0.2); +} + +.hesabix-status-item input[type="checkbox"] { + position: absolute; + opacity: 0; + pointer-events: none; +} + +.hesabix-status-icon { + width: 24px; + height: 24px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.hesabix-status-icon svg { + width: 16px; + height: 16px; + fill: currentColor; +} + +.hesabix-status-content { + flex: 1; +} + +.hesabix-status-title { + font-weight: 600; + color: #23282d; + margin-bottom: 4px; + font-size: 14px; +} + +.hesabix-status-description { + font-size: 12px; + color: #666; + line-height: 1.4; +} + + +.hesabix-status-pending .hesabix-status-icon { + background: #ffba00; + color: #fff; +} + +.hesabix-status-processing .hesabix-status-icon { + background: #0073aa; + color: #fff; +} + +.hesabix-status-on-hold .hesabix-status-icon { + background: #f7b100; + color: #fff; +} + +.hesabix-status-completed .hesabix-status-icon { + background: #46b450; + color: #fff; +} + +.hesabix-status-cancelled .hesabix-status-icon { + background: #dc3232; + color: #fff; +} + +.hesabix-status-refunded .hesabix-status-icon { + background: #a0a5aa; + color: #fff; +} + +.hesabix-status-failed .hesabix-status-icon { + background: #dc3232; + color: #fff; +} + +.hesabix-status-checkout-draft .hesabix-status-icon { + background: #6c757d; + color: #fff; +} + + +.hesabix-status-item.selected.hesabix-status-pending { + border-color: #ffba00; + background: #fffbf0; +} + +.hesabix-status-item.selected.hesabix-status-processing { + border-color: #0073aa; + background: #f0f8ff; +} + +.hesabix-status-item.selected.hesabix-status-on-hold { + border-color: #f7b100; + background: #fffbf0; +} + +.hesabix-status-item.selected.hesabix-status-completed { + border-color: #46b450; + background: #f0fff0; +} + +.hesabix-status-item.selected.hesabix-status-cancelled { + border-color: #dc3232; + background: #fff0f0; +} + +.hesabix-status-item.selected.hesabix-status-refunded { + border-color: #a0a5aa; + background: #f8f9fa; +} + +.hesabix-status-item.selected.hesabix-status-failed { + border-color: #dc3232; + background: #fff0f0; +} + +.hesabix-status-item.selected.hesabix-status-checkout-draft { + border-color: #6c757d; + background: #f8f9fa; +} + + +@media (max-width: 768px) { + .hesabix-status-grid { + grid-template-columns: 1fr; + } + + .hesabix-status-item { + padding: 12px; + } +} + + +.hesabix-status-counter { + margin-top: 12px; + padding: 8px 12px; + background: #f8f9fa; + border-radius: 4px; + font-size: 12px; + color: #666; + border: 1px solid #e1e5e9; +} + +.hesabix-status-counter strong { + color: #0073aa; +} + + +.hesabix-date-presets { + margin-bottom: 16px; +} + +.hesabix-date-presets>div { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + gap: 10px; + margin-top: 12px; +} + +.hesabix-date-preset-btn { + position: relative; + border: 2px solid #e1e5e9; + border-radius: 6px; + padding: 12px 16px; + background: #fff; + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 10px; + font-size: 13px; + font-weight: 500; + color: #23282d; +} + +.hesabix-date-preset-btn:hover { + border-color: #0073aa; + box-shadow: 0 2px 6px rgba(0, 115, 170, 0.12); + transform: translateY(-1px); +} + +.hesabix-date-preset-btn.active { + border-color: #0073aa; + background: #f0f8ff; + box-shadow: 0 2px 6px rgba(0, 115, 170, 0.18); + padding-right: 44px; +} + +.hesabix-date-preset-btn:focus { + outline: none; + box-shadow: 0 0 0 3px rgba(0, 115, 170, 0.1); +} + +.hesabix-date-preset-btn.active::after { + content: '✓'; + position: absolute; + right: 16px; + top: 50%; + transform: translateY(-50%); + width: 20px; + height: 20px; + border-radius: 50%; + background: #0073aa; + color: #fff; + font-size: 12px; + font-weight: bold; + display: flex; + align-items: center; + justify-content: center; + padding: 2px !important; + padding-top: 4px !important; +} + +.hesabix-date-range-container { + margin: 16px 0; +} + +.hesabix-date-range-wrapper { + display: flex; + align-items: flex-end; + gap: 16px; + flex-wrap: wrap; +} + +.hesabix-date-field { + display: flex; + flex-direction: column; + gap: 6px; + flex: 1; + min-width: 160px; +} + +.hesabix-date-label { + font-size: 14px; + font-weight: 500; + color: #374151; + margin-bottom: 4px; +} + +.hesabix-date-input { + padding: 10px 12px; + border: 1px solid #d1d5db; + border-radius: 6px; + font-size: 14px; + background: #ffffff; + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.hesabix-date-input:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +.hesabix-date-input.error { + border-color: #dc2626; + box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1); +} + +.hesabix-date-arrow { + display: flex; + align-items: center; + justify-content: center; + color: #6b7280; + margin-bottom: 8px; + flex-shrink: 0; +} + +.hesabix-selected-range { + animation: hesabix-fade-in 0.3s ease; +} + +@keyframes hesabix-fade-in { + from { + opacity: 0; + transform: translateY(-10px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + + +@media (max-width: 768px) { + .hesabix-date-range-wrapper { + flex-direction: column; + align-items: stretch; + } + + .hesabix-date-field { + min-width: unset; + } + + .hesabix-date-arrow { + transform: rotate(-90deg); + margin: 8px 0; + } + + .hesabix-date-presets>div { + grid-template-columns: 1fr !important; + } + + .hesabix-date-preset-btn { + width: 100%; + justify-content: flex-start; + } + + #log-history-list { + grid-template-columns: 1fr !important; + } + + .log-date-btn { + width: 100% !important; + justify-content: flex-start !important; + } +} + + +.hesabix-freight-switch-container { + margin: 16px 0; +} + +.hesabix-freight-options { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 12px; + margin-bottom: 16px; +} + +.hesabix-freight-option { + position: relative; + border: 2px solid #e1e5e9; + border-radius: 8px; + padding: 16px; + background: #fff; + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 12px; +} + +.hesabix-freight-option:hover { + border-color: #0073aa; + box-shadow: 0 2px 8px rgba(0, 115, 170, 0.15); + transform: translateY(-1px); +} + +.hesabix-freight-option.active { + border-color: #0073aa; + background: #f0f8ff; + box-shadow: 0 2px 8px rgba(0, 115, 170, 0.2); +} + +.hesabix-freight-option-content { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + width: 100%; +} + +.hesabix-freight-icon { + width: 24px; + height: 24px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + background: #f8f9fa; + transition: all 0.3s ease; +} + +.hesabix-freight-option.active .hesabix-freight-icon { + background: #0073aa; + color: #fff; +} + +.hesabix-freight-icon svg { + width: 16px; + height: 16px; + fill: currentColor; +} + +.hesabix-freight-option:not(.active) .hesabix-freight-icon { + color: #6b7280; +} + +.hesabix-freight-title { + font-weight: 600; + color: #23282d; + margin-bottom: 4px; + font-size: 14px; +} + +.hesabix-freight-desc { + font-size: 12px; + color: #666; + line-height: 1.4; +} + +.hesabix-freight-option.active .hesabix-freight-title { + color: #0073aa; +} + +.hesabix-freight-option.active .hesabix-freight-desc { + color: #0369a1; +} + + +.hesabix-freight-option[data-value="disabled"] .hesabix-freight-icon { + background: #dc2626; + color: #fff; +} + +.hesabix-freight-option[data-value="disabled"].active .hesabix-freight-title { + color: #dc2626; +} + +.hesabix-freight-option[data-value="disabled"].active .hesabix-freight-desc { + color: #b91c1c; +} + +.hesabix-freight-option[data-value="disabled"].active { + border-color: #dc2626; + background: #fef2f2; +} + + +.hesabix-freight-option[data-value="0"] .hesabix-freight-icon { + background: #16a34a; + color: #fff; +} + +.hesabix-freight-option[data-value="0"].active .hesabix-freight-title { + color: #16a34a; +} + +.hesabix-freight-option[data-value="0"].active .hesabix-freight-desc { + color: #15803d; +} + +.hesabix-freight-option[data-value="0"].active { + border-color: #16a34a; + background: #f0fdf4; +} + + +.hesabix-freight-option[data-value="1"] .hesabix-freight-icon { + background: #eab308; + color: #fff; +} + +.hesabix-freight-option[data-value="1"].active .hesabix-freight-title { + color: #eab308; +} + +.hesabix-freight-option[data-value="1"].active .hesabix-freight-desc { + color: #ca8a04; +} + +.hesabix-freight-option[data-value="1"].active { + border-color: #eab308; + background: #fefce8; +} + + +@media (max-width: 768px) { + .hesabix-freight-options { + grid-template-columns: 1fr; + } + + .hesabix-freight-option { + padding: 14px; + } + + .hesabix-freight-option-content { + gap: 10px; + } + + .hesabix-card-header { + flex-direction: column !important; + align-items: flex-start !important; + gap: 10px !important; + } + + .hesabix-card-header .hesabix-card-subtitle { + font-size: 0.8rem !important; + } + + .hesabix-alert { + display: block !important; + } + + .hesabix-card form table th { + width: 100% !important; + } + + .form-table td fieldset label { + display: flex !important; + flex-direction: column !important; + gap: 10px !important; + } + + .hesabix-form-actions { + display: flex !important; + flex-direction: column !important; + gap: 10px !important; + align-items: flex-start !important; + } +} + +ul { + list-style: disc; +} + +@media screen and (min-width: 992px) { + .hesabix-alert ul { + margin-right: 45px; + } +} + + +.custom-api-address-field { + display: none; +} + +.custom-api-address-field.show { + display: table-row; +} + + +.hesabix-api-error-container { + text-align: center; + padding: 40px 20px; + background: #fff; + border-radius: 10px; + box-shadow: 0 4px 20px rgba(102, 126, 234, 0.1); + margin: 20px 0; + border: 1px solid #e9ecef; + max-width: 500px; + margin-left: auto; + margin-right: auto; +} + +.hesabix-api-error-container .hesabix-error-icon { + margin-bottom: 20px; + display: flex; + justify-content: center; +} + +.hesabix-api-error-container .hesabix-error-icon svg { + width: 64px; + height: 64px; + color: #dc3545; + opacity: 0.8; +} + +.hesabix-api-error-container h3 { + color: #dc3545; + margin-bottom: 15px; + font-size: 18px; + font-weight: 600; + margin-top: 0; +} + +.hesabix-api-error-container p { + color: #6c757d; + margin-bottom: 25px; + font-size: 14px; + line-height: 1.6; + margin-top: 0; +} + +.hesabix-api-error-container .hesabix-error-actions { + margin-top: 25px; +} + +.hesabix-api-error-container .hesabix-btn { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 12px 24px; + border-radius: 8px; + text-decoration: none; + font-weight: 600; + transition: all 0.3s ease; + border: none; + cursor: pointer; + font-size: 0.95rem; + text-align: center; + justify-content: center; + min-width: 120px; + background: #667eea; + color: white; +} + +.hesabix-api-error-container .hesabix-btn:hover { + background: #5a6fd8; + color: white; + transform: translateY(-2px); + text-decoration: none; +} + +.hesabix-api-error-container .hesabix-btn svg { + width: 16px; + height: 16px; + fill: currentColor; +} + +@media (max-width: 768px) { + .hesabix-api-error-container { + padding: 30px 15px; + margin: 15px 10px; + } + + .hesabix-api-error-container .hesabix-error-icon svg { + width: 48px; + height: 48px; + } + + .hesabix-api-error-container h3 { + font-size: 16px; + } + + .hesabix-api-error-container p { + font-size: 13px; + } +} + + +.hesabix-radio-text { + flex: 1; + font-size: 0.95rem; + color: #495057; + line-height: 1.4; +} + +.hesabix-radio input[type="radio"] { + display: none; +} + + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + + +.hesabix-table-container.disabled-fields { + opacity: 0.6; + pointer-events: none; +} + +.hesabix-table-container.disabled-fields input[type="checkbox"], +.hesabix-table-container.disabled-fields input[type="text"] { + opacity: 0.5; + cursor: not-allowed; +} + +.hesabix-table-container.disabled-fields .hesabix-switch { + opacity: 0.5; + cursor: not-allowed; +} + +table tr:last-child td { + border-bottom: none; +} + +#footer-left { + display: flex; + justify-content: center; + align-items: center; + gap: 2px; +} + +#footer-left .signature-button { + margin-right: 10px; +} + +.hesabix-date-input-jalali { + font-family: 'Tahoma', 'Arial', sans-serif; + font-size: 14px; + padding: 8px 12px; + border: 1px solid #d1d5db; + border-radius: 6px; + background-color: #ffffff; + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +.hesabix-date-input-jalali:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +.hesabix-date-input-jalali.error { + border-color: #dc2626; + box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1); +} + +.hesabix-date-input-jalali::placeholder { + color: #9ca3af; + font-size: 13px; +} + +.hesabix-date-field { + display: flex; + flex-direction: column; + gap: 4px; +} + +.hesabix-date-label { + font-weight: 500; + color: #374151; + font-size: 14px; +} + +.hesabix-date-range-wrapper { + display: flex; + align-items: flex-end; + gap: 12px; + flex-wrap: wrap; +} + +.hesabix-date-arrow { + display: flex; + align-items: center; + color: #6b7280; + margin-bottom: 4px; +} + +@media (max-width: 768px) { + .hesabix-date-range-wrapper { + flex-direction: column; + align-items: stretch; + gap: 8px; + } + + .hesabix-date-arrow { + display: none; + } + + .hesabix-date-input-jalali { + width: 100%; + } +} + +.hesabix-date-field input { + padding: 10px 12px !important; +} \ No newline at end of file diff --git a/admin/fonts/eot/IRANYekanWebBlack.eot b/assets/fonts/eot/IRANYekanWebBlack.eot similarity index 100% rename from admin/fonts/eot/IRANYekanWebBlack.eot rename to assets/fonts/eot/IRANYekanWebBlack.eot diff --git a/admin/fonts/eot/IRANYekanWebBold.eot b/assets/fonts/eot/IRANYekanWebBold.eot similarity index 100% rename from admin/fonts/eot/IRANYekanWebBold.eot rename to assets/fonts/eot/IRANYekanWebBold.eot diff --git a/admin/fonts/eot/IRANYekanWebExtraBlack.eot b/assets/fonts/eot/IRANYekanWebExtraBlack.eot similarity index 100% rename from admin/fonts/eot/IRANYekanWebExtraBlack.eot rename to assets/fonts/eot/IRANYekanWebExtraBlack.eot diff --git a/admin/fonts/eot/IRANYekanWebExtraBold.eot b/assets/fonts/eot/IRANYekanWebExtraBold.eot similarity index 100% rename from admin/fonts/eot/IRANYekanWebExtraBold.eot rename to assets/fonts/eot/IRANYekanWebExtraBold.eot diff --git a/admin/fonts/eot/IRANYekanWebLight.eot b/assets/fonts/eot/IRANYekanWebLight.eot similarity index 100% rename from admin/fonts/eot/IRANYekanWebLight.eot rename to assets/fonts/eot/IRANYekanWebLight.eot diff --git a/admin/fonts/eot/IRANYekanWebMedium.eot b/assets/fonts/eot/IRANYekanWebMedium.eot similarity index 100% rename from admin/fonts/eot/IRANYekanWebMedium.eot rename to assets/fonts/eot/IRANYekanWebMedium.eot diff --git a/admin/fonts/eot/IRANYekanWebRegular.eot b/assets/fonts/eot/IRANYekanWebRegular.eot similarity index 100% rename from admin/fonts/eot/IRANYekanWebRegular.eot rename to assets/fonts/eot/IRANYekanWebRegular.eot diff --git a/admin/fonts/eot/IRANYekanWebThin.eot b/assets/fonts/eot/IRANYekanWebThin.eot similarity index 100% rename from admin/fonts/eot/IRANYekanWebThin.eot rename to assets/fonts/eot/IRANYekanWebThin.eot diff --git a/admin/fonts/svg/IRANYekanWebRegular.svg b/assets/fonts/svg/IRANYekanWebRegular.svg similarity index 99% rename from admin/fonts/svg/IRANYekanWebRegular.svg rename to assets/fonts/svg/IRANYekanWebRegular.svg index e0997ef..b92610d 100644 --- a/admin/fonts/svg/IRANYekanWebRegular.svg +++ b/assets/fonts/svg/IRANYekanWebRegular.svg @@ -1,1548 +1,1548 @@ - - - - -Created by FontForge 20170924 at Wed Sep 16 22:18:33 2020 - By www-data -Copyright (c) 2019 by www.fontiran.com (Moslem Ebrahimi). All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +Created by FontForge 20170924 at Wed Sep 16 22:18:33 2020 + By www-data +Copyright (c) 2019 by www.fontiran.com (Moslem Ebrahimi). All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/admin/fonts/svg/iranyekanwebblack.svg b/assets/fonts/svg/iranyekanwebblack.svg similarity index 99% rename from admin/fonts/svg/iranyekanwebblack.svg rename to assets/fonts/svg/iranyekanwebblack.svg index 7852c95..878552d 100644 --- a/admin/fonts/svg/iranyekanwebblack.svg +++ b/assets/fonts/svg/iranyekanwebblack.svg @@ -1,1474 +1,1474 @@ - - - - -Created by FontForge 20161003 at Sun Dec 16 22:19:23 2018 - By www-data -Copyright (c) 2019 by fontiran.com. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +Created by FontForge 20161003 at Sun Dec 16 22:19:23 2018 + By www-data +Copyright (c) 2019 by fontiran.com. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/admin/fonts/svg/iranyekanwebbold.svg b/assets/fonts/svg/iranyekanwebbold.svg similarity index 99% rename from admin/fonts/svg/iranyekanwebbold.svg rename to assets/fonts/svg/iranyekanwebbold.svg index 6a6006b..88b7867 100644 --- a/admin/fonts/svg/iranyekanwebbold.svg +++ b/assets/fonts/svg/iranyekanwebbold.svg @@ -1,1569 +1,1569 @@ - - - - -Created by FontForge 20161003 at Sun Dec 16 22:19:37 2018 - By www-data -Copyright (c) 2019 by fontiran.com. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +Created by FontForge 20161003 at Sun Dec 16 22:19:37 2018 + By www-data +Copyright (c) 2019 by fontiran.com. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/admin/fonts/svg/iranyekanwebextrablack.svg b/assets/fonts/svg/iranyekanwebextrablack.svg similarity index 99% rename from admin/fonts/svg/iranyekanwebextrablack.svg rename to assets/fonts/svg/iranyekanwebextrablack.svg index 815b866..01c9d7d 100644 --- a/admin/fonts/svg/iranyekanwebextrablack.svg +++ b/assets/fonts/svg/iranyekanwebextrablack.svg @@ -1,1486 +1,1486 @@ - - - - -Created by FontForge 20161003 at Sun Dec 16 22:19:45 2018 - By www-data -Copyright (c) 2019 by fontiran.com. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +Created by FontForge 20161003 at Sun Dec 16 22:19:45 2018 + By www-data +Copyright (c) 2019 by fontiran.com. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/admin/fonts/svg/iranyekanwebextrabold.svg b/assets/fonts/svg/iranyekanwebextrabold.svg similarity index 99% rename from admin/fonts/svg/iranyekanwebextrabold.svg rename to assets/fonts/svg/iranyekanwebextrabold.svg index 21e8a53..1dcb7ea 100644 --- a/admin/fonts/svg/iranyekanwebextrabold.svg +++ b/assets/fonts/svg/iranyekanwebextrabold.svg @@ -1,1472 +1,1472 @@ - - - - -Created by FontForge 20161003 at Sun Dec 16 22:19:55 2018 - By www-data -Copyright (c) 2018 by fontiran.com. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +Created by FontForge 20161003 at Sun Dec 16 22:19:55 2018 + By www-data +Copyright (c) 2018 by fontiran.com. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/admin/fonts/svg/iranyekanweblight.svg b/assets/fonts/svg/iranyekanweblight.svg similarity index 99% rename from admin/fonts/svg/iranyekanweblight.svg rename to assets/fonts/svg/iranyekanweblight.svg index da89c03..9c0c619 100644 --- a/admin/fonts/svg/iranyekanweblight.svg +++ b/assets/fonts/svg/iranyekanweblight.svg @@ -1,1619 +1,1619 @@ - - - - -Created by FontForge 20161003 at Sun Dec 16 22:20:09 2018 - By www-data -Copyright (c) 2019 by fontiran.com. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +Created by FontForge 20161003 at Sun Dec 16 22:20:09 2018 + By www-data +Copyright (c) 2019 by fontiran.com. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/admin/fonts/svg/iranyekanwebmedium.svg b/assets/fonts/svg/iranyekanwebmedium.svg similarity index 99% rename from admin/fonts/svg/iranyekanwebmedium.svg rename to assets/fonts/svg/iranyekanwebmedium.svg index 3e2ce2c..e7fd092 100644 --- a/admin/fonts/svg/iranyekanwebmedium.svg +++ b/assets/fonts/svg/iranyekanwebmedium.svg @@ -1,1573 +1,1573 @@ - - - - -Created by FontForge 20161003 at Sun Dec 16 22:20:19 2018 - By www-data -Copyright (c) 2019 by fontiran.com. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +Created by FontForge 20161003 at Sun Dec 16 22:20:19 2018 + By www-data +Copyright (c) 2019 by fontiran.com. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/admin/fonts/svg/iranyekanwebthin.svg b/assets/fonts/svg/iranyekanwebthin.svg similarity index 99% rename from admin/fonts/svg/iranyekanwebthin.svg rename to assets/fonts/svg/iranyekanwebthin.svg index 2cd7c74..f83cc44 100644 --- a/admin/fonts/svg/iranyekanwebthin.svg +++ b/assets/fonts/svg/iranyekanwebthin.svg @@ -1,1639 +1,1639 @@ - - - - -Created by FontForge 20161003 at Sun Dec 16 22:20:45 2018 - By www-data -Copyright (c) 2019 by fontiran.com. All rights reserved. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +Created by FontForge 20161003 at Sun Dec 16 22:20:45 2018 + By www-data +Copyright (c) 2019 by fontiran.com. All rights reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/admin/fonts/ttf/IRANYekanWebBlack.ttf b/assets/fonts/ttf/IRANYekanWebBlack.ttf similarity index 100% rename from admin/fonts/ttf/IRANYekanWebBlack.ttf rename to assets/fonts/ttf/IRANYekanWebBlack.ttf diff --git a/admin/fonts/ttf/IRANYekanWebBold.ttf b/assets/fonts/ttf/IRANYekanWebBold.ttf similarity index 100% rename from admin/fonts/ttf/IRANYekanWebBold.ttf rename to assets/fonts/ttf/IRANYekanWebBold.ttf diff --git a/admin/fonts/ttf/IRANYekanWebExtraBlack.ttf b/assets/fonts/ttf/IRANYekanWebExtraBlack.ttf similarity index 100% rename from admin/fonts/ttf/IRANYekanWebExtraBlack.ttf rename to assets/fonts/ttf/IRANYekanWebExtraBlack.ttf diff --git a/admin/fonts/ttf/IRANYekanWebExtraBold.ttf b/assets/fonts/ttf/IRANYekanWebExtraBold.ttf similarity index 100% rename from admin/fonts/ttf/IRANYekanWebExtraBold.ttf rename to assets/fonts/ttf/IRANYekanWebExtraBold.ttf diff --git a/admin/fonts/ttf/IRANYekanWebLight.ttf b/assets/fonts/ttf/IRANYekanWebLight.ttf similarity index 100% rename from admin/fonts/ttf/IRANYekanWebLight.ttf rename to assets/fonts/ttf/IRANYekanWebLight.ttf diff --git a/admin/fonts/ttf/IRANYekanWebMedium.ttf b/assets/fonts/ttf/IRANYekanWebMedium.ttf similarity index 100% rename from admin/fonts/ttf/IRANYekanWebMedium.ttf rename to assets/fonts/ttf/IRANYekanWebMedium.ttf diff --git a/admin/fonts/ttf/IRANYekanWebRegular.ttf b/assets/fonts/ttf/IRANYekanWebRegular.ttf similarity index 100% rename from admin/fonts/ttf/IRANYekanWebRegular.ttf rename to assets/fonts/ttf/IRANYekanWebRegular.ttf diff --git a/admin/fonts/ttf/IRANYekanWebThin.ttf b/assets/fonts/ttf/IRANYekanWebThin.ttf similarity index 100% rename from admin/fonts/ttf/IRANYekanWebThin.ttf rename to assets/fonts/ttf/IRANYekanWebThin.ttf diff --git a/admin/fonts/woff/IRANYekanWebBlack.woff b/assets/fonts/woff/IRANYekanWebBlack.woff similarity index 100% rename from admin/fonts/woff/IRANYekanWebBlack.woff rename to assets/fonts/woff/IRANYekanWebBlack.woff diff --git a/admin/fonts/woff/IRANYekanWebBold.woff b/assets/fonts/woff/IRANYekanWebBold.woff similarity index 100% rename from admin/fonts/woff/IRANYekanWebBold.woff rename to assets/fonts/woff/IRANYekanWebBold.woff diff --git a/admin/fonts/woff/IRANYekanWebExtraBlack.woff b/assets/fonts/woff/IRANYekanWebExtraBlack.woff similarity index 100% rename from admin/fonts/woff/IRANYekanWebExtraBlack.woff rename to assets/fonts/woff/IRANYekanWebExtraBlack.woff diff --git a/admin/fonts/woff/IRANYekanWebExtraBold.woff b/assets/fonts/woff/IRANYekanWebExtraBold.woff similarity index 100% rename from admin/fonts/woff/IRANYekanWebExtraBold.woff rename to assets/fonts/woff/IRANYekanWebExtraBold.woff diff --git a/admin/fonts/woff/IRANYekanWebLight.woff b/assets/fonts/woff/IRANYekanWebLight.woff similarity index 100% rename from admin/fonts/woff/IRANYekanWebLight.woff rename to assets/fonts/woff/IRANYekanWebLight.woff diff --git a/admin/fonts/woff/IRANYekanWebMedium.woff b/assets/fonts/woff/IRANYekanWebMedium.woff similarity index 100% rename from admin/fonts/woff/IRANYekanWebMedium.woff rename to assets/fonts/woff/IRANYekanWebMedium.woff diff --git a/admin/fonts/woff/IRANYekanWebRegular.woff b/assets/fonts/woff/IRANYekanWebRegular.woff similarity index 100% rename from admin/fonts/woff/IRANYekanWebRegular.woff rename to assets/fonts/woff/IRANYekanWebRegular.woff diff --git a/admin/fonts/woff/IRANYekanWebThin.woff b/assets/fonts/woff/IRANYekanWebThin.woff similarity index 100% rename from admin/fonts/woff/IRANYekanWebThin.woff rename to assets/fonts/woff/IRANYekanWebThin.woff diff --git a/admin/fonts/woff2/IRANYekanWebBlack.woff2 b/assets/fonts/woff2/IRANYekanWebBlack.woff2 similarity index 100% rename from admin/fonts/woff2/IRANYekanWebBlack.woff2 rename to assets/fonts/woff2/IRANYekanWebBlack.woff2 diff --git a/admin/fonts/woff2/IRANYekanWebBold.woff2 b/assets/fonts/woff2/IRANYekanWebBold.woff2 similarity index 100% rename from admin/fonts/woff2/IRANYekanWebBold.woff2 rename to assets/fonts/woff2/IRANYekanWebBold.woff2 diff --git a/admin/fonts/woff2/IRANYekanWebExtraBlack.woff2 b/assets/fonts/woff2/IRANYekanWebExtraBlack.woff2 similarity index 100% rename from admin/fonts/woff2/IRANYekanWebExtraBlack.woff2 rename to assets/fonts/woff2/IRANYekanWebExtraBlack.woff2 diff --git a/admin/fonts/woff2/IRANYekanWebExtraBold.woff2 b/assets/fonts/woff2/IRANYekanWebExtraBold.woff2 similarity index 100% rename from admin/fonts/woff2/IRANYekanWebExtraBold.woff2 rename to assets/fonts/woff2/IRANYekanWebExtraBold.woff2 diff --git a/admin/fonts/woff2/IRANYekanWebLight.woff2 b/assets/fonts/woff2/IRANYekanWebLight.woff2 similarity index 100% rename from admin/fonts/woff2/IRANYekanWebLight.woff2 rename to assets/fonts/woff2/IRANYekanWebLight.woff2 diff --git a/admin/fonts/woff2/IRANYekanWebMedium.woff2 b/assets/fonts/woff2/IRANYekanWebMedium.woff2 similarity index 100% rename from admin/fonts/woff2/IRANYekanWebMedium.woff2 rename to assets/fonts/woff2/IRANYekanWebMedium.woff2 diff --git a/admin/fonts/woff2/IRANYekanWebRegular.woff2 b/assets/fonts/woff2/IRANYekanWebRegular.woff2 similarity index 100% rename from admin/fonts/woff2/IRANYekanWebRegular.woff2 rename to assets/fonts/woff2/IRANYekanWebRegular.woff2 diff --git a/admin/fonts/woff2/IRANYekanWebThin.woff2 b/assets/fonts/woff2/IRANYekanWebThin.woff2 similarity index 100% rename from admin/fonts/woff2/IRANYekanWebThin.woff2 rename to assets/fonts/woff2/IRANYekanWebThin.woff2 diff --git a/assets/img/heart.gif b/assets/img/heart.gif new file mode 100644 index 0000000..d379e57 Binary files /dev/null and b/assets/img/heart.gif differ diff --git a/admin/img/hesabix-logo.fa.png b/assets/img/hesabix-logo.fa.png similarity index 100% rename from admin/img/hesabix-logo.fa.png rename to assets/img/hesabix-logo.fa.png diff --git a/assets/img/hesabix-logo.png b/assets/img/hesabix-logo.png new file mode 100644 index 0000000..f945669 Binary files /dev/null and b/assets/img/hesabix-logo.png differ diff --git a/admin/img/icons/box-open.svg b/assets/img/icons/box-open.svg similarity index 100% rename from admin/img/icons/box-open.svg rename to assets/img/icons/box-open.svg diff --git a/admin/img/icons/cog.svg b/assets/img/icons/cog.svg similarity index 100% rename from admin/img/icons/cog.svg rename to assets/img/icons/cog.svg diff --git a/admin/img/icons/file-alt.svg b/assets/img/icons/file-alt.svg similarity index 100% rename from admin/img/icons/file-alt.svg rename to assets/img/icons/file-alt.svg diff --git a/admin/img/icons/file-export.svg b/assets/img/icons/file-export.svg similarity index 100% rename from admin/img/icons/file-export.svg rename to assets/img/icons/file-export.svg diff --git a/admin/img/icons/file-invoice-dollar.svg b/assets/img/icons/file-invoice-dollar.svg similarity index 100% rename from admin/img/icons/file-invoice-dollar.svg rename to assets/img/icons/file-invoice-dollar.svg diff --git a/admin/img/icons/home.svg b/assets/img/icons/home.svg similarity index 100% rename from admin/img/icons/home.svg rename to assets/img/icons/home.svg diff --git a/admin/img/icons/money-check-alt.svg b/assets/img/icons/money-check-alt.svg similarity index 100% rename from admin/img/icons/money-check-alt.svg rename to assets/img/icons/money-check-alt.svg diff --git a/admin/img/icons/sync-alt.svg b/assets/img/icons/sync-alt.svg similarity index 100% rename from admin/img/icons/sync-alt.svg rename to assets/img/icons/sync-alt.svg diff --git a/admin/img/icons/users.svg b/assets/img/icons/users.svg similarity index 100% rename from admin/img/icons/users.svg rename to assets/img/icons/users.svg diff --git a/admin/img/logo.png b/assets/img/logo.png similarity index 100% rename from admin/img/logo.png rename to assets/img/logo.png diff --git a/admin/img/menu-icon.png b/assets/img/menu-icon.png similarity index 100% rename from admin/img/menu-icon.png rename to assets/img/menu-icon.png diff --git a/admin/js/bootstrap.bundle.min.js b/assets/js/bootstrap.bundle.min.js similarity index 99% rename from admin/js/bootstrap.bundle.min.js rename to assets/js/bootstrap.bundle.min.js index 637329a..c682e1b 100644 --- a/admin/js/bootstrap.bundle.min.js +++ b/assets/js/bootstrap.bundle.min.js @@ -1,7 +1,7 @@ -/*! - * Bootstrap v5.0.0-beta2 (https://getbootstrap.com/) - * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) - */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";function t(t,e){for(var n=0;n0,i._pointerEvent=Boolean(window.PointerEvent),i._addEventListeners(),i}i(o,t);var r=o.prototype;return r.next=function(){this._isSliding||this._slide("next")},r.nextWhenVisible=function(){!document.hidden&&g(this._element)&&this.next()},r.prev=function(){this._isSliding||this._slide("prev")},r.pause=function(t){t||(this._isPaused=!0),Y(".carousel-item-next, .carousel-item-prev",this._element)&&(f(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},r.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config&&this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},r.to=function(t){var e=this;this._activeElement=Y(".active.carousel-item",this._element);var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)B.one(this._element,"slid.bs.carousel",(function(){return e.to(t)}));else{if(n===t)return this.pause(),void this.cycle();var i=t>n?"next":"prev";this._slide(i,this._items[t])}},r.dispose=function(){t.prototype.dispose.call(this),B.off(this._element,".bs.carousel"),this._items=null,this._config=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},r._getConfig=function(t){return t=n({},X,t),p("carousel",t,Q),t},r._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&(b?this.next():this.prev()),e<0&&(b?this.prev():this.next())}},r._addEventListeners=function(){var t=this;this._config.keyboard&&B.on(this._element,"keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&(B.on(this._element,"mouseenter.bs.carousel",(function(e){return t.pause(e)})),B.on(this._element,"mouseleave.bs.carousel",(function(e){return t.cycle(e)}))),this._config.touch&&this._touchSupported&&this._addTouchEventListeners()},r._addTouchEventListeners=function(){var t=this,e=function(e){!t._pointerEvent||"pen"!==e.pointerType&&"touch"!==e.pointerType?t._pointerEvent||(t.touchStartX=e.touches[0].clientX):t.touchStartX=e.clientX},n=function(e){!t._pointerEvent||"pen"!==e.pointerType&&"touch"!==e.pointerType||(t.touchDeltaX=e.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};F(".carousel-item img",this._element).forEach((function(t){B.on(t,"dragstart.bs.carousel",(function(t){return t.preventDefault()}))})),this._pointerEvent?(B.on(this._element,"pointerdown.bs.carousel",(function(t){return e(t)})),B.on(this._element,"pointerup.bs.carousel",(function(t){return n(t)})),this._element.classList.add("pointer-event")):(B.on(this._element,"touchstart.bs.carousel",(function(t){return e(t)})),B.on(this._element,"touchmove.bs.carousel",(function(e){return function(e){e.touches&&e.touches.length>1?t.touchDeltaX=0:t.touchDeltaX=e.touches[0].clientX-t.touchStartX}(e)})),B.on(this._element,"touchend.bs.carousel",(function(t){return n(t)})))},r._keydown=function(t){/input|textarea/i.test(t.target.tagName)||("ArrowLeft"===t.key?(t.preventDefault(),b?this.next():this.prev()):"ArrowRight"===t.key&&(t.preventDefault(),b?this.prev():this.next()))},r._getItemIndex=function(t){return this._items=t&&t.parentNode?F(".carousel-item",t.parentNode):[],this._items.indexOf(t)},r._getItemByDirection=function(t,e){var n="next"===t,i="prev"===t,o=this._getItemIndex(e),r=this._items.length-1;if((i&&0===o||n&&o===r)&&!this._config.wrap)return e;var s=(o+("prev"===t?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},r._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(Y(".active.carousel-item",this._element));return B.trigger(this._element,"slide.bs.carousel",{relatedTarget:t,direction:e,from:i,to:n})},r._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=Y(".active",this._indicatorsElement);e.classList.remove("active"),e.removeAttribute("aria-current");for(var n=F("[data-bs-target]",this._indicatorsElement),i=0;i0)for(var i=0;i=0}function _t(t){return((ut(t)?t.ownerDocument:t.document)||window.document).documentElement}function bt(t){return"html"===lt(t)?t:t.assignedSlot||t.parentNode||t.host||_t(t)}function yt(t){if(!ft(t)||"fixed"===mt(t).position)return null;var e=t.offsetParent;if(e){var n=_t(e);if("body"===lt(e)&&"static"===mt(e).position&&"static"!==mt(n).position)return n}return e}function wt(t){for(var e=ct(t),n=yt(t);n&&vt(n)&&"static"===mt(n).position;)n=yt(n);return n&&"body"===lt(n)&&"static"===mt(n).position?e:n||function(t){for(var e=bt(t);ft(e)&&["html","body"].indexOf(lt(e))<0;){var n=mt(e);if("none"!==n.transform||"none"!==n.perspective||n.willChange&&"auto"!==n.willChange)return e;e=e.parentNode}return null}(t)||e}function Et(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function Tt(t,e,n){return Math.max(t,Math.min(e,n))}function kt(t){return Object.assign(Object.assign({},{top:0,right:0,bottom:0,left:0}),t)}function At(t,e){return e.reduce((function(e,n){return e[n]=t,e}),{})}var Lt={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,n=t.state,i=t.name,o=n.elements.arrow,r=n.modifiersData.popperOffsets,s=ht(n.placement),a=Et(s),l=[it,nt].indexOf(s)>=0?"height":"width";if(o&&r){var c=n.modifiersData[i+"#persistent"].padding,u=pt(o),f="y"===a?tt:it,d="y"===a?et:nt,h=n.rects.reference[l]+n.rects.reference[a]-r[a]-n.rects.popper[l],p=r[a]-n.rects.reference[a],g=wt(o),m=g?"y"===a?g.clientHeight||0:g.clientWidth||0:0,v=h/2-p/2,_=c[f],b=m-u[l]-c[d],y=m/2-u[l]/2+v,w=Tt(_,y,b),E=a;n.modifiersData[i]=((e={})[E]=w,e.centerOffset=w-y,e)}},effect:function(t){var e=t.state,n=t.options,i=t.name,o=n.element,r=void 0===o?"[data-popper-arrow]":o,s=n.padding,a=void 0===s?0:s;null!=r&&("string"!=typeof r||(r=e.elements.popper.querySelector(r)))&>(e.elements.popper,r)&&(e.elements.arrow=r,e.modifiersData[i+"#persistent"]={padding:kt("number"!=typeof a?a:At(a,ot))})},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]},Ot={top:"auto",right:"auto",bottom:"auto",left:"auto"};function Dt(t){var e,n=t.popper,i=t.popperRect,o=t.placement,r=t.offsets,s=t.position,a=t.gpuAcceleration,l=t.adaptive,c=t.roundOffsets?function(t){var e=t.x,n=t.y,i=window.devicePixelRatio||1;return{x:Math.round(e*i)/i||0,y:Math.round(n*i)/i||0}}(r):r,u=c.x,f=void 0===u?0:u,d=c.y,h=void 0===d?0:d,p=r.hasOwnProperty("x"),g=r.hasOwnProperty("y"),m=it,v=tt,_=window;if(l){var b=wt(n);b===ct(n)&&(b=_t(n)),o===tt&&(v=et,h-=b.clientHeight-i.height,h*=a?1:-1),o===it&&(m=nt,f-=b.clientWidth-i.width,f*=a?1:-1)}var y,w=Object.assign({position:s},l&&Ot);return a?Object.assign(Object.assign({},w),{},((y={})[v]=g?"0":"",y[m]=p?"0":"",y.transform=(_.devicePixelRatio||1)<2?"translate("+f+"px, "+h+"px)":"translate3d("+f+"px, "+h+"px, 0)",y)):Object.assign(Object.assign({},w),{},((e={})[v]=g?h+"px":"",e[m]=p?f+"px":"",e.transform="",e))}var xt={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,n=t.options,i=n.gpuAcceleration,o=void 0===i||i,r=n.adaptive,s=void 0===r||r,a=n.roundOffsets,l=void 0===a||a,c={placement:ht(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:o};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign(Object.assign({},e.styles.popper),Dt(Object.assign(Object.assign({},c),{},{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:s,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign(Object.assign({},e.styles.arrow),Dt(Object.assign(Object.assign({},c),{},{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign(Object.assign({},e.attributes.popper),{},{"data-popper-placement":e.placement})},data:{}},Ct={passive:!0},St={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,n=t.instance,i=t.options,o=i.scroll,r=void 0===o||o,s=i.resize,a=void 0===s||s,l=ct(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return r&&c.forEach((function(t){t.addEventListener("scroll",n.update,Ct)})),a&&l.addEventListener("resize",n.update,Ct),function(){r&&c.forEach((function(t){t.removeEventListener("scroll",n.update,Ct)})),a&&l.removeEventListener("resize",n.update,Ct)}},data:{}},jt={left:"right",right:"left",bottom:"top",top:"bottom"};function Nt(t){return t.replace(/left|right|bottom|top/g,(function(t){return jt[t]}))}var Pt={start:"end",end:"start"};function It(t){return t.replace(/start|end/g,(function(t){return Pt[t]}))}function Mt(t){var e=t.getBoundingClientRect();return{width:e.width,height:e.height,top:e.top,right:e.right,bottom:e.bottom,left:e.left,x:e.left,y:e.top}}function Bt(t){var e=ct(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Ht(t){return Mt(_t(t)).left+Bt(t).scrollLeft}function Rt(t){var e=mt(t),n=e.overflow,i=e.overflowX,o=e.overflowY;return/auto|scroll|overlay|hidden/.test(n+o+i)}function Wt(t,e){void 0===e&&(e=[]);var n=function t(e){return["html","body","#document"].indexOf(lt(e))>=0?e.ownerDocument.body:ft(e)&&Rt(e)?e:t(bt(e))}(t),i="body"===lt(n),o=ct(n),r=i?[o].concat(o.visualViewport||[],Rt(n)?n:[]):n,s=e.concat(r);return i?s:s.concat(Wt(bt(r)))}function Kt(t){return Object.assign(Object.assign({},t),{},{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function Ut(t,e){return"viewport"===e?Kt(function(t){var e=ct(t),n=_t(t),i=e.visualViewport,o=n.clientWidth,r=n.clientHeight,s=0,a=0;return i&&(o=i.width,r=i.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(s=i.offsetLeft,a=i.offsetTop)),{width:o,height:r,x:s+Ht(t),y:a}}(t)):ft(e)?function(t){var e=Mt(t);return e.top=e.top+t.clientTop,e.left=e.left+t.clientLeft,e.bottom=e.top+t.clientHeight,e.right=e.left+t.clientWidth,e.width=t.clientWidth,e.height=t.clientHeight,e.x=e.left,e.y=e.top,e}(e):Kt(function(t){var e=_t(t),n=Bt(t),i=t.ownerDocument.body,o=Math.max(e.scrollWidth,e.clientWidth,i?i.scrollWidth:0,i?i.clientWidth:0),r=Math.max(e.scrollHeight,e.clientHeight,i?i.scrollHeight:0,i?i.clientHeight:0),s=-n.scrollLeft+Ht(t),a=-n.scrollTop;return"rtl"===mt(i||e).direction&&(s+=Math.max(e.clientWidth,i?i.clientWidth:0)-o),{width:o,height:r,x:s,y:a}}(_t(t)))}function zt(t){return t.split("-")[1]}function Ft(t){var e,n=t.reference,i=t.element,o=t.placement,r=o?ht(o):null,s=o?zt(o):null,a=n.x+n.width/2-i.width/2,l=n.y+n.height/2-i.height/2;switch(r){case tt:e={x:a,y:n.y-i.height};break;case et:e={x:a,y:n.y+n.height};break;case nt:e={x:n.x+n.width,y:l};break;case it:e={x:n.x-i.width,y:l};break;default:e={x:n.x,y:n.y}}var c=r?Et(r):null;if(null!=c){var u="y"===c?"height":"width";switch(s){case"start":e[c]=e[c]-(n[u]/2-i[u]/2);break;case"end":e[c]=e[c]+(n[u]/2-i[u]/2)}}return e}function Yt(t,e){void 0===e&&(e={});var n=e,i=n.placement,o=void 0===i?t.placement:i,r=n.boundary,s=void 0===r?"clippingParents":r,a=n.rootBoundary,l=void 0===a?"viewport":a,c=n.elementContext,u=void 0===c?"popper":c,f=n.altBoundary,d=void 0!==f&&f,h=n.padding,p=void 0===h?0:h,g=kt("number"!=typeof p?p:At(p,ot)),m="popper"===u?"reference":"popper",v=t.elements.reference,_=t.rects.popper,b=t.elements[d?m:u],y=function(t,e,n){var i="clippingParents"===e?function(t){var e=Wt(bt(t)),n=["absolute","fixed"].indexOf(mt(t).position)>=0&&ft(t)?wt(t):t;return ut(n)?e.filter((function(t){return ut(t)&>(t,n)&&"body"!==lt(t)})):[]}(t):[].concat(e),o=[].concat(i,[n]),r=o[0],s=o.reduce((function(e,n){var i=Ut(t,n);return e.top=Math.max(i.top,e.top),e.right=Math.min(i.right,e.right),e.bottom=Math.min(i.bottom,e.bottom),e.left=Math.max(i.left,e.left),e}),Ut(t,r));return s.width=s.right-s.left,s.height=s.bottom-s.top,s.x=s.left,s.y=s.top,s}(ut(b)?b:b.contextElement||_t(t.elements.popper),s,l),w=Mt(v),E=Ft({reference:w,element:_,strategy:"absolute",placement:o}),T=Kt(Object.assign(Object.assign({},_),E)),k="popper"===u?T:w,A={top:y.top-k.top+g.top,bottom:k.bottom-y.bottom+g.bottom,left:y.left-k.left+g.left,right:k.right-y.right+g.right},L=t.modifiersData.offset;if("popper"===u&&L){var O=L[o];Object.keys(A).forEach((function(t){var e=[nt,et].indexOf(t)>=0?1:-1,n=[tt,et].indexOf(t)>=0?"y":"x";A[t]+=O[n]*e}))}return A}function qt(t,e){void 0===e&&(e={});var n=e,i=n.placement,o=n.boundary,r=n.rootBoundary,s=n.padding,a=n.flipVariations,l=n.allowedAutoPlacements,c=void 0===l?st:l,u=zt(i),f=u?a?rt:rt.filter((function(t){return zt(t)===u})):ot,d=f.filter((function(t){return c.indexOf(t)>=0}));0===d.length&&(d=f);var h=d.reduce((function(e,n){return e[n]=Yt(t,{placement:n,boundary:o,rootBoundary:r,padding:s})[ht(n)],e}),{});return Object.keys(h).sort((function(t,e){return h[t]-h[e]}))}var Vt={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,n=t.options,i=t.name;if(!e.modifiersData[i]._skip){for(var o=n.mainAxis,r=void 0===o||o,s=n.altAxis,a=void 0===s||s,l=n.fallbackPlacements,c=n.padding,u=n.boundary,f=n.rootBoundary,d=n.altBoundary,h=n.flipVariations,p=void 0===h||h,g=n.allowedAutoPlacements,m=e.options.placement,v=ht(m),_=l||(v!==m&&p?function(t){if("auto"===ht(t))return[];var e=Nt(t);return[It(t),e,It(e)]}(m):[Nt(m)]),b=[m].concat(_).reduce((function(t,n){return t.concat("auto"===ht(n)?qt(e,{placement:n,boundary:u,rootBoundary:f,padding:c,flipVariations:p,allowedAutoPlacements:g}):n)}),[]),y=e.rects.reference,w=e.rects.popper,E=new Map,T=!0,k=b[0],A=0;A=0,C=x?"width":"height",S=Yt(e,{placement:L,boundary:u,rootBoundary:f,altBoundary:d,padding:c}),j=x?D?nt:it:D?et:tt;y[C]>w[C]&&(j=Nt(j));var N=Nt(j),P=[];if(r&&P.push(S[O]<=0),a&&P.push(S[j]<=0,S[N]<=0),P.every((function(t){return t}))){k=L,T=!1;break}E.set(L,P)}if(T)for(var I=function(t){var e=b.find((function(e){var n=E.get(e);if(n)return n.slice(0,t).every((function(t){return t}))}));if(e)return k=e,"break"},M=p?3:1;M>0&&"break"!==I(M);M--);e.placement!==k&&(e.modifiersData[i]._skip=!0,e.placement=k,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function Xt(t,e,n){return void 0===n&&(n={x:0,y:0}),{top:t.top-e.height-n.y,right:t.right-e.width+n.x,bottom:t.bottom-e.height+n.y,left:t.left-e.width-n.x}}function Qt(t){return[tt,nt,et,it].some((function(e){return t[e]>=0}))}var $t={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,n=t.name,i=e.rects.reference,o=e.rects.popper,r=e.modifiersData.preventOverflow,s=Yt(e,{elementContext:"reference"}),a=Yt(e,{altBoundary:!0}),l=Xt(s,i),c=Xt(a,o,r),u=Qt(l),f=Qt(c);e.modifiersData[n]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:u,hasPopperEscaped:f},e.attributes.popper=Object.assign(Object.assign({},e.attributes.popper),{},{"data-popper-reference-hidden":u,"data-popper-escaped":f})}},Gt={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,n=t.options,i=t.name,o=n.offset,r=void 0===o?[0,0]:o,s=st.reduce((function(t,n){return t[n]=function(t,e,n){var i=ht(t),o=[it,tt].indexOf(i)>=0?-1:1,r="function"==typeof n?n(Object.assign(Object.assign({},e),{},{placement:t})):n,s=r[0],a=r[1];return s=s||0,a=(a||0)*o,[it,nt].indexOf(i)>=0?{x:a,y:s}:{x:s,y:a}}(n,e.rects,r),t}),{}),a=s[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[i]=s}},Zt={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,n=t.name;e.modifiersData[n]=Ft({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},Jt={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,n=t.options,i=t.name,o=n.mainAxis,r=void 0===o||o,s=n.altAxis,a=void 0!==s&&s,l=n.boundary,c=n.rootBoundary,u=n.altBoundary,f=n.padding,d=n.tether,h=void 0===d||d,p=n.tetherOffset,g=void 0===p?0:p,m=Yt(e,{boundary:l,rootBoundary:c,padding:f,altBoundary:u}),v=ht(e.placement),_=zt(e.placement),b=!_,y=Et(v),w="x"===y?"y":"x",E=e.modifiersData.popperOffsets,T=e.rects.reference,k=e.rects.popper,A="function"==typeof g?g(Object.assign(Object.assign({},e.rects),{},{placement:e.placement})):g,L={x:0,y:0};if(E){if(r){var O="y"===y?tt:it,D="y"===y?et:nt,x="y"===y?"height":"width",C=E[y],S=E[y]+m[O],j=E[y]-m[D],N=h?-k[x]/2:0,P="start"===_?T[x]:k[x],I="start"===_?-k[x]:-T[x],M=e.elements.arrow,B=h&&M?pt(M):{width:0,height:0},H=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},R=H[O],W=H[D],K=Tt(0,T[x],B[x]),U=b?T[x]/2-N-K-R-A:P-K-R-A,z=b?-T[x]/2+N+K+W+A:I+K+W+A,F=e.elements.arrow&&wt(e.elements.arrow),Y=F?"y"===y?F.clientTop||0:F.clientLeft||0:0,q=e.modifiersData.offset?e.modifiersData.offset[e.placement][y]:0,V=E[y]+U-q-Y,X=E[y]+z-q,Q=Tt(h?Math.min(S,V):S,C,h?Math.max(j,X):j);E[y]=Q,L[y]=Q-C}if(a){var $="x"===y?tt:it,G="x"===y?et:nt,Z=E[w],J=Tt(Z+m[$],Z,Z-m[G]);E[w]=J,L[w]=J-Z}e.modifiersData[i]=L}},requiresIfExists:["offset"]};function te(t,e,n){void 0===n&&(n=!1);var i,o,r=_t(e),s=Mt(t),a=ft(e),l={scrollLeft:0,scrollTop:0},c={x:0,y:0};return(a||!a&&!n)&&(("body"!==lt(e)||Rt(r))&&(l=(i=e)!==ct(i)&&ft(i)?{scrollLeft:(o=i).scrollLeft,scrollTop:o.scrollTop}:Bt(i)),ft(e)?((c=Mt(e)).x+=e.clientLeft,c.y+=e.clientTop):r&&(c.x=Ht(r))),{x:s.left+l.scrollLeft-c.x,y:s.top+l.scrollTop-c.y,width:s.width,height:s.height}}var ee={placement:"bottom",modifiers:[],strategy:"absolute"};function ne(){for(var t=arguments.length,e=new Array(t),n=0;n0&&r--,"ArrowDown"===t.key&&rdocument.documentElement.clientHeight;e||(this._element.style.overflowY="hidden"),this._element.classList.add("modal-static");var n=u(this._dialog);B.off(this._element,"transitionend"),B.one(this._element,"transitionend",(function(){t._element.classList.remove("modal-static"),e||(B.one(t._element,"transitionend",(function(){t._element.style.overflowY=""})),h(t._element,n))})),h(this._element,n),this._element.focus()}},r._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;(!this._isBodyOverflowing&&t&&!b||this._isBodyOverflowing&&!t&&b)&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),(this._isBodyOverflowing&&!t&&!b||!this._isBodyOverflowing&&t&&b)&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},r._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},r._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)
',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:[0,0],container:!1,fallbackPlacements:["top","right","bottom","left"],boundary:"clippingParents",customClass:"",sanitize:!0,sanitizeFn:null,allowList:{"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},popperConfig:null},Ce={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},Se=function(t){function o(e,n){var i;if(void 0===ae)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");return(i=t.call(this,e)||this)._isEnabled=!0,i._timeout=0,i._hoverState="",i._activeTrigger={},i._popper=null,i.config=i._getConfig(n),i.tip=null,i._setListeners(),i}i(o,t);var r=o.prototype;return r.enable=function(){this._isEnabled=!0},r.disable=function(){this._isEnabled=!1},r.toggleEnabled=function(){this._isEnabled=!this._isEnabled},r.toggle=function(t){if(this._isEnabled)if(t){var e=this._initializeOnDelegatedTarget(t);e._activeTrigger.click=!e._activeTrigger.click,e._isWithActiveTrigger()?e._enter(null,e):e._leave(null,e)}else{if(this.getTipElement().classList.contains("show"))return void this._leave(null,this);this._enter(null,this)}},r.dispose=function(){clearTimeout(this._timeout),B.off(this._element,this.constructor.EVENT_KEY),B.off(this._element.closest(".modal"),"hide.bs.modal",this._hideModalHandler),this.tip&&this.tip.parentNode&&this.tip.parentNode.removeChild(this.tip),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.config=null,this.tip=null,t.prototype.dispose.call(this)},r.show=function(){var t=this;if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(this.isWithContent()&&this._isEnabled){var e=B.trigger(this._element,this.constructor.Event.SHOW),n=function t(e){if(!document.documentElement.attachShadow)return null;if("function"==typeof e.getRootNode){var n=e.getRootNode();return n instanceof ShadowRoot?n:null}return e instanceof ShadowRoot?e:e.parentNode?t(e.parentNode):null}(this._element),i=null===n?this._element.ownerDocument.documentElement.contains(this._element):n.contains(this._element);if(!e.defaultPrevented&&i){var o=this.getTipElement(),r=s(this.constructor.NAME);o.setAttribute("id",r),this._element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&o.classList.add("fade");var a="function"==typeof this.config.placement?this.config.placement.call(this,o,this._element):this.config.placement,l=this._getAttachment(a);this._addAttachmentClass(l);var c=this._getContainer();E(o,this.constructor.DATA_KEY,this),this._element.ownerDocument.documentElement.contains(this.tip)||c.appendChild(o),B.trigger(this._element,this.constructor.Event.INSERTED),this._popper=se(this._element,o,this._getPopperConfig(l)),o.classList.add("show");var f,d,p="function"==typeof this.config.customClass?this.config.customClass():this.config.customClass;p&&(f=o.classList).add.apply(f,p.split(" ")),"ontouchstart"in document.documentElement&&(d=[]).concat.apply(d,document.body.children).forEach((function(t){B.on(t,"mouseover",(function(){}))}));var g=function(){var e=t._hoverState;t._hoverState=null,B.trigger(t._element,t.constructor.Event.SHOWN),"out"===e&&t._leave(null,t)};if(this.tip.classList.contains("fade")){var m=u(this.tip);B.one(this.tip,"transitionend",g),h(this.tip,m)}else g()}}},r.hide=function(){var t=this;if(this._popper){var e=this.getTipElement(),n=function(){"show"!==t._hoverState&&e.parentNode&&e.parentNode.removeChild(e),t._cleanTipClass(),t._element.removeAttribute("aria-describedby"),B.trigger(t._element,t.constructor.Event.HIDDEN),t._popper&&(t._popper.destroy(),t._popper=null)};if(!B.trigger(this._element,this.constructor.Event.HIDE).defaultPrevented){var i;if(e.classList.remove("show"),"ontouchstart"in document.documentElement&&(i=[]).concat.apply(i,document.body.children).forEach((function(t){return B.off(t,"mouseover",m)})),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,this.tip.classList.contains("fade")){var o=u(e);B.one(e,"transitionend",n),h(e,o)}else n();this._hoverState=""}}},r.update=function(){null!==this._popper&&this._popper.update()},r.isWithContent=function(){return Boolean(this.getTitle())},r.getTipElement=function(){if(this.tip)return this.tip;var t=document.createElement("div");return t.innerHTML=this.config.template,this.tip=t.children[0],this.tip},r.setContent=function(){var t=this.getTipElement();this.setElementContent(Y(".tooltip-inner",t),this.getTitle()),t.classList.remove("fade","show")},r.setElementContent=function(t,e){if(null!==t)return"object"==typeof e&&d(e)?(e.jquery&&(e=e[0]),void(this.config.html?e.parentNode!==t&&(t.innerHTML="",t.appendChild(e)):t.textContent=e.textContent)):void(this.config.html?(this.config.sanitize&&(e=ke(e,this.config.allowList,this.config.sanitizeFn)),t.innerHTML=e):t.textContent=e)},r.getTitle=function(){var t=this._element.getAttribute("data-bs-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this._element):this.config.title),t},r.updateAttachment=function(t){return"right"===t?"end":"left"===t?"start":t},r._initializeOnDelegatedTarget=function(t,e){var n=this.constructor.DATA_KEY;return(e=e||T(t.delegateTarget,n))||(e=new this.constructor(t.delegateTarget,this._getDelegateConfig()),E(t.delegateTarget,n,e)),e},r._getOffset=function(){var t=this,e=this.config.offset;return"string"==typeof e?e.split(",").map((function(t){return Number.parseInt(t,10)})):"function"==typeof e?function(n){return e(n,t._element)}:e},r._getPopperConfig=function(t){var e=this,i={placement:t,modifiers:[{name:"flip",options:{altBoundary:!0,fallbackPlacements:this.config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this.config.boundary}},{name:"arrow",options:{element:"."+this.constructor.NAME+"-arrow"}},{name:"onChange",enabled:!0,phase:"afterWrite",fn:function(t){return e._handlePopperPlacementChange(t)}}],onFirstUpdate:function(t){t.options.placement!==t.placement&&e._handlePopperPlacementChange(t)}};return n({},i,"function"==typeof this.config.popperConfig?this.config.popperConfig(i):this.config.popperConfig)},r._addAttachmentClass=function(t){this.getTipElement().classList.add("bs-tooltip-"+this.updateAttachment(t))},r._getContainer=function(){return!1===this.config.container?document.body:d(this.config.container)?this.config.container:Y(this.config.container)},r._getAttachment=function(t){return De[t.toUpperCase()]},r._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(e){if("click"===e)B.on(t._element,t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==e){var n="hover"===e?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,i="hover"===e?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;B.on(t._element,n,t.config.selector,(function(e){return t._enter(e)})),B.on(t._element,i,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t._element&&t.hide()},B.on(this._element.closest(".modal"),"hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=n({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},r._fixTitle=function(){var t=this._element.getAttribute("title"),e=typeof this._element.getAttribute("data-bs-original-title");(t||"string"!==e)&&(this._element.setAttribute("data-bs-original-title",t||""),!t||this._element.getAttribute("aria-label")||this._element.textContent||this._element.setAttribute("aria-label",t),this._element.setAttribute("title",""))},r._enter=function(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),e.getTipElement().classList.contains("show")||"show"===e._hoverState?e._hoverState="show":(clearTimeout(e._timeout),e._hoverState="show",e.config.delay&&e.config.delay.show?e._timeout=setTimeout((function(){"show"===e._hoverState&&e.show()}),e.config.delay.show):e.show())},r._leave=function(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusout"===t.type?"focus":"hover"]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState="out",e.config.delay&&e.config.delay.hide?e._timeout=setTimeout((function(){"out"===e._hoverState&&e.hide()}),e.config.delay.hide):e.hide())},r._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},r._getConfig=function(t){var e=z.getDataAttributes(this._element);return Object.keys(e).forEach((function(t){Le.has(t)&&delete e[t]})),t&&"object"==typeof t.container&&t.container.jquery&&(t.container=t.container[0]),"number"==typeof(t=n({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),p("tooltip",t,this.constructor.DefaultType),t.sanitize&&(t.template=ke(t.template,t.allowList,t.sanitizeFn)),t},r._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},r._cleanTipClass=function(){var t=this.getTipElement(),e=t.getAttribute("class").match(Ae);null!==e&&e.length>0&&e.map((function(t){return t.trim()})).forEach((function(e){return t.classList.remove(e)}))},r._handlePopperPlacementChange=function(t){var e=t.state;e&&(this.tip=e.elements.popper,this._cleanTipClass(),this._addAttachmentClass(this._getAttachment(e.placement)))},o.jQueryInterface=function(t){return this.each((function(){var e=T(this,"bs.tooltip"),n="object"==typeof t&&t;if((e||!/dispose|hide/.test(t))&&(e||(e=new o(this,n)),"string"==typeof t)){if(void 0===e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},e(o,null,[{key:"Default",get:function(){return xe}},{key:"NAME",get:function(){return"tooltip"}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return Ce}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return Oe}}]),o}(H);y("tooltip",Se);var je=new RegExp("(^|\\s)bs-popover\\S+","g"),Ne=n({},Se.Default,{placement:"right",offset:[0,8],trigger:"click",content:"",template:''}),Pe=n({},Se.DefaultType,{content:"(string|element|function)"}),Ie={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},Me=function(t){function n(){return t.apply(this,arguments)||this}i(n,t);var o=n.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.setContent=function(){var t=this.getTipElement();this.setElementContent(Y(".popover-header",t),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this._element)),this.setElementContent(Y(".popover-body",t),e),t.classList.remove("fade","show")},o._addAttachmentClass=function(t){this.getTipElement().classList.add("bs-popover-"+this.updateAttachment(t))},o._getContent=function(){return this._element.getAttribute("data-bs-content")||this.config.content},o._cleanTipClass=function(){var t=this.getTipElement(),e=t.getAttribute("class").match(je);null!==e&&e.length>0&&e.map((function(t){return t.trim()})).forEach((function(e){return t.classList.remove(e)}))},n.jQueryInterface=function(t){return this.each((function(){var e=T(this,"bs.popover"),i="object"==typeof t?t:null;if((e||!/dispose|hide/.test(t))&&(e||(e=new n(this,i),E(this,"bs.popover",e)),"string"==typeof t)){if(void 0===e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},e(n,null,[{key:"Default",get:function(){return Ne}},{key:"NAME",get:function(){return"popover"}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return Ie}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return Pe}}]),n}(Se);y("popover",Me);var Be={offset:10,method:"auto",target:""},He={offset:"number",method:"string",target:"(string|element)"},Re=function(t){function o(e,n){var i;return(i=t.call(this,e)||this)._scrollElement="BODY"===e.tagName?window:e,i._config=i._getConfig(n),i._selector=i._config.target+" .nav-link, "+i._config.target+" .list-group-item, "+i._config.target+" .dropdown-item",i._offsets=[],i._targets=[],i._activeTarget=null,i._scrollHeight=0,B.on(i._scrollElement,"scroll.bs.scrollspy",(function(){return i._process()})),i.refresh(),i._process(),i}i(o,t);var r=o.prototype;return r.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?"offset":"position",n="auto"===this._config.method?e:this._config.method,i="position"===n?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),F(this._selector).map((function(t){var e=l(t),o=e?Y(e):null;if(o){var r=o.getBoundingClientRect();if(r.width||r.height)return[z[n](o).top+i,e]}return null})).filter((function(t){return t})).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},r.dispose=function(){t.prototype.dispose.call(this),B.off(this._scrollElement,".bs.scrollspy"),this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},r._getConfig=function(t){if("string"!=typeof(t=n({},Be,"object"==typeof t&&t?t:{})).target&&d(t.target)){var e=t.target.id;e||(e=s("scrollspy"),t.target.id=e),t.target="#"+e}return p("scrollspy",t,He),t},r._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},r._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},r._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},r._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;)this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&(void 0===this._offsets[o+1]||t li > .active":".active";e=(e=F(o,i))[e.length-1]}var r=e?B.trigger(e,"hide.bs.tab",{relatedTarget:this._element}):null;if(!(B.trigger(this._element,"show.bs.tab",{relatedTarget:e}).defaultPrevented||null!==r&&r.defaultPrevented)){this._activate(this._element,i);var s=function(){B.trigger(e,"hidden.bs.tab",{relatedTarget:t._element}),B.trigger(t._element,"shown.bs.tab",{relatedTarget:e})};n?this._activate(n,n.parentNode,s):s()}}},o._activate=function(t,e,n){var i=this,o=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?q(e,".active"):F(":scope > li > .active",e))[0],r=n&&o&&o.classList.contains("fade"),s=function(){return i._transitionComplete(t,o,n)};if(o&&r){var a=u(o);o.classList.remove("show"),B.one(o,"transitionend",s),h(o,a)}else s()},o._transitionComplete=function(t,e,n){if(e){e.classList.remove("active");var i=Y(":scope > .dropdown-menu .active",e.parentNode);i&&i.classList.remove("active"),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}t.classList.add("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),v(t),t.classList.contains("fade")&&t.classList.add("show"),t.parentNode&&t.parentNode.classList.contains("dropdown-menu")&&(t.closest(".dropdown")&&F(".dropdown-toggle").forEach((function(t){return t.classList.add("active")})),t.setAttribute("aria-expanded",!0)),n&&n()},n.jQueryInterface=function(t){return this.each((function(){var e=T(this,"bs.tab")||new n(this);if("string"==typeof t){if(void 0===e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},e(n,null,[{key:"DATA_KEY",get:function(){return"bs.tab"}}]),n}(H);B.on(document,"click.bs.tab.data-api",'[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',(function(t){t.preventDefault(),(T(this,"bs.tab")||new We(this)).show()})),y("tab",We);var Ke={animation:"boolean",autohide:"boolean",delay:"number"},Ue={animation:!0,autohide:!0,delay:5e3},ze=function(t){function o(e,n){var i;return(i=t.call(this,e)||this)._config=i._getConfig(n),i._timeout=null,i._setListeners(),i}i(o,t);var r=o.prototype;return r.show=function(){var t=this;if(!B.trigger(this._element,"show.bs.toast").defaultPrevented){this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");var e=function(){t._element.classList.remove("showing"),t._element.classList.add("show"),B.trigger(t._element,"shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove("hide"),v(this._element),this._element.classList.add("showing"),this._config.animation){var n=u(this._element);B.one(this._element,"transitionend",e),h(this._element,n)}else e()}},r.hide=function(){var t=this;if(this._element.classList.contains("show")&&!B.trigger(this._element,"hide.bs.toast").defaultPrevented){var e=function(){t._element.classList.add("hide"),B.trigger(t._element,"hidden.bs.toast")};if(this._element.classList.remove("show"),this._config.animation){var n=u(this._element);B.one(this._element,"transitionend",e),h(this._element,n)}else e()}},r.dispose=function(){this._clearTimeout(),this._element.classList.contains("show")&&this._element.classList.remove("show"),B.off(this._element,"click.dismiss.bs.toast"),t.prototype.dispose.call(this),this._config=null},r._getConfig=function(t){return t=n({},Ue,z.getDataAttributes(this._element),"object"==typeof t&&t?t:{}),p("toast",t,this.constructor.DefaultType),t},r._setListeners=function(){var t=this;B.on(this._element,"click.dismiss.bs.toast",'[data-bs-dismiss="toast"]',(function(){return t.hide()}))},r._clearTimeout=function(){clearTimeout(this._timeout),this._timeout=null},o.jQueryInterface=function(t){return this.each((function(){var e=T(this,"bs.toast");if(e||(e=new o(this,"object"==typeof t&&t)),"string"==typeof t){if(void 0===e[t])throw new TypeError('No method named "'+t+'"');e[t](this)}}))},e(o,null,[{key:"DefaultType",get:function(){return Ke}},{key:"Default",get:function(){return Ue}},{key:"DATA_KEY",get:function(){return"bs.toast"}}]),o}(H);return y("toast",ze),{Alert:R,Button:W,Carousel:$,Collapse:J,Dropdown:ve,Modal:ye,Popover:Me,ScrollSpy:Re,Tab:We,Toast:ze,Tooltip:Se}})); +/*! + * Bootstrap v5.0.0-beta2 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";function t(t,e){for(var n=0;n0,i._pointerEvent=Boolean(window.PointerEvent),i._addEventListeners(),i}i(o,t);var r=o.prototype;return r.next=function(){this._isSliding||this._slide("next")},r.nextWhenVisible=function(){!document.hidden&&g(this._element)&&this.next()},r.prev=function(){this._isSliding||this._slide("prev")},r.pause=function(t){t||(this._isPaused=!0),Y(".carousel-item-next, .carousel-item-prev",this._element)&&(f(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null},r.cycle=function(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config&&this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))},r.to=function(t){var e=this;this._activeElement=Y(".active.carousel-item",this._element);var n=this._getItemIndex(this._activeElement);if(!(t>this._items.length-1||t<0))if(this._isSliding)B.one(this._element,"slid.bs.carousel",(function(){return e.to(t)}));else{if(n===t)return this.pause(),void this.cycle();var i=t>n?"next":"prev";this._slide(i,this._items[t])}},r.dispose=function(){t.prototype.dispose.call(this),B.off(this._element,".bs.carousel"),this._items=null,this._config=null,this._interval=null,this._isPaused=null,this._isSliding=null,this._activeElement=null,this._indicatorsElement=null},r._getConfig=function(t){return t=n({},X,t),p("carousel",t,Q),t},r._handleSwipe=function(){var t=Math.abs(this.touchDeltaX);if(!(t<=40)){var e=t/this.touchDeltaX;this.touchDeltaX=0,e>0&&(b?this.next():this.prev()),e<0&&(b?this.prev():this.next())}},r._addEventListeners=function(){var t=this;this._config.keyboard&&B.on(this._element,"keydown.bs.carousel",(function(e){return t._keydown(e)})),"hover"===this._config.pause&&(B.on(this._element,"mouseenter.bs.carousel",(function(e){return t.pause(e)})),B.on(this._element,"mouseleave.bs.carousel",(function(e){return t.cycle(e)}))),this._config.touch&&this._touchSupported&&this._addTouchEventListeners()},r._addTouchEventListeners=function(){var t=this,e=function(e){!t._pointerEvent||"pen"!==e.pointerType&&"touch"!==e.pointerType?t._pointerEvent||(t.touchStartX=e.touches[0].clientX):t.touchStartX=e.clientX},n=function(e){!t._pointerEvent||"pen"!==e.pointerType&&"touch"!==e.pointerType||(t.touchDeltaX=e.clientX-t.touchStartX),t._handleSwipe(),"hover"===t._config.pause&&(t.pause(),t.touchTimeout&&clearTimeout(t.touchTimeout),t.touchTimeout=setTimeout((function(e){return t.cycle(e)}),500+t._config.interval))};F(".carousel-item img",this._element).forEach((function(t){B.on(t,"dragstart.bs.carousel",(function(t){return t.preventDefault()}))})),this._pointerEvent?(B.on(this._element,"pointerdown.bs.carousel",(function(t){return e(t)})),B.on(this._element,"pointerup.bs.carousel",(function(t){return n(t)})),this._element.classList.add("pointer-event")):(B.on(this._element,"touchstart.bs.carousel",(function(t){return e(t)})),B.on(this._element,"touchmove.bs.carousel",(function(e){return function(e){e.touches&&e.touches.length>1?t.touchDeltaX=0:t.touchDeltaX=e.touches[0].clientX-t.touchStartX}(e)})),B.on(this._element,"touchend.bs.carousel",(function(t){return n(t)})))},r._keydown=function(t){/input|textarea/i.test(t.target.tagName)||("ArrowLeft"===t.key?(t.preventDefault(),b?this.next():this.prev()):"ArrowRight"===t.key&&(t.preventDefault(),b?this.prev():this.next()))},r._getItemIndex=function(t){return this._items=t&&t.parentNode?F(".carousel-item",t.parentNode):[],this._items.indexOf(t)},r._getItemByDirection=function(t,e){var n="next"===t,i="prev"===t,o=this._getItemIndex(e),r=this._items.length-1;if((i&&0===o||n&&o===r)&&!this._config.wrap)return e;var s=(o+("prev"===t?-1:1))%this._items.length;return-1===s?this._items[this._items.length-1]:this._items[s]},r._triggerSlideEvent=function(t,e){var n=this._getItemIndex(t),i=this._getItemIndex(Y(".active.carousel-item",this._element));return B.trigger(this._element,"slide.bs.carousel",{relatedTarget:t,direction:e,from:i,to:n})},r._setActiveIndicatorElement=function(t){if(this._indicatorsElement){var e=Y(".active",this._indicatorsElement);e.classList.remove("active"),e.removeAttribute("aria-current");for(var n=F("[data-bs-target]",this._indicatorsElement),i=0;i0)for(var i=0;i=0}function _t(t){return((ut(t)?t.ownerDocument:t.document)||window.document).documentElement}function bt(t){return"html"===lt(t)?t:t.assignedSlot||t.parentNode||t.host||_t(t)}function yt(t){if(!ft(t)||"fixed"===mt(t).position)return null;var e=t.offsetParent;if(e){var n=_t(e);if("body"===lt(e)&&"static"===mt(e).position&&"static"!==mt(n).position)return n}return e}function wt(t){for(var e=ct(t),n=yt(t);n&&vt(n)&&"static"===mt(n).position;)n=yt(n);return n&&"body"===lt(n)&&"static"===mt(n).position?e:n||function(t){for(var e=bt(t);ft(e)&&["html","body"].indexOf(lt(e))<0;){var n=mt(e);if("none"!==n.transform||"none"!==n.perspective||n.willChange&&"auto"!==n.willChange)return e;e=e.parentNode}return null}(t)||e}function Et(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function Tt(t,e,n){return Math.max(t,Math.min(e,n))}function kt(t){return Object.assign(Object.assign({},{top:0,right:0,bottom:0,left:0}),t)}function At(t,e){return e.reduce((function(e,n){return e[n]=t,e}),{})}var Lt={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,n=t.state,i=t.name,o=n.elements.arrow,r=n.modifiersData.popperOffsets,s=ht(n.placement),a=Et(s),l=[it,nt].indexOf(s)>=0?"height":"width";if(o&&r){var c=n.modifiersData[i+"#persistent"].padding,u=pt(o),f="y"===a?tt:it,d="y"===a?et:nt,h=n.rects.reference[l]+n.rects.reference[a]-r[a]-n.rects.popper[l],p=r[a]-n.rects.reference[a],g=wt(o),m=g?"y"===a?g.clientHeight||0:g.clientWidth||0:0,v=h/2-p/2,_=c[f],b=m-u[l]-c[d],y=m/2-u[l]/2+v,w=Tt(_,y,b),E=a;n.modifiersData[i]=((e={})[E]=w,e.centerOffset=w-y,e)}},effect:function(t){var e=t.state,n=t.options,i=t.name,o=n.element,r=void 0===o?"[data-popper-arrow]":o,s=n.padding,a=void 0===s?0:s;null!=r&&("string"!=typeof r||(r=e.elements.popper.querySelector(r)))&>(e.elements.popper,r)&&(e.elements.arrow=r,e.modifiersData[i+"#persistent"]={padding:kt("number"!=typeof a?a:At(a,ot))})},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]},Ot={top:"auto",right:"auto",bottom:"auto",left:"auto"};function Dt(t){var e,n=t.popper,i=t.popperRect,o=t.placement,r=t.offsets,s=t.position,a=t.gpuAcceleration,l=t.adaptive,c=t.roundOffsets?function(t){var e=t.x,n=t.y,i=window.devicePixelRatio||1;return{x:Math.round(e*i)/i||0,y:Math.round(n*i)/i||0}}(r):r,u=c.x,f=void 0===u?0:u,d=c.y,h=void 0===d?0:d,p=r.hasOwnProperty("x"),g=r.hasOwnProperty("y"),m=it,v=tt,_=window;if(l){var b=wt(n);b===ct(n)&&(b=_t(n)),o===tt&&(v=et,h-=b.clientHeight-i.height,h*=a?1:-1),o===it&&(m=nt,f-=b.clientWidth-i.width,f*=a?1:-1)}var y,w=Object.assign({position:s},l&&Ot);return a?Object.assign(Object.assign({},w),{},((y={})[v]=g?"0":"",y[m]=p?"0":"",y.transform=(_.devicePixelRatio||1)<2?"translate("+f+"px, "+h+"px)":"translate3d("+f+"px, "+h+"px, 0)",y)):Object.assign(Object.assign({},w),{},((e={})[v]=g?h+"px":"",e[m]=p?f+"px":"",e.transform="",e))}var xt={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,n=t.options,i=n.gpuAcceleration,o=void 0===i||i,r=n.adaptive,s=void 0===r||r,a=n.roundOffsets,l=void 0===a||a,c={placement:ht(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:o};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign(Object.assign({},e.styles.popper),Dt(Object.assign(Object.assign({},c),{},{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:s,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign(Object.assign({},e.styles.arrow),Dt(Object.assign(Object.assign({},c),{},{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign(Object.assign({},e.attributes.popper),{},{"data-popper-placement":e.placement})},data:{}},Ct={passive:!0},St={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,n=t.instance,i=t.options,o=i.scroll,r=void 0===o||o,s=i.resize,a=void 0===s||s,l=ct(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return r&&c.forEach((function(t){t.addEventListener("scroll",n.update,Ct)})),a&&l.addEventListener("resize",n.update,Ct),function(){r&&c.forEach((function(t){t.removeEventListener("scroll",n.update,Ct)})),a&&l.removeEventListener("resize",n.update,Ct)}},data:{}},jt={left:"right",right:"left",bottom:"top",top:"bottom"};function Nt(t){return t.replace(/left|right|bottom|top/g,(function(t){return jt[t]}))}var Pt={start:"end",end:"start"};function It(t){return t.replace(/start|end/g,(function(t){return Pt[t]}))}function Mt(t){var e=t.getBoundingClientRect();return{width:e.width,height:e.height,top:e.top,right:e.right,bottom:e.bottom,left:e.left,x:e.left,y:e.top}}function Bt(t){var e=ct(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function Ht(t){return Mt(_t(t)).left+Bt(t).scrollLeft}function Rt(t){var e=mt(t),n=e.overflow,i=e.overflowX,o=e.overflowY;return/auto|scroll|overlay|hidden/.test(n+o+i)}function Wt(t,e){void 0===e&&(e=[]);var n=function t(e){return["html","body","#document"].indexOf(lt(e))>=0?e.ownerDocument.body:ft(e)&&Rt(e)?e:t(bt(e))}(t),i="body"===lt(n),o=ct(n),r=i?[o].concat(o.visualViewport||[],Rt(n)?n:[]):n,s=e.concat(r);return i?s:s.concat(Wt(bt(r)))}function Kt(t){return Object.assign(Object.assign({},t),{},{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function Ut(t,e){return"viewport"===e?Kt(function(t){var e=ct(t),n=_t(t),i=e.visualViewport,o=n.clientWidth,r=n.clientHeight,s=0,a=0;return i&&(o=i.width,r=i.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(s=i.offsetLeft,a=i.offsetTop)),{width:o,height:r,x:s+Ht(t),y:a}}(t)):ft(e)?function(t){var e=Mt(t);return e.top=e.top+t.clientTop,e.left=e.left+t.clientLeft,e.bottom=e.top+t.clientHeight,e.right=e.left+t.clientWidth,e.width=t.clientWidth,e.height=t.clientHeight,e.x=e.left,e.y=e.top,e}(e):Kt(function(t){var e=_t(t),n=Bt(t),i=t.ownerDocument.body,o=Math.max(e.scrollWidth,e.clientWidth,i?i.scrollWidth:0,i?i.clientWidth:0),r=Math.max(e.scrollHeight,e.clientHeight,i?i.scrollHeight:0,i?i.clientHeight:0),s=-n.scrollLeft+Ht(t),a=-n.scrollTop;return"rtl"===mt(i||e).direction&&(s+=Math.max(e.clientWidth,i?i.clientWidth:0)-o),{width:o,height:r,x:s,y:a}}(_t(t)))}function zt(t){return t.split("-")[1]}function Ft(t){var e,n=t.reference,i=t.element,o=t.placement,r=o?ht(o):null,s=o?zt(o):null,a=n.x+n.width/2-i.width/2,l=n.y+n.height/2-i.height/2;switch(r){case tt:e={x:a,y:n.y-i.height};break;case et:e={x:a,y:n.y+n.height};break;case nt:e={x:n.x+n.width,y:l};break;case it:e={x:n.x-i.width,y:l};break;default:e={x:n.x,y:n.y}}var c=r?Et(r):null;if(null!=c){var u="y"===c?"height":"width";switch(s){case"start":e[c]=e[c]-(n[u]/2-i[u]/2);break;case"end":e[c]=e[c]+(n[u]/2-i[u]/2)}}return e}function Yt(t,e){void 0===e&&(e={});var n=e,i=n.placement,o=void 0===i?t.placement:i,r=n.boundary,s=void 0===r?"clippingParents":r,a=n.rootBoundary,l=void 0===a?"viewport":a,c=n.elementContext,u=void 0===c?"popper":c,f=n.altBoundary,d=void 0!==f&&f,h=n.padding,p=void 0===h?0:h,g=kt("number"!=typeof p?p:At(p,ot)),m="popper"===u?"reference":"popper",v=t.elements.reference,_=t.rects.popper,b=t.elements[d?m:u],y=function(t,e,n){var i="clippingParents"===e?function(t){var e=Wt(bt(t)),n=["absolute","fixed"].indexOf(mt(t).position)>=0&&ft(t)?wt(t):t;return ut(n)?e.filter((function(t){return ut(t)&>(t,n)&&"body"!==lt(t)})):[]}(t):[].concat(e),o=[].concat(i,[n]),r=o[0],s=o.reduce((function(e,n){var i=Ut(t,n);return e.top=Math.max(i.top,e.top),e.right=Math.min(i.right,e.right),e.bottom=Math.min(i.bottom,e.bottom),e.left=Math.max(i.left,e.left),e}),Ut(t,r));return s.width=s.right-s.left,s.height=s.bottom-s.top,s.x=s.left,s.y=s.top,s}(ut(b)?b:b.contextElement||_t(t.elements.popper),s,l),w=Mt(v),E=Ft({reference:w,element:_,strategy:"absolute",placement:o}),T=Kt(Object.assign(Object.assign({},_),E)),k="popper"===u?T:w,A={top:y.top-k.top+g.top,bottom:k.bottom-y.bottom+g.bottom,left:y.left-k.left+g.left,right:k.right-y.right+g.right},L=t.modifiersData.offset;if("popper"===u&&L){var O=L[o];Object.keys(A).forEach((function(t){var e=[nt,et].indexOf(t)>=0?1:-1,n=[tt,et].indexOf(t)>=0?"y":"x";A[t]+=O[n]*e}))}return A}function qt(t,e){void 0===e&&(e={});var n=e,i=n.placement,o=n.boundary,r=n.rootBoundary,s=n.padding,a=n.flipVariations,l=n.allowedAutoPlacements,c=void 0===l?st:l,u=zt(i),f=u?a?rt:rt.filter((function(t){return zt(t)===u})):ot,d=f.filter((function(t){return c.indexOf(t)>=0}));0===d.length&&(d=f);var h=d.reduce((function(e,n){return e[n]=Yt(t,{placement:n,boundary:o,rootBoundary:r,padding:s})[ht(n)],e}),{});return Object.keys(h).sort((function(t,e){return h[t]-h[e]}))}var Vt={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,n=t.options,i=t.name;if(!e.modifiersData[i]._skip){for(var o=n.mainAxis,r=void 0===o||o,s=n.altAxis,a=void 0===s||s,l=n.fallbackPlacements,c=n.padding,u=n.boundary,f=n.rootBoundary,d=n.altBoundary,h=n.flipVariations,p=void 0===h||h,g=n.allowedAutoPlacements,m=e.options.placement,v=ht(m),_=l||(v!==m&&p?function(t){if("auto"===ht(t))return[];var e=Nt(t);return[It(t),e,It(e)]}(m):[Nt(m)]),b=[m].concat(_).reduce((function(t,n){return t.concat("auto"===ht(n)?qt(e,{placement:n,boundary:u,rootBoundary:f,padding:c,flipVariations:p,allowedAutoPlacements:g}):n)}),[]),y=e.rects.reference,w=e.rects.popper,E=new Map,T=!0,k=b[0],A=0;A=0,C=x?"width":"height",S=Yt(e,{placement:L,boundary:u,rootBoundary:f,altBoundary:d,padding:c}),j=x?D?nt:it:D?et:tt;y[C]>w[C]&&(j=Nt(j));var N=Nt(j),P=[];if(r&&P.push(S[O]<=0),a&&P.push(S[j]<=0,S[N]<=0),P.every((function(t){return t}))){k=L,T=!1;break}E.set(L,P)}if(T)for(var I=function(t){var e=b.find((function(e){var n=E.get(e);if(n)return n.slice(0,t).every((function(t){return t}))}));if(e)return k=e,"break"},M=p?3:1;M>0&&"break"!==I(M);M--);e.placement!==k&&(e.modifiersData[i]._skip=!0,e.placement=k,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function Xt(t,e,n){return void 0===n&&(n={x:0,y:0}),{top:t.top-e.height-n.y,right:t.right-e.width+n.x,bottom:t.bottom-e.height+n.y,left:t.left-e.width-n.x}}function Qt(t){return[tt,nt,et,it].some((function(e){return t[e]>=0}))}var $t={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,n=t.name,i=e.rects.reference,o=e.rects.popper,r=e.modifiersData.preventOverflow,s=Yt(e,{elementContext:"reference"}),a=Yt(e,{altBoundary:!0}),l=Xt(s,i),c=Xt(a,o,r),u=Qt(l),f=Qt(c);e.modifiersData[n]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:u,hasPopperEscaped:f},e.attributes.popper=Object.assign(Object.assign({},e.attributes.popper),{},{"data-popper-reference-hidden":u,"data-popper-escaped":f})}},Gt={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,n=t.options,i=t.name,o=n.offset,r=void 0===o?[0,0]:o,s=st.reduce((function(t,n){return t[n]=function(t,e,n){var i=ht(t),o=[it,tt].indexOf(i)>=0?-1:1,r="function"==typeof n?n(Object.assign(Object.assign({},e),{},{placement:t})):n,s=r[0],a=r[1];return s=s||0,a=(a||0)*o,[it,nt].indexOf(i)>=0?{x:a,y:s}:{x:s,y:a}}(n,e.rects,r),t}),{}),a=s[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[i]=s}},Zt={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,n=t.name;e.modifiersData[n]=Ft({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},Jt={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,n=t.options,i=t.name,o=n.mainAxis,r=void 0===o||o,s=n.altAxis,a=void 0!==s&&s,l=n.boundary,c=n.rootBoundary,u=n.altBoundary,f=n.padding,d=n.tether,h=void 0===d||d,p=n.tetherOffset,g=void 0===p?0:p,m=Yt(e,{boundary:l,rootBoundary:c,padding:f,altBoundary:u}),v=ht(e.placement),_=zt(e.placement),b=!_,y=Et(v),w="x"===y?"y":"x",E=e.modifiersData.popperOffsets,T=e.rects.reference,k=e.rects.popper,A="function"==typeof g?g(Object.assign(Object.assign({},e.rects),{},{placement:e.placement})):g,L={x:0,y:0};if(E){if(r){var O="y"===y?tt:it,D="y"===y?et:nt,x="y"===y?"height":"width",C=E[y],S=E[y]+m[O],j=E[y]-m[D],N=h?-k[x]/2:0,P="start"===_?T[x]:k[x],I="start"===_?-k[x]:-T[x],M=e.elements.arrow,B=h&&M?pt(M):{width:0,height:0},H=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},R=H[O],W=H[D],K=Tt(0,T[x],B[x]),U=b?T[x]/2-N-K-R-A:P-K-R-A,z=b?-T[x]/2+N+K+W+A:I+K+W+A,F=e.elements.arrow&&wt(e.elements.arrow),Y=F?"y"===y?F.clientTop||0:F.clientLeft||0:0,q=e.modifiersData.offset?e.modifiersData.offset[e.placement][y]:0,V=E[y]+U-q-Y,X=E[y]+z-q,Q=Tt(h?Math.min(S,V):S,C,h?Math.max(j,X):j);E[y]=Q,L[y]=Q-C}if(a){var $="x"===y?tt:it,G="x"===y?et:nt,Z=E[w],J=Tt(Z+m[$],Z,Z-m[G]);E[w]=J,L[w]=J-Z}e.modifiersData[i]=L}},requiresIfExists:["offset"]};function te(t,e,n){void 0===n&&(n=!1);var i,o,r=_t(e),s=Mt(t),a=ft(e),l={scrollLeft:0,scrollTop:0},c={x:0,y:0};return(a||!a&&!n)&&(("body"!==lt(e)||Rt(r))&&(l=(i=e)!==ct(i)&&ft(i)?{scrollLeft:(o=i).scrollLeft,scrollTop:o.scrollTop}:Bt(i)),ft(e)?((c=Mt(e)).x+=e.clientLeft,c.y+=e.clientTop):r&&(c.x=Ht(r))),{x:s.left+l.scrollLeft-c.x,y:s.top+l.scrollTop-c.y,width:s.width,height:s.height}}var ee={placement:"bottom",modifiers:[],strategy:"absolute"};function ne(){for(var t=arguments.length,e=new Array(t),n=0;n0&&r--,"ArrowDown"===t.key&&rdocument.documentElement.clientHeight;e||(this._element.style.overflowY="hidden"),this._element.classList.add("modal-static");var n=u(this._dialog);B.off(this._element,"transitionend"),B.one(this._element,"transitionend",(function(){t._element.classList.remove("modal-static"),e||(B.one(t._element,"transitionend",(function(){t._element.style.overflowY=""})),h(t._element,n))})),h(this._element,n),this._element.focus()}},r._adjustDialog=function(){var t=this._element.scrollHeight>document.documentElement.clientHeight;(!this._isBodyOverflowing&&t&&!b||this._isBodyOverflowing&&!t&&b)&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),(this._isBodyOverflowing&&!t&&!b||!this._isBodyOverflowing&&t&&b)&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},r._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},r._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=Math.round(t.left+t.right)
',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:[0,0],container:!1,fallbackPlacements:["top","right","bottom","left"],boundary:"clippingParents",customClass:"",sanitize:!0,sanitizeFn:null,allowList:{"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},popperConfig:null},Ce={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},Se=function(t){function o(e,n){var i;if(void 0===ae)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");return(i=t.call(this,e)||this)._isEnabled=!0,i._timeout=0,i._hoverState="",i._activeTrigger={},i._popper=null,i.config=i._getConfig(n),i.tip=null,i._setListeners(),i}i(o,t);var r=o.prototype;return r.enable=function(){this._isEnabled=!0},r.disable=function(){this._isEnabled=!1},r.toggleEnabled=function(){this._isEnabled=!this._isEnabled},r.toggle=function(t){if(this._isEnabled)if(t){var e=this._initializeOnDelegatedTarget(t);e._activeTrigger.click=!e._activeTrigger.click,e._isWithActiveTrigger()?e._enter(null,e):e._leave(null,e)}else{if(this.getTipElement().classList.contains("show"))return void this._leave(null,this);this._enter(null,this)}},r.dispose=function(){clearTimeout(this._timeout),B.off(this._element,this.constructor.EVENT_KEY),B.off(this._element.closest(".modal"),"hide.bs.modal",this._hideModalHandler),this.tip&&this.tip.parentNode&&this.tip.parentNode.removeChild(this.tip),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.config=null,this.tip=null,t.prototype.dispose.call(this)},r.show=function(){var t=this;if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(this.isWithContent()&&this._isEnabled){var e=B.trigger(this._element,this.constructor.Event.SHOW),n=function t(e){if(!document.documentElement.attachShadow)return null;if("function"==typeof e.getRootNode){var n=e.getRootNode();return n instanceof ShadowRoot?n:null}return e instanceof ShadowRoot?e:e.parentNode?t(e.parentNode):null}(this._element),i=null===n?this._element.ownerDocument.documentElement.contains(this._element):n.contains(this._element);if(!e.defaultPrevented&&i){var o=this.getTipElement(),r=s(this.constructor.NAME);o.setAttribute("id",r),this._element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&o.classList.add("fade");var a="function"==typeof this.config.placement?this.config.placement.call(this,o,this._element):this.config.placement,l=this._getAttachment(a);this._addAttachmentClass(l);var c=this._getContainer();E(o,this.constructor.DATA_KEY,this),this._element.ownerDocument.documentElement.contains(this.tip)||c.appendChild(o),B.trigger(this._element,this.constructor.Event.INSERTED),this._popper=se(this._element,o,this._getPopperConfig(l)),o.classList.add("show");var f,d,p="function"==typeof this.config.customClass?this.config.customClass():this.config.customClass;p&&(f=o.classList).add.apply(f,p.split(" ")),"ontouchstart"in document.documentElement&&(d=[]).concat.apply(d,document.body.children).forEach((function(t){B.on(t,"mouseover",(function(){}))}));var g=function(){var e=t._hoverState;t._hoverState=null,B.trigger(t._element,t.constructor.Event.SHOWN),"out"===e&&t._leave(null,t)};if(this.tip.classList.contains("fade")){var m=u(this.tip);B.one(this.tip,"transitionend",g),h(this.tip,m)}else g()}}},r.hide=function(){var t=this;if(this._popper){var e=this.getTipElement(),n=function(){"show"!==t._hoverState&&e.parentNode&&e.parentNode.removeChild(e),t._cleanTipClass(),t._element.removeAttribute("aria-describedby"),B.trigger(t._element,t.constructor.Event.HIDDEN),t._popper&&(t._popper.destroy(),t._popper=null)};if(!B.trigger(this._element,this.constructor.Event.HIDE).defaultPrevented){var i;if(e.classList.remove("show"),"ontouchstart"in document.documentElement&&(i=[]).concat.apply(i,document.body.children).forEach((function(t){return B.off(t,"mouseover",m)})),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,this.tip.classList.contains("fade")){var o=u(e);B.one(e,"transitionend",n),h(e,o)}else n();this._hoverState=""}}},r.update=function(){null!==this._popper&&this._popper.update()},r.isWithContent=function(){return Boolean(this.getTitle())},r.getTipElement=function(){if(this.tip)return this.tip;var t=document.createElement("div");return t.innerHTML=this.config.template,this.tip=t.children[0],this.tip},r.setContent=function(){var t=this.getTipElement();this.setElementContent(Y(".tooltip-inner",t),this.getTitle()),t.classList.remove("fade","show")},r.setElementContent=function(t,e){if(null!==t)return"object"==typeof e&&d(e)?(e.jquery&&(e=e[0]),void(this.config.html?e.parentNode!==t&&(t.innerHTML="",t.appendChild(e)):t.textContent=e.textContent)):void(this.config.html?(this.config.sanitize&&(e=ke(e,this.config.allowList,this.config.sanitizeFn)),t.innerHTML=e):t.textContent=e)},r.getTitle=function(){var t=this._element.getAttribute("data-bs-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this._element):this.config.title),t},r.updateAttachment=function(t){return"right"===t?"end":"left"===t?"start":t},r._initializeOnDelegatedTarget=function(t,e){var n=this.constructor.DATA_KEY;return(e=e||T(t.delegateTarget,n))||(e=new this.constructor(t.delegateTarget,this._getDelegateConfig()),E(t.delegateTarget,n,e)),e},r._getOffset=function(){var t=this,e=this.config.offset;return"string"==typeof e?e.split(",").map((function(t){return Number.parseInt(t,10)})):"function"==typeof e?function(n){return e(n,t._element)}:e},r._getPopperConfig=function(t){var e=this,i={placement:t,modifiers:[{name:"flip",options:{altBoundary:!0,fallbackPlacements:this.config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this.config.boundary}},{name:"arrow",options:{element:"."+this.constructor.NAME+"-arrow"}},{name:"onChange",enabled:!0,phase:"afterWrite",fn:function(t){return e._handlePopperPlacementChange(t)}}],onFirstUpdate:function(t){t.options.placement!==t.placement&&e._handlePopperPlacementChange(t)}};return n({},i,"function"==typeof this.config.popperConfig?this.config.popperConfig(i):this.config.popperConfig)},r._addAttachmentClass=function(t){this.getTipElement().classList.add("bs-tooltip-"+this.updateAttachment(t))},r._getContainer=function(){return!1===this.config.container?document.body:d(this.config.container)?this.config.container:Y(this.config.container)},r._getAttachment=function(t){return De[t.toUpperCase()]},r._setListeners=function(){var t=this;this.config.trigger.split(" ").forEach((function(e){if("click"===e)B.on(t._element,t.constructor.Event.CLICK,t.config.selector,(function(e){return t.toggle(e)}));else if("manual"!==e){var n="hover"===e?t.constructor.Event.MOUSEENTER:t.constructor.Event.FOCUSIN,i="hover"===e?t.constructor.Event.MOUSELEAVE:t.constructor.Event.FOCUSOUT;B.on(t._element,n,t.config.selector,(function(e){return t._enter(e)})),B.on(t._element,i,t.config.selector,(function(e){return t._leave(e)}))}})),this._hideModalHandler=function(){t._element&&t.hide()},B.on(this._element.closest(".modal"),"hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=n({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},r._fixTitle=function(){var t=this._element.getAttribute("title"),e=typeof this._element.getAttribute("data-bs-original-title");(t||"string"!==e)&&(this._element.setAttribute("data-bs-original-title",t||""),!t||this._element.getAttribute("aria-label")||this._element.textContent||this._element.setAttribute("aria-label",t),this._element.setAttribute("title",""))},r._enter=function(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusin"===t.type?"focus":"hover"]=!0),e.getTipElement().classList.contains("show")||"show"===e._hoverState?e._hoverState="show":(clearTimeout(e._timeout),e._hoverState="show",e.config.delay&&e.config.delay.show?e._timeout=setTimeout((function(){"show"===e._hoverState&&e.show()}),e.config.delay.show):e.show())},r._leave=function(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusout"===t.type?"focus":"hover"]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState="out",e.config.delay&&e.config.delay.hide?e._timeout=setTimeout((function(){"out"===e._hoverState&&e.hide()}),e.config.delay.hide):e.hide())},r._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},r._getConfig=function(t){var e=z.getDataAttributes(this._element);return Object.keys(e).forEach((function(t){Le.has(t)&&delete e[t]})),t&&"object"==typeof t.container&&t.container.jquery&&(t.container=t.container[0]),"number"==typeof(t=n({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),p("tooltip",t,this.constructor.DefaultType),t.sanitize&&(t.template=ke(t.template,t.allowList,t.sanitizeFn)),t},r._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},r._cleanTipClass=function(){var t=this.getTipElement(),e=t.getAttribute("class").match(Ae);null!==e&&e.length>0&&e.map((function(t){return t.trim()})).forEach((function(e){return t.classList.remove(e)}))},r._handlePopperPlacementChange=function(t){var e=t.state;e&&(this.tip=e.elements.popper,this._cleanTipClass(),this._addAttachmentClass(this._getAttachment(e.placement)))},o.jQueryInterface=function(t){return this.each((function(){var e=T(this,"bs.tooltip"),n="object"==typeof t&&t;if((e||!/dispose|hide/.test(t))&&(e||(e=new o(this,n)),"string"==typeof t)){if(void 0===e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},e(o,null,[{key:"Default",get:function(){return xe}},{key:"NAME",get:function(){return"tooltip"}},{key:"DATA_KEY",get:function(){return"bs.tooltip"}},{key:"Event",get:function(){return Ce}},{key:"EVENT_KEY",get:function(){return".bs.tooltip"}},{key:"DefaultType",get:function(){return Oe}}]),o}(H);y("tooltip",Se);var je=new RegExp("(^|\\s)bs-popover\\S+","g"),Ne=n({},Se.Default,{placement:"right",offset:[0,8],trigger:"click",content:"",template:''}),Pe=n({},Se.DefaultType,{content:"(string|element|function)"}),Ie={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"},Me=function(t){function n(){return t.apply(this,arguments)||this}i(n,t);var o=n.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.setContent=function(){var t=this.getTipElement();this.setElementContent(Y(".popover-header",t),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this._element)),this.setElementContent(Y(".popover-body",t),e),t.classList.remove("fade","show")},o._addAttachmentClass=function(t){this.getTipElement().classList.add("bs-popover-"+this.updateAttachment(t))},o._getContent=function(){return this._element.getAttribute("data-bs-content")||this.config.content},o._cleanTipClass=function(){var t=this.getTipElement(),e=t.getAttribute("class").match(je);null!==e&&e.length>0&&e.map((function(t){return t.trim()})).forEach((function(e){return t.classList.remove(e)}))},n.jQueryInterface=function(t){return this.each((function(){var e=T(this,"bs.popover"),i="object"==typeof t?t:null;if((e||!/dispose|hide/.test(t))&&(e||(e=new n(this,i),E(this,"bs.popover",e)),"string"==typeof t)){if(void 0===e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},e(n,null,[{key:"Default",get:function(){return Ne}},{key:"NAME",get:function(){return"popover"}},{key:"DATA_KEY",get:function(){return"bs.popover"}},{key:"Event",get:function(){return Ie}},{key:"EVENT_KEY",get:function(){return".bs.popover"}},{key:"DefaultType",get:function(){return Pe}}]),n}(Se);y("popover",Me);var Be={offset:10,method:"auto",target:""},He={offset:"number",method:"string",target:"(string|element)"},Re=function(t){function o(e,n){var i;return(i=t.call(this,e)||this)._scrollElement="BODY"===e.tagName?window:e,i._config=i._getConfig(n),i._selector=i._config.target+" .nav-link, "+i._config.target+" .list-group-item, "+i._config.target+" .dropdown-item",i._offsets=[],i._targets=[],i._activeTarget=null,i._scrollHeight=0,B.on(i._scrollElement,"scroll.bs.scrollspy",(function(){return i._process()})),i.refresh(),i._process(),i}i(o,t);var r=o.prototype;return r.refresh=function(){var t=this,e=this._scrollElement===this._scrollElement.window?"offset":"position",n="auto"===this._config.method?e:this._config.method,i="position"===n?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),F(this._selector).map((function(t){var e=l(t),o=e?Y(e):null;if(o){var r=o.getBoundingClientRect();if(r.width||r.height)return[z[n](o).top+i,e]}return null})).filter((function(t){return t})).sort((function(t,e){return t[0]-e[0]})).forEach((function(e){t._offsets.push(e[0]),t._targets.push(e[1])}))},r.dispose=function(){t.prototype.dispose.call(this),B.off(this._scrollElement,".bs.scrollspy"),this._scrollElement=null,this._config=null,this._selector=null,this._offsets=null,this._targets=null,this._activeTarget=null,this._scrollHeight=null},r._getConfig=function(t){if("string"!=typeof(t=n({},Be,"object"==typeof t&&t?t:{})).target&&d(t.target)){var e=t.target.id;e||(e=s("scrollspy"),t.target.id=e),t.target="#"+e}return p("scrollspy",t,He),t},r._getScrollTop=function(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop},r._getScrollHeight=function(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)},r._getOffsetHeight=function(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height},r._process=function(){var t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),n=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=n){var i=this._targets[this._targets.length-1];this._activeTarget!==i&&this._activate(i)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(var o=this._offsets.length;o--;)this._activeTarget!==this._targets[o]&&t>=this._offsets[o]&&(void 0===this._offsets[o+1]||t li > .active":".active";e=(e=F(o,i))[e.length-1]}var r=e?B.trigger(e,"hide.bs.tab",{relatedTarget:this._element}):null;if(!(B.trigger(this._element,"show.bs.tab",{relatedTarget:e}).defaultPrevented||null!==r&&r.defaultPrevented)){this._activate(this._element,i);var s=function(){B.trigger(e,"hidden.bs.tab",{relatedTarget:t._element}),B.trigger(t._element,"shown.bs.tab",{relatedTarget:e})};n?this._activate(n,n.parentNode,s):s()}}},o._activate=function(t,e,n){var i=this,o=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?q(e,".active"):F(":scope > li > .active",e))[0],r=n&&o&&o.classList.contains("fade"),s=function(){return i._transitionComplete(t,o,n)};if(o&&r){var a=u(o);o.classList.remove("show"),B.one(o,"transitionend",s),h(o,a)}else s()},o._transitionComplete=function(t,e,n){if(e){e.classList.remove("active");var i=Y(":scope > .dropdown-menu .active",e.parentNode);i&&i.classList.remove("active"),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}t.classList.add("active"),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),v(t),t.classList.contains("fade")&&t.classList.add("show"),t.parentNode&&t.parentNode.classList.contains("dropdown-menu")&&(t.closest(".dropdown")&&F(".dropdown-toggle").forEach((function(t){return t.classList.add("active")})),t.setAttribute("aria-expanded",!0)),n&&n()},n.jQueryInterface=function(t){return this.each((function(){var e=T(this,"bs.tab")||new n(this);if("string"==typeof t){if(void 0===e[t])throw new TypeError('No method named "'+t+'"');e[t]()}}))},e(n,null,[{key:"DATA_KEY",get:function(){return"bs.tab"}}]),n}(H);B.on(document,"click.bs.tab.data-api",'[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',(function(t){t.preventDefault(),(T(this,"bs.tab")||new We(this)).show()})),y("tab",We);var Ke={animation:"boolean",autohide:"boolean",delay:"number"},Ue={animation:!0,autohide:!0,delay:5e3},ze=function(t){function o(e,n){var i;return(i=t.call(this,e)||this)._config=i._getConfig(n),i._timeout=null,i._setListeners(),i}i(o,t);var r=o.prototype;return r.show=function(){var t=this;if(!B.trigger(this._element,"show.bs.toast").defaultPrevented){this._clearTimeout(),this._config.animation&&this._element.classList.add("fade");var e=function(){t._element.classList.remove("showing"),t._element.classList.add("show"),B.trigger(t._element,"shown.bs.toast"),t._config.autohide&&(t._timeout=setTimeout((function(){t.hide()}),t._config.delay))};if(this._element.classList.remove("hide"),v(this._element),this._element.classList.add("showing"),this._config.animation){var n=u(this._element);B.one(this._element,"transitionend",e),h(this._element,n)}else e()}},r.hide=function(){var t=this;if(this._element.classList.contains("show")&&!B.trigger(this._element,"hide.bs.toast").defaultPrevented){var e=function(){t._element.classList.add("hide"),B.trigger(t._element,"hidden.bs.toast")};if(this._element.classList.remove("show"),this._config.animation){var n=u(this._element);B.one(this._element,"transitionend",e),h(this._element,n)}else e()}},r.dispose=function(){this._clearTimeout(),this._element.classList.contains("show")&&this._element.classList.remove("show"),B.off(this._element,"click.dismiss.bs.toast"),t.prototype.dispose.call(this),this._config=null},r._getConfig=function(t){return t=n({},Ue,z.getDataAttributes(this._element),"object"==typeof t&&t?t:{}),p("toast",t,this.constructor.DefaultType),t},r._setListeners=function(){var t=this;B.on(this._element,"click.dismiss.bs.toast",'[data-bs-dismiss="toast"]',(function(){return t.hide()}))},r._clearTimeout=function(){clearTimeout(this._timeout),this._timeout=null},o.jQueryInterface=function(t){return this.each((function(){var e=T(this,"bs.toast");if(e||(e=new o(this,"object"==typeof t&&t)),"string"==typeof t){if(void 0===e[t])throw new TypeError('No method named "'+t+'"');e[t](this)}}))},e(o,null,[{key:"DefaultType",get:function(){return Ke}},{key:"Default",get:function(){return Ue}},{key:"DATA_KEY",get:function(){return"bs.toast"}}]),o}(H);return y("toast",ze),{Alert:R,Button:W,Carousel:$,Collapse:J,Dropdown:ve,Modal:ye,Popover:Me,ScrollSpy:Re,Tab:We,Toast:ze,Tooltip:Se}})); //# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/assets/js/hesabix-admin.js b/assets/js/hesabix-admin.js new file mode 100644 index 0000000..54affca --- /dev/null +++ b/assets/js/hesabix-admin.js @@ -0,0 +1,1875 @@ +/* + * 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(''); + } + + $.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(''); + } + + 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('خطا'); + $('#hesabix-home-products-label').text('محصولات'); + $('#hesabix-home-customers-count').html('خطا'); + $('#hesabix-home-customers-label').text('مشتریان'); + $('#hesabix-home-orders-count').html('خطا'); + $('#hesabix-home-orders-label').text('سفارشات'); + $('#hesabix-home-connection-card').removeClass('connected not-connected'); + $('#hesabix-home-connection-icon').attr('d', ''); + $('#hesabix-home-connection-text').html('خطا'); + $('#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(` + + + + + نسخه جدید ${data.latest_version} موجود است + + `); + btn.attr('onclick', `window.open('${data.download_url}', '_blank')`); + this.showUpdateNotification(data); + } else { + btn.removeClass('hesabix-update-badge').addClass('hesabix-badge status'); + btn.html(` + + + + + نسخه فعلی بروز است + + `); + 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(` + + + + + ${message} + + `); + btn.removeAttr('onclick'); + }); + }, + + showUpdateNotification: function(data) { + const notification = $(` +
+
+

نسخه جدید موجود است!

+ +
+

+ نسخه ${data.latest_version} از پلاگین حسابیکس منتشر شده است. + نسخه فعلی شما: ${data.current_version} +

+
+ + +
+
+ `); + + 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(' خروج محصولات...'); + $('#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(' در حال ورود کالاها از حسابیکس, لطفاً صبر کنید...'); + $('#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(' استخراج موجودی اول دوره...'); + $('#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(' خروجی مشتریان، لطفاً صبر کنید...'); + $('#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(''); + $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(''); + $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(''); + $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(''); + $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(''); + $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(''); + $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(' بروزرسانی محصولات لطفا صبر کنید...') + .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 = '
' + + '' + + '' + + '' + message + '
'; + + 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: 'adminSaveApiSettings', + 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: 'adminTestApiConnection', + 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 = ` +
+
+ ${message} +
+
+ `; + 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('

در حال بارگذاری...

'); + $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('
خطا در بارگذاری محتوا
'); + } + }, + error: () => { + $tabContent.html('
خطا در بارگذاری محتوا
'); + } + }); + } + }); + }, + + 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 ? + '
تنظیمات با موفقیت ذخیره شد.
' : + '
خطا در ذخیره تنظیمات!
'; + $('#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 = '
خطا در ذخیره تنظیمات!
'; + $('#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 ? + '
تنظیمات با موفقیت ذخیره شد.
' : + '
خطا در ذخیره تنظیمات!
'; + $('#catalog-settings-message').html(msg).fadeIn(); + $('html, body').animate({ scrollTop: 0 }, 500); + }, + error: () => { + $btn.removeClass('loading').prop('disabled', false); + const msg = '
خطا در ذخیره تنظیمات!
'; + $('#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 ? + '
تنظیمات با موفقیت ذخیره شد.
' : + '
خطا در ذخیره تنظیمات!
'; + $('#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 = '
خطا در ذخیره تنظیمات!
'; + $('#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 ? + '
تنظیمات با موفقیت ذخیره شد.
' : + '
خطا در ذخیره تنظیمات!
'; + $('#customers-settings-message').html(msg).fadeIn(); + $('html, body').animate({ scrollTop: 0 }, 500); + }, + error: () => { + $btn.removeClass('loading').prop('disabled', false); + const msg = '
خطا در ذخیره تنظیمات!
'; + $('#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 ? + '
فیلدهای اضافی با موفقیت ذخیره شد.
' : + '
خطا در ذخیره فیلدهای اضافی!
'; + $('#customers-fields-message').html(msg).fadeIn(); + $('html, body').animate({ scrollTop: 0 }, 500); + }, + error: () => { + $btn.removeClass('loading').prop('disabled', false); + const msg = '
خطا در ذخیره فیلدهای اضافی!
'; + $('#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} (${daysDiff} روز)`); + } + } + }, + + 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(); +} \ No newline at end of file diff --git a/assets/js/hesabix.js b/assets/js/hesabix.js new file mode 100644 index 0000000..54affca --- /dev/null +++ b/assets/js/hesabix.js @@ -0,0 +1,1875 @@ +/* + * 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(''); + } + + $.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(''); + } + + 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('خطا'); + $('#hesabix-home-products-label').text('محصولات'); + $('#hesabix-home-customers-count').html('خطا'); + $('#hesabix-home-customers-label').text('مشتریان'); + $('#hesabix-home-orders-count').html('خطا'); + $('#hesabix-home-orders-label').text('سفارشات'); + $('#hesabix-home-connection-card').removeClass('connected not-connected'); + $('#hesabix-home-connection-icon').attr('d', ''); + $('#hesabix-home-connection-text').html('خطا'); + $('#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(` + + + + + نسخه جدید ${data.latest_version} موجود است + + `); + btn.attr('onclick', `window.open('${data.download_url}', '_blank')`); + this.showUpdateNotification(data); + } else { + btn.removeClass('hesabix-update-badge').addClass('hesabix-badge status'); + btn.html(` + + + + + نسخه فعلی بروز است + + `); + 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(` + + + + + ${message} + + `); + btn.removeAttr('onclick'); + }); + }, + + showUpdateNotification: function(data) { + const notification = $(` +
+
+

نسخه جدید موجود است!

+ +
+

+ نسخه ${data.latest_version} از پلاگین حسابیکس منتشر شده است. + نسخه فعلی شما: ${data.current_version} +

+
+ + +
+
+ `); + + 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(' خروج محصولات...'); + $('#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(' در حال ورود کالاها از حسابیکس, لطفاً صبر کنید...'); + $('#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(' استخراج موجودی اول دوره...'); + $('#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(' خروجی مشتریان، لطفاً صبر کنید...'); + $('#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(''); + $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(''); + $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(''); + $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(''); + $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(''); + $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(''); + $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(' بروزرسانی محصولات لطفا صبر کنید...') + .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 = '
' + + '' + + '' + + '' + message + '
'; + + 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: 'adminSaveApiSettings', + 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: 'adminTestApiConnection', + 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 = ` +
+
+ ${message} +
+
+ `; + 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('

در حال بارگذاری...

'); + $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('
خطا در بارگذاری محتوا
'); + } + }, + error: () => { + $tabContent.html('
خطا در بارگذاری محتوا
'); + } + }); + } + }); + }, + + 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 ? + '
تنظیمات با موفقیت ذخیره شد.
' : + '
خطا در ذخیره تنظیمات!
'; + $('#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 = '
خطا در ذخیره تنظیمات!
'; + $('#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 ? + '
تنظیمات با موفقیت ذخیره شد.
' : + '
خطا در ذخیره تنظیمات!
'; + $('#catalog-settings-message').html(msg).fadeIn(); + $('html, body').animate({ scrollTop: 0 }, 500); + }, + error: () => { + $btn.removeClass('loading').prop('disabled', false); + const msg = '
خطا در ذخیره تنظیمات!
'; + $('#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 ? + '
تنظیمات با موفقیت ذخیره شد.
' : + '
خطا در ذخیره تنظیمات!
'; + $('#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 = '
خطا در ذخیره تنظیمات!
'; + $('#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 ? + '
تنظیمات با موفقیت ذخیره شد.
' : + '
خطا در ذخیره تنظیمات!
'; + $('#customers-settings-message').html(msg).fadeIn(); + $('html, body').animate({ scrollTop: 0 }, 500); + }, + error: () => { + $btn.removeClass('loading').prop('disabled', false); + const msg = '
خطا در ذخیره تنظیمات!
'; + $('#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 ? + '
فیلدهای اضافی با موفقیت ذخیره شد.
' : + '
خطا در ذخیره فیلدهای اضافی!
'; + $('#customers-fields-message').html(msg).fadeIn(); + $('html, body').animate({ scrollTop: 0 }, 500); + }, + error: () => { + $btn.removeClass('loading').prop('disabled', false); + const msg = '
خطا در ذخیره فیلدهای اضافی!
'; + $('#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} (${daysDiff} روز)`); + } + } + }, + + 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(); +} \ No newline at end of file diff --git a/hesabix.php b/hesabix.php new file mode 100644 index 0000000..500844a --- /dev/null +++ b/hesabix.php @@ -0,0 +1,74 @@ +run(); +} + +run_hesabix(); + +add_filter('admin_footer_text', function ($footer_text) { + global $pagenow; + if ($pagenow === 'admin.php' && isset($_GET['page']) && $_GET['page'] === 'hesabix-option') { + return __('Hesabix Plugin developed with', 'hesabix') . + ' ' . + __('by', 'hesabix') . + ' ' . __('Mohammad Rezai', 'hesabix') . '.' . + ' + + + + + + + + ' . __('Pirouz', 'hesabix') . ' + '; + } + return $footer_text; +}, 999); + diff --git a/includes/class-hesabix-activator.php b/includes/class-hesabix-activator.php new file mode 100644 index 0000000..5e4c987 --- /dev/null +++ b/includes/class-hesabix-activator.php @@ -0,0 +1,56 @@ +prefix . "hesabix"; + $charset_collate = $wpdb->get_charset_collate(); + + $sql = " + CREATE TABLE $table_name ( + id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, + obj_type varchar(32) NOT NULL, + id_hesabix int(11) UNSIGNED NOT NULL, + id_ps int(11) UNSIGNED NOT NULL, + id_ps_attribute int(11) UNSIGNED NOT NULL DEFAULT 0, + uid_hesabix int(11) UNSIGNED NOT NULL, + PRIMARY KEY (id) + ) $charset_collate;"; + + require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); + dbDelta($sql); + + update_option('hesabix_db_version', self::$hesabix_db_version); + } +} diff --git a/includes/class-ssbhesabix-api.php b/includes/class-hesabix-api.php similarity index 63% rename from includes/class-ssbhesabix-api.php rename to includes/class-hesabix-api.php index 5fc9ca2..7bfc33f 100644 --- a/includes/class-ssbhesabix-api.php +++ b/includes/class-hesabix-api.php @@ -1,532 +1,550 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - */ - -class Ssbhesabix_Api -{ - //================================================================================================ - public function apiRequest($method, $data = array()) - { - if ($method == null) - return false; - - $endpoint = 'https://hesabix.ir/' . $method; - - $apiAddress = get_option('ssbhesabix_api_address', 0); - - if ($apiAddress == 1) - $endpoint = 'https://next.hesabix.ir/' . $method; - - $body = array_merge(array( - 'API-KEY' => get_option('ssbhesabix_account_api'), - ), $data); - - //Debug mode - if (get_option('ssbhesabix_debug_mode')) { - HesabixLogService::log(array("Debug Mode - Data: " . print_r($data, true))); - } - - $options = array( - 'body' => wp_json_encode($body), - 'headers' => array( - 'Content-Type' => 'application/json', - 'API-KEY' => get_option('ssbhesabix_account_api'), - 'activeBid' => get_option('ssbhesabix_account_bid'), - 'activeYear' => get_option('ssbhesabix_account_year'), - ), - 'timeout' => 60, - 'redirection' => 5, - 'blocking' => true, - 'httpversion' => '1.0', - 'sslverify' => false, - 'data_format' => 'body', - ); - - //HesabixLogService::writeLogObj($options); - - $wp_remote_post = wp_remote_post($endpoint, $options); - $result = json_decode(wp_remote_retrieve_body($wp_remote_post)); - - //Debug mode - if (get_option('ssbhesabix_debug_mode')) { - HesabixLogService::log(array("Debug Mode - Result: " . print_r($result, true))); - } - - //fix API limit request - Maximum request per minutes is 60 times, - sleep(1); - - if ($result == null) { - return 'No response from Hesabix'; - } else { - if (!isset($result->Success)) { - switch ($result->ErrorCode) { - case '100': - return 'InternalServerError'; - case '101': - return 'TooManyRequests'; - case '103': - return 'MissingData'; - case '104': - return 'MissingParameter' . '. ErrorMessage: ' . $result->ErrorMessage; - case '105': - return 'ApiDisabled'; - case '106': - return 'UserIsNotOwner'; - case '107': - return 'BusinessNotFound'; - case '108': - return 'BusinessExpired'; - case '110': - return 'IdMustBeZero'; - case '111': - return 'IdMustNotBeZero'; - case '112': - return 'ObjectNotFound' . '. ErrorMessage: ' . $result->ErrorMessage; - case '113': - return 'MissingApiKey'; - case '114': - return 'ParameterIsOutOfRange' . '. ErrorMessage: ' . $result->ErrorMessage; - case '190': - return 'ApplicationError' . '. ErrorMessage: ' . $result->ErrorMessage; - } - } else { - return $result; - } - } - return false; - } - //================================================================================================ - //Contact functions - public function contactGet($code) - { - $method = 'contact/get'; - $data = array( - 'code' => $code, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function contactGetById($idList) - { - $method = 'contact/getById'; - $data = array( - 'idList' => $idList, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function contactGetContacts($queryInfo) - { - $method = 'contact/getcontacts'; - $data = array( - 'queryInfo' => $queryInfo, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function contactSave($contact) - { - $method = 'api/person/mod'; - return $this->apiRequest($method, $contact); - } - //================================================================================================ - public function contactBatchSave($contacts) - { - $method = 'api/person/group/mod'; - $data = array( - 'items' => $contacts, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function contactDelete($code) - { - $method = 'contact/delete'; - $data = array( - 'code' => $code, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function contactGetByPhoneOrEmail($phone, $email) - { - $method = 'contact/findByPhoneOrEmail'; - $data = array( - 'mobile' => $phone, - 'email' => $email, - 'phone' => $phone, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - //Items functions - public function itemGet($code) - { - $method = 'item/get'; - $data = array( - 'code' => $code, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function itemGetByBarcode($barcode) - { - $method = 'item/getByBarcode'; - $data = array( - 'barcode' => $barcode, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function itemGetById($idList) - { - $method = 'item/getById'; - $data = array( - 'idList' => $idList, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function itemGetItems($queryInfo = null) - { - $method = 'api/commodity/search/extra'; - $data = array( - 'queryInfo' => $queryInfo, - ); - - return $this->apiRequest($method, $data); - } - - public function itemGetItemsByCodes($values = []) - { - $method = 'api/commodity/search/bycodes'; - return $this->apiRequest($method, $values); - } - //================================================================================================ - public function itemSave($item) - { - $method = 'api/commodity/mod/0'; - return $this->apiRequest($method, $item); - } - //================================================================================================ - public function itemBatchSave($items) - { - $method = 'api/commodity/group/mod'; - $data = array( - 'items' => $items, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function itemDelete($code) - { - $method = 'item/delete'; - $data = array( - 'code' => $code, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function itemGetQuantity($warehouseCode, $codes) - { - $method = 'item/GetQuantity'; - $data = array( - 'warehouseCode' => $warehouseCode, - 'codes' => $codes, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - //Invoice functions - public function invoiceGet($number, $type = 0) - { - $method = 'invoice/get'; - $data = array( - 'number' => $number, - 'type' => $type, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function invoiceGetById($id) - { - $method = 'invoice/getById'; - $data = array( - 'id' => $id, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function invoiceGetByIdList($idList) - { - $method = 'invoice/getById'; - $data = array( - 'idList' => $idList, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function invoiceGetInvoices($queryinfo, $type = 0) - { - $method = 'invoice/getinvoices'; - $data = array( - 'type' => $type, - 'queryInfo' => $queryinfo, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function invoiceSave($invoice, $GUID = '') - { - $method = 'invoice/save'; - $data = array( - 'invoice' => $invoice, - ); - if ($GUID != '') - $data['requestUniqueId'] = $GUID; - $this->saveStatistics(); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function invoiceDelete($number, $type = 0) - { - $method = 'invoice/delete'; - $data = array( - 'code' => $number, - 'type' => $type, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function invoiceSavePayment($number, $financialData, $accountPath, $date, $amount, $transactionNumber = null, $description = null, $transactionFee = 0) - { - $method = 'invoice/savepayment'; - $data = array( - 'number' => (int) $number, - 'date' => $date, - 'amount' => $amount, - 'transactionNumber' => $transactionNumber, - 'description' => $description, - 'transactionFee' => $transactionFee, - ); - - $data = array_merge($data, $financialData); - if ($accountPath != []) - $data = array_merge($data, $accountPath); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function invoiceGetOnlineInvoiceURL($number, $type = 0) - { - $method = 'invoice/getonlineinvoiceurl'; - $data = array( - 'number' => $number, - 'type' => $type, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function itemUpdateOpeningQuantity($items) - { - $method = 'item/UpdateOpeningQuantity'; - $data = array( - 'items' => $items, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function saveWarehouseReceipt($receipt) - { - $method = 'invoice/SaveWarehouseReceipt'; - $data = array( - 'deleteOldReceipts' => true, - 'receipt' => $receipt, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function warehouseReceiptGetByIdList($idList) - { - $method = 'invoice/getWarehouseReceipt'; - $data = array( - 'idList' => $idList, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function getWarehouseReceipt($objectId) - { - $method = 'warehouse/GetById'; - $data = array( - 'id' => $objectId, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - //Settings functions - public function settingSetChangeHook($url, $hookPassword) - { - $method = 'hooks/setting/SetChangeHook'; - $data = array( - 'url' => $url, - 'hookPassword' => $hookPassword, - ); - - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function settingGetChanges($start = 0) - { - $method = 'hooks/setting/GetChanges'; - $data = array( - 'start' => $start, - ); - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function settingGetAccounts() - { - $method = 'hooks/setting/GetAccounts'; - return $this->apiRequest($method); - } - //================================================================================================ - public function settingGetBanks() - { - $method = 'hooks/setting/getBanks'; - return $this->apiRequest($method); - } - //================================================================================================ - public function settingGetCashes() - { - $method = 'setting/GetCashes'; - return $this->apiRequest($method); - } - //================================================================================================ - public function settingGetProjects() - { - $method = 'api/projects/list'; - return $this->apiRequest($method); - } - //================================================================================================ - public function settingGetSalesmen() - { - $method = 'api/person/list/salesmen'; - return $this->apiRequest($method); - } - //================================================================================================ - public function settingGetCurrency() - { - $method = 'hooks/setting/getCurrency'; - - return $this->apiRequest($method); - } - //================================================================================================ - public function settingGetFiscalYear() - { - $method = 'hooks/setting/GetFiscalYear'; - - return $this->apiRequest($method); - } - //================================================================================================ - public function settingGetWarehouses() - { - $method = 'api/storeroom/list'; - return $this->apiRequest($method); - } - //================================================================================================ - public function fixClearTags() - { - $method = 'fix/clearTag'; - return $this->apiRequest($method); - } - //================================================================================================ - public function settingGetSubscriptionInfo() - { - $method = 'hooks/setting/getBusinessInfo'; - return $this->apiRequest($method); - } - //========================================================================================================================= - public function getLastChangeId($start = 1000000000) - { - $method = 'setting/GetChanges'; - $data = array( - 'start' => $start, - ); - return $this->apiRequest($method, $data); - } - //================================================================================================ - public function saveStatistics() - { - $plugin_version = constant('SSBHESABIX_VERSION'); - - $endpoint = "https://hesabix.ir/statistics/save"; - $body = array( - "Platform" => "Woocommerce/" . $plugin_version, - "Website" => get_site_url(), - 'APIKEY' => get_option('ssbhesabix_account_api'), - "IP" => $_SERVER['REMOTE_ADDR'] - ); - - $options = array( - 'body' => wp_json_encode($body), - 'headers' => array( - 'Content-Type' => 'application/json', - ), - 'timeout' => 60, - 'redirection' => 5, - 'blocking' => true, - 'httpversion' => '1.0', - 'sslverify' => false, - 'data_format' => 'body', - ); - - $wp_remote_post = wp_remote_post($endpoint, $options); - $result = json_decode(wp_remote_retrieve_body($wp_remote_post)); - } - //================================================================================================ - public function checkMobileAndNationalCode($nationalCode, $billingPhone) - { - $method = 'inquiry/checkMobileAndNationalCode'; - $data = array( - 'nationalCode' => $nationalCode, - 'mobile' => $billingPhone, - ); - return $this->apiRequest($method, $data); - } - //================================================================================================ + get_option('hesabix_account_api'), + 'reqType' => 'woocommercePlugin', + ), $data); + + + if (get_option('hesabix_debug_mode') == 'yes') { + HesabixLogService::log(array("Debug Mode - Data: " . print_r($data, true))); + } + + $options = array( + 'body' => wp_json_encode($body), + 'headers' => array( + 'Content-Type' => 'application/json', + 'API-KEY' => get_option('hesabix_account_api'), + 'activeBid' => get_option('hesabix_account_bid'), + 'activeYear' => get_option('hesabix_account_year'), + ), + 'timeout' => 15, + 'redirection' => 5, + 'blocking' => true, + 'data_format' => 'body', + ); + + $wp_remote_post = wp_remote_post($endpoint, $options); + if ($method == 'api/commodity/search/extra') { + + } + $result = json_decode(wp_remote_retrieve_body($wp_remote_post)); + + + if (get_option('hesabix_debug_mode') == 'yes') { + HesabixLogService::log(array("Debug Mode - Result: " . print_r($result, true))); + } + + + sleep(1); + + if ($result == null) { + return 'No response from Hesabix'; + } else { + if (!isset($result->Success)) { + switch ($result->ErrorCode) { + case '100': + return 'InternalServerError'; + case '101': + return 'TooManyRequests'; + case '103': + return 'MissingData'; + case '104': + return 'MissingParameter' . '. ErrorMessage: ' . $result->ErrorMessage; + case '105': + return 'ApiDisabled'; + case '106': + return 'UserIsNotOwner'; + case '107': + return 'BusinessNotFound'; + case '108': + return 'BusinessExpired'; + case '110': + return 'IdMustBeZero'; + case '111': + return 'IdMustNotBeZero'; + case '112': + return 'ObjectNotFound' . '. ErrorMessage: ' . $result->ErrorMessage; + case '113': + return 'MissingApiKey'; + case '114': + return 'ParameterIsOutOfRange' . '. ErrorMessage: ' . $result->ErrorMessage; + case '190': + return 'ApplicationError' . '. ErrorMessage: ' . $result->ErrorMessage; + } + } else { + return $result; + } + } + return false; + } + + + public function contactGet($code) + { + $method = 'contact/get'; + $data = array( + 'code' => $code, + ); + + return $this->apiRequest($method, $data); + } + + public function contactGetById($idList) + { + $method = 'contact/getById'; + $data = array( + 'idList' => $idList, + ); + + return $this->apiRequest($method, $data); + } + + public function contactGetContacts($queryInfo) + { + $method = 'contact/getcontacts'; + $data = array( + 'queryInfo' => $queryInfo, + ); + + return $this->apiRequest($method, $data); + } + + public function contactSave($contact) + { + $method = 'hooks/modify/person'; + return $this->apiRequest($method, $contact); + } + + public function contactBatchSave($contacts) + { + $method = 'api/person/group/mod'; + $data = array( + 'items' => $contacts, + ); + + return $this->apiRequest($method, $data); + } + + public function contactDelete($code) + { + $method = 'contact/delete'; + $data = array( + 'code' => $code, + ); + + return $this->apiRequest($method, $data); + } + + public function contactGetByPhoneOrEmail($phone, $email) + { + $method = 'contact/findByPhoneOrEmail'; + $data = array( + 'mobile' => $phone, + 'email' => $email, + 'phone' => $phone, + ); + + return $this->apiRequest($method, $data); + } + + + public function itemGet($code) + { + $method = 'item/get'; + $data = array( + 'code' => $code, + ); + + return $this->apiRequest($method, $data); + } + + public function itemGetByBarcode($barcode) + { + $method = 'item/getByBarcode'; + $data = array( + 'barcode' => $barcode, + ); + + return $this->apiRequest($method, $data); + } + + public function itemGetById($idList) + { + $method = 'item/getById'; + $data = array( + 'idList' => $idList, + ); + + return $this->apiRequest($method, $data); + } + + public function itemGetItems($queryInfo = null) + { + $method = 'api/commodity/search/extra'; + $data = array( + 'queryInfo' => $queryInfo, + ); + + return $this->apiRequest($method, $data); + } + + public function itemGetItemsByCodes($values = []) + { + $method = 'api/commodity/search/bycodes'; + return $this->apiRequest($method, $values); + } + + public function itemSave($item) + { + $method = 'api/commodity/mod'; + return $this->apiRequest($method, $item); + } + + public function itemBatchSave($items) + { + $method = 'api/commodity/group/mod'; + $data = array( + 'items' => $items, + ); + + return $this->apiRequest($method, $data); + } + + public function itemDelete($code) + { + $method = 'item/delete'; + $data = array( + 'code' => $code, + ); + + return $this->apiRequest($method, $data); + } + + public function itemGetQuantity($warehouseCode, $codes) + { + $method = 'item/GetQuantity'; + $data = array( + 'warehouseCode' => $warehouseCode, + 'codes' => $codes, + ); + + return $this->apiRequest($method, $data); + } + + + public function invoiceGet($number, $type = 0) + { + $method = 'invoice/get'; + $data = array( + 'number' => $number, + 'type' => $type, + ); + + return $this->apiRequest($method, $data); + } + + public function invoiceGetById($id) + { + $method = 'invoice/getById'; + $data = array( + 'id' => $id, + ); + + return $this->apiRequest($method, $data); + } + + public function invoiceGetByIdList($idList) + { + $method = 'invoice/getById'; + $data = array( + 'idList' => $idList, + ); + + return $this->apiRequest($method, $data); + } + + public function invoiceGetInvoices($queryinfo, $type = 0) + { + $method = 'invoice/getinvoices'; + $data = array( + 'type' => $type, + 'queryInfo' => $queryinfo, + ); + + return $this->apiRequest($method, $data); + } + + public function invoiceSave($invoice) + { + $method = 'api/sell/v2/mod'; + $this->saveStatistics(); + + return $this->apiRequest($method, $invoice); + } + + public function invoiceDelete($number, $type = 0) + { + $method = 'invoice/delete'; + $data = array( + 'code' => $number, + 'type' => $type, + ); + + return $this->apiRequest($method, $data); + } + + public function invoiceSavePayment($number, $financialData, $accountPath, $date, $amount, $transactionNumber = null, $description = null, $transactionFee = 0) + { + $method = 'invoice/savepayment'; + $data = array( + 'number' => (int) $number, + 'date' => $date, + 'amount' => $amount, + 'transactionNumber' => $transactionNumber, + 'description' => $description, + 'transactionFee' => $transactionFee, + ); + + $data = array_merge($data, $financialData); + if ($accountPath != []) + $data = array_merge($data, $accountPath); + + return $this->apiRequest($method, $data); + } + + public function invoiceGetOnlineInvoiceURL($number, $type = 0) + { + $method = 'invoice/getonlineinvoiceurl'; + $data = array( + 'number' => $number, + 'type' => $type, + ); + + return $this->apiRequest($method, $data); + } + + public function itemUpdateOpeningQuantity($items) + { + $method = 'item/UpdateOpeningQuantity'; + $data = array( + 'items' => $items, + ); + + return $this->apiRequest($method, $data); + } + + public function saveWarehouseReceipt($receipt) + { + $method = 'invoice/SaveWarehouseReceipt'; + $data = array( + 'deleteOldReceipts' => true, + 'receipt' => $receipt, + ); + + return $this->apiRequest($method, $data); + } + + public function warehouseReceiptGetByIdList($idList) + { + $method = 'invoice/getWarehouseReceipt'; + $data = array( + 'idList' => $idList, + ); + + return $this->apiRequest($method, $data); + } + + public function getWarehouseReceipt($objectId) + { + $method = 'warehouse/GetById'; + $data = array( + 'id' => $objectId, + ); + + return $this->apiRequest($method, $data); + } + + + public function settingSetChangeHook($url, $hookPassword) + { + $method = 'hooks/setting/SetChangeHook'; + $data = array( + 'url' => $url, + 'hookPassword' => $hookPassword, + ); + + return $this->apiRequest($method, $data); + } + + public function settingGetChanges($start = 0) + { + $method = 'hooks/setting/GetChanges'; + $data = array( + 'start' => $start, + ); + return $this->apiRequest($method, $data); + } + + public function settingGetAccounts() + { + $method = 'hooks/setting/GetAccounts'; + return $this->apiRequest($method); + } + + public function settingGetBanks() + { + $method = 'hooks/setting/getBanks'; + return $this->apiRequest($method); + } + + public function settingGetCashes() + { + $method = 'setting/GetCashes'; + return $this->apiRequest($method); + } + + public function settingGetProjects() + { + $method = 'api/projects/list'; + return $this->apiRequest($method); + } + + public function settingGetSalesmen() + { + $method = 'api/person/list/salesmen'; + return $this->apiRequest($method); + } + + public function settingGetCurrency() + { + $method = 'hooks/setting/getCurrency'; + + return $this->apiRequest($method); + } + + public function settingGetFiscalYear() + { + $method = 'hooks/setting/GetFiscalYear'; + + return $this->apiRequest($method); + } + + public function settingGetWarehouses() + { + $method = 'api/storeroom/list'; + return $this->apiRequest($method); + } + + public function fixClearTags() + { + $method = 'fix/clearTag'; + return $this->apiRequest($method); + } + + public function settingGetSubscriptionInfo() + { + $method = 'hooks/setting/getBusinessInfo'; + return $this->apiRequest($method); + } + + public function getLastChangeId($start = 1000000000) + { + $method = 'setting/GetChanges'; + $data = array( + 'start' => $start, + ); + return $this->apiRequest($method, $data); + } + + public function saveStatistics() + { + $plugin_version = constant('HESABIX_VERSION'); + + $endpoint = "https://app.hesabix.ir/statistics/save"; + + $apiAddress = get_option('hesabix_api_address', 0); + + if ($apiAddress == 1) + $endpoint = 'https://next.hesabix.ir/statistics/save'; + if ($apiAddress == 2) + $endpoint = 'https://hesabix.dragonizzer.ir/statistics/save'; + if ($apiAddress == 'custom') { + $customAddress = get_option('hesabix_custom_api_address', ''); + if (!empty($customAddress)) { + + $customAddress = rtrim($customAddress, '/'); + $endpoint = $customAddress . '/statistics/save'; + } + } + + $body = array( + "Platform" => "Woocommerce/" . $plugin_version, + "Website" => get_site_url(), + 'APIKEY' => get_option('hesabix_account_api'), + "IP" => $_SERVER['REMOTE_ADDR'] + ); + + $options = array( + 'body' => wp_json_encode($body), + 'headers' => array( + 'Content-Type' => 'application/json', + ), + 'timeout' => 60, + 'redirection' => 5, + 'blocking' => true, + 'httpversion' => '1.0', + 'sslverify' => false, + 'data_format' => 'body', + ); + + $wp_remote_post = wp_remote_post($endpoint, $options); + $result = json_decode(wp_remote_retrieve_body($wp_remote_post)); + } + + public function checkMobileAndNationalCode($nationalCode, $billingPhone) + { + $method = 'inquiry/checkMobileAndNationalCode'; + $data = array( + 'nationalCode' => $nationalCode, + 'mobile' => $billingPhone, + ); + return $this->apiRequest($method, $data); + } + } \ No newline at end of file diff --git a/includes/class-hesabix-deactivator.php b/includes/class-hesabix-deactivator.php new file mode 100644 index 0000000..e3afd78 --- /dev/null +++ b/includes/class-hesabix-deactivator.php @@ -0,0 +1,16 @@ +actions = array(); + $this->filters = array(); + + } + + public function add_action($hook, $component, $callback, $priority = 10, $accepted_args = 1) + { + $this->actions = $this->add($this->actions, $hook, $component, $callback, $priority, $accepted_args); + } + + public function add_filter($hook, $component, $callback, $priority = 10, $accepted_args = 1) + { + $this->filters = $this->add($this->filters, $hook, $component, $callback, $priority, $accepted_args); + } + + private function add($hooks, $hook, $component, $callback, $priority, $accepted_args) + { + + $hooks[] = array( + 'hook' => $hook, + 'component' => $component, + 'callback' => $callback, + 'priority' => $priority, + 'accepted_args' => $accepted_args + ); + + return $hooks; + + } + + public function run() + { + + foreach ($this->filters as $hook) { + add_filter($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args']); + } + + foreach ($this->actions as $hook) { + add_action($hook['hook'], array($hook['component'], $hook['callback']), $hook['priority'], $hook['accepted_args']); + } + + } + +} diff --git a/includes/class-hesabix-validation.php b/includes/class-hesabix-validation.php new file mode 100644 index 0000000..0a9b060 --- /dev/null +++ b/includes/class-hesabix-validation.php @@ -0,0 +1,406 @@ += 0 && $salesTax <= 100) { + return $salesTax; + } else { + return 0; + } + } + + public static function itemSalesInfoValidation($salesInfo) + { + return mb_substr($salesInfo, 0, 99); + } + + public static function itemPurchaseCostValidation($purchaseCost) + { + if ($purchaseCost >= 0) { + return $purchaseCost; + } else { + return 0; + } + } + + public static function itemPurchaseInfoValidation($purchaseInfo) + { + return mb_substr($purchaseInfo, 0, 99); + } + + public static function itemTagValidation($tag) + { + return mb_substr($tag, 0, 254); + } + + public static function contactCodeValidation($code) + { + $code = preg_replace('/[^0-9]/', '', $code); + return mb_substr($code, 0, 5); + } + + public static function contactDisplayNameValidation($displayName) + { + return mb_substr($displayName, 0, 99); + } + + public static function contactCompanyValidation($company) + { + return mb_substr($company, 0, 99); + } + + public static function contactTitleValidation($title) + { + return mb_substr($title, 0, 49); + } + + public static function contactFirstNameValidation($firstName) + { + return mb_substr($firstName, 0, 49); + } + + public static function contactLastNameValidation($lastName) + { + return mb_substr($lastName, 0, 49); + } + + public static function contactAddressValidation($address) + { + return mb_substr($address, 0, 149); + } + + public static function contactCountryValidation($country) + { + return mb_substr($country, 0, 49); + } + + public static function contactStateValidation($state) + { + if (is_numeric($state)) { + if (is_plugin_active("persian-woocommerce-shipping/woocommerce-shipping.php")) { + $state = PWS()::get_state($state); + } + } + return mb_substr($state, 0, 49); + } + + public static function contactCityValidation($city) + { + if (is_numeric($city)) { + if (is_plugin_active("persian-woocommerce-shipping/woocommerce-shipping.php")) { + $city = PWS()::get_city($city); + } + } + return mb_substr($city, 0, 49); + } + + public static function contactPostalCodeValidation($postalCode) + { + $postalCode = preg_replace('/[^0-9]/', '', $postalCode); + $postalCode = self::formatFarsiNumbers($postalCode); + return mb_substr($postalCode, 0, 10); + } + + public static function contactPhoneValidation($phone) + { + $phone = preg_replace('/[^0-9]/', '', $phone); + $phone = self::formatFarsiNumbers($phone); + return mb_substr($phone, 0, 14); + } + + public static function contactMobileValidation($mobile) + { + $mobile = preg_replace('/[^0-9]/', '', $mobile); + return mb_substr($mobile, 0, 14); + } + + public static function contactFaxValidation($fax) + { + $fax = preg_replace('/[^0-9]/', '', $fax); + return mb_substr($fax, 0, 14); + } + + public static function contactEmailValidation($email) + { + $isValid = true; + $atIndex = strrpos($email, "@"); + if (is_bool($atIndex) && !$atIndex) { + $isValid = false; + } else { + $domain = substr($email, $atIndex + 1); + $local = substr($email, 0, $atIndex); + $localLen = strlen($local); + $domainLen = strlen($domain); + if ($localLen < 1 || $localLen > 64) { + + $isValid = false; + } else if ($domainLen < 1 || $domainLen > 255) { + + $isValid = false; + } else if ($local[0] == '.' || $local[$localLen - 1] == '.') { + + $isValid = false; + } else if (preg_match('/\\.\\./', $local)) { + + $isValid = false; + } else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) { + + $isValid = false; + } else if (preg_match('/\\.\\./', $domain)) { + + $isValid = false; + } else if + ( + !preg_match( + '/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', + str_replace("\\\\", "", $local) + ) + ) { + + + if ( + !preg_match( + '/^"(\\\\"|[^"])+"$/', + str_replace("\\\\", "", $local) + ) + ) { + $isValid = false; + } + } + } + + if ($isValid) { + return $email; + } else { + return null; + } + } + + public static function contactWebsiteValidation($website) + { + return mb_substr($website, 0, 119); + } + + public static function contactNoteValidation($note) + { + return mb_substr($note, 0, 499); + } + + public static function contactCategoryValidation($category) + { + return $category; + } + + public static function contactTagValidation($tag) + { + return mb_substr($tag, 0, 254); + } + + public static function invoiceFinancialYearValidation($financialYear) + { + return $financialYear; + } + + public static function invoiceCurrencyRateValidation($currencyRate) + { + if ($currencyRate > 0) { + return $currencyRate; + } else { + return 1; + } + } + + public static function invoiceNumberValidation($number) + { + return mb_substr($number, 0, 49); + } + + public static function invoiceContactTitleValidation($contactTitle) + { + return mb_substr($contactTitle, 0, 199); + } + + public static function invoiceDueDateValidation($dueDate) + { + return $dueDate; + } + + public static function invoiceNoteValidation($note) + { + return mb_substr($note, 0, 499); + } + + public static function invoiceReferenceValidation($reference) + { + return mb_substr($reference, 0, 49); + } + + public static function invoiceTagValidation($tag) + { + return mb_substr($tag, 0, 254); + } + + public function invoiceItemsValidation($items) + { + return $items; + } + + public static function invoiceItemDescriptionValidation($description) + { + return self::remove_emoji($description, 249); + } + + public static function invoiceItemQuantityValidation($quantity) + { + if ($quantity > 0) { + return $quantity; + } else { + return 1; + } + } + + public static function invoiceItemUnitValidation($unit) + { + return mb_substr($unit, 0, 29); + } + + public static function invoiceItemUnitPriceValidation($unitPrice) + { + if ($unitPrice >= 0) { + return $unitPrice; + } else { + return 0; + } + } + + public static function invoiceItemAmountValidation($amount) + { + if ($amount >= 0) { + return $amount; + } else { + return 0; + } + } + + public static function invoiceItemDiscountValidation($discount) + { + if ($discount >= 0) { + return $discount; + } else { + return 0; + } + } + + public static function invoiceItemTaxValidation($tax) + { + if ($tax >= 0) { + return $tax; + } else { + return 0; + } + } + + public static function invoiceItemTotalAmountValidation($totalAmount) + { + if ($totalAmount >= 0) { + return $totalAmount; + } else { + return 0; + } + } + + public static function remove_emoji($string, $length = 200): string + { + $regex_alphanumeric = '/[\x{1F100}-\x{1F1FF}]/u'; + $clear_string = preg_replace($regex_alphanumeric, '', $string); + + $regex_symbols = '/[\x{1F300}-\x{1F5FF}]/u'; + $clear_string = preg_replace($regex_symbols, '', $clear_string); + + $regex_emoticons = '/[\x{1F600}-\x{1F64F}]/u'; + $clear_string = preg_replace($regex_emoticons, '', $clear_string); + + $regex_transport = '/[\x{1F680}-\x{1F6FF}]/u'; + $clear_string = preg_replace($regex_transport, '', $clear_string); + + $regex_supplemental = '/[\x{1F900}-\x{1F9FF}]/u'; + $clear_string = preg_replace($regex_supplemental, '', $clear_string); + + $regex_misc = '/[\x{2600}-\x{26FF}\x{1F7E9}-\x{1F7EF}]/u'; + $clear_string = preg_replace($regex_misc, '', $clear_string); + + $regex_dingbats = '/[\x{2700}-\x{27BF}]/u'; + $clear_string = preg_replace($regex_dingbats, '', $clear_string); + + $truncated_string = mb_substr($clear_string, 0, $length); + + return $truncated_string; + } + +} diff --git a/includes/class-ssbhesabix-webhook.php b/includes/class-hesabix-webhook.php similarity index 62% rename from includes/class-ssbhesabix-webhook.php rename to includes/class-hesabix-webhook.php index 0dce617..bb35d2e 100644 --- a/includes/class-ssbhesabix-webhook.php +++ b/includes/class-hesabix-webhook.php @@ -1,352 +1,358 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - * @author Babak Alizadeh - */ - -class Ssbhesabix_Webhook -{ - public $invoicesObjectId = array(); - public $invoiceItemsCode = array(); - public $itemsObjectId = array(); - public $contactsObjectId = array(); - public $warehouseReceiptsObjectId = array(); - - public function __construct() - { - //hesabixLogService::writeLogStr("Calling Webhook"); - $wpFaService = new HesabixWpFaService(); - - $hesabixApi = new Ssbhesabix_Api(); - - $lastChange = get_option('ssbhesabix_last_log_check_id'); - $changes = $hesabixApi->settingGetChanges($lastChange + 1); - - if ($changes->Success) { - update_option('ssbhesabix_business_expired', 0); - - foreach ($changes->Result as $item) { - if (!$item->API) { - switch ($item->ObjectType) { - case 'Invoice': - if ($item->Action == 123) { - $wpFa1 = $wpFaService->getWpFaByHesabixId('order', $item->Extra2); - if($wpFa1) { - $wpFaService->delete($wpFa1); - HesabixLogService::writeLogStr("The invoice link with the order deleted. Invoice number: " . $item->Extra2 . ", Order id: " . $wpFa1->idWp); - } - } - $this->invoicesObjectId[] = $item->ObjectId; - foreach (explode(',', $item->Extra) as $invoiceItem) { - if ($invoiceItem != '') { - $this->invoiceItemsCode[] = $invoiceItem; - } - } - break; - case 'WarehouseReceipt': - if ($item->Action == 261) { - global $wpdb; - $hesabixApi = new Ssbhesabix_Api(); - $receipt = $hesabixApi->getWarehouseReceipt($item->ObjectId); -// HesabixLogService::writeLogObj($receipt->Result->Items); - foreach ($receipt->Result->Items as $receiptItem) { - $wpFa = $wpFaService->getWpFaByHesabixId('product', $receiptItem->ItemCode); - $wpdb->insert($wpdb->prefix . 'ssbhesabix', array( - 'id_hesabix' => (int)$item->ObjectId, - 'obj_type' => "receiptItems", - 'id_ps' => $wpFa->idWp, - 'id_ps_attribute' => $wpFa->idWpAttribute - )); - } - - if (get_option('ssbhesabix_item_update_quantity', 'no') == 'no') { - HesabixLogService::writeLogStr("Sync Products Quantity is Off"); - } - } - if ($item->Action == 263) { - global $wpdb; - $rows = $wpdb->get_results("SELECT * FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id_hesabix` = $item->ObjectId"); - $receiptID = $item->ObjectId; - foreach ($rows as $row) { - $post_id = ($row->id_ps_attribute && $row->id_ps_attribute > 0) ? $row->id_ps_attribute : $row->id_ps; - //$product = wc_get_product( $post_id ); - - if (get_option('ssbhesabix_item_update_quantity', 'no') == 'no') { - HesabixLogService::writeLogStr("Sync Products Quantity is Off"); - } - - $productId = $row->id_ps; - $attributeId = $row->id_ps_attribute; - - if (get_option('ssbhesabix_item_update_quantity', 'no') == 'yes') - update_post_meta($attributeId, '_manage_stock', 'yes'); - - if ($productId == $attributeId) $attributeId = 0; - $result = array(); - - $wpFaService = new HesabixWpFaService(); - $wpFa = $wpFaService->getWpFa('product', $productId, $attributeId); - if ($wpFa) { - - $api = new Ssbhesabix_Api(); - $warehouse = get_option('ssbhesabix_item_update_quantity_based_on', "-1"); - if ($warehouse == "-1") - $response = $api->itemGet($wpFa->idHesabix); - else { - $response = $api->itemGetQuantity($warehouse, array($wpFa->idHesabix)); - } - - if ($response->Success) { - $item = $warehouse == "-1" ? $response->Result : $response->Result[0]; - $newProps = Ssbhesabix_Admin_Functions::setItemChanges($item); - } else { - HesabixLogService::writeLogStr("Product is not defined in Hesabix"); - } - } - } - - $wpdb->delete($wpdb->prefix . 'ssbhesabix', array('id_hesabix' => $receiptID)); - break; - } - $this->warehouseReceiptsObjectId[] = $item->ObjectId; - break; - case 'Product': - if ($item->Action == 53) { - $wpFa = $wpFaService->getWpFaByHesabixId('product', $item->Extra); - if ($wpFa) { - global $wpdb; - $wpdb->delete($wpdb->prefix . 'ssbhesabix', array('id' => $wpFa->id)); - } - break; - } - - $this->itemsObjectId[] = $item->ObjectId; - break; - case 'Contact': - if ($item->Action == 33) { - $id_obj = $wpFaService->getWpFaIdByHesabixId('customer', $item->Extra); - global $wpdb; - $wpdb->delete($wpdb->prefix . 'ssbhesabix', array('id' => $id_obj)); - break; - } - - $this->contactsObjectId[] = $item->ObjectId; - break; - } - } - } - - $this->invoiceItemsCode = array_unique($this->invoiceItemsCode); - $this->contactsObjectId = array_unique($this->contactsObjectId); - $this->itemsObjectId = array_unique($this->itemsObjectId); - $this->invoicesObjectId = array_unique($this->invoicesObjectId); - - $this->setChanges(); - - $lastChange = end($changes->Result); - if (is_object($lastChange)) - update_option('ssbhesabix_last_log_check_id', $lastChange->Id); - else if ($changes->LastId) - update_option('ssbhesabix_last_log_check_id', $changes->LastId); - - } else { - HesabixLogService::log(array("ssbhesabix - Cannot check last changes. Error Message: " . (string)$changes->ErrorMessage . ". Error Code: " . (string)$changes->ErrorCode)); - if ($changes->ErrorCode == 108) { - update_option('ssbhesabix_business_expired', 1); - add_action('admin_notices', array(__CLASS__, 'ssbhesabix_business_expired_notice')); - } - return false; - } - - return true; - } -//================================================================================================================================= - public function ssbhesabix_business_expired_notice() - { - echo '

' . __('Cannot connect to Hesabix. Business expired.', 'ssbhesabix') . '

'; - } -//================================================================================================================================= - public function setChanges() - { - //Items - $items = array(); - - if (!empty($this->warehouseReceiptsObjectId)) { - $receipts = $this->getObjectsByIdList($this->warehouseReceiptsObjectId, 'WarehouseReceipt'); - if ($receipts != false) { - foreach ($receipts as $receipt) { - foreach ($receipt->Items as $item) - array_push($this->invoiceItemsCode, $item->ItemCode); - } - } - } - - if (!empty($this->itemsObjectId)) { - $objects = $this->getObjectsByIdList($this->itemsObjectId, 'item'); - if ($objects != false) { - foreach ($objects as $object) { - array_push($items, $object); - } - } - } - - if (!empty($this->invoiceItemsCode)) { - $objects = $this->getObjectsByCodeList($this->invoiceItemsCode); - - if ($objects != false) { - foreach ($objects as $object) { - array_push($items, $object); - } - } - } - - if (!empty($items)) { - update_option("ssbhesabix_inside_product_edit", 1); - try { - foreach ($items as $item) { - Ssbhesabix_Admin_Functions::setItemChanges($item); - } - } catch (Exception $e) { - } finally { - update_option("ssbhesabix_inside_product_edit", 0); - } - } - - return true; - } -//================================================================================================================================= - public function setInvoiceChanges($invoice) - { - if (!is_object($invoice)) return false; - - $wpFaService = new HesabixWpFaService(); - - $number = $invoice->Number; - $json = json_decode($invoice->Tag); - if (is_object($json)) { - $id_order = $json->id_order; - } else { - $id_order = 0; - } - - if ($invoice->InvoiceType == 0) { - if ($id_order == 0) { - HesabixLogService::log(array("This invoice is not defined in OnlineStore. Invoice Number: " . $number)); - } else { - //check if order exist in wooCommerce - $id_obj = $wpFaService->getWpFaId('order', $id_order); - if ($id_obj != false) { - global $wpdb; - $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id` = $id_obj"); - if (is_object($row) && $row->id_hesabix != $number) { - $id_hesabix_old = $row->id_hesabix; - //ToDo: number must be int in hesabix - $wpdb->update($wpdb->prefix . 'ssbhesabix', array('id_hesabix' => $number), array('id' => $id_obj)); - HesabixLogService::log(array("Invoice Number changed. Old Number: $id_hesabix_old. New ID: $number")); - } - } - } - } - } -//================================================================================================================================= - public function setContactChanges($contact) - { - if (!is_object($contact)) return false; - - $code = $contact->Code; - - $json = json_decode($contact->Tag); - if (is_object($json)) { - $id_customer = $json->id_customer; - } else { - $id_customer = 0; - } - - if ($id_customer == 0) { - HesabixLogService::log(array("This Customer is not define in OnlineStore. Customer code: $code")); - return false; - } - - $wpFaService = new HesabixWpFaService(); - $id_obj = $wpFaService->getWpFaId('customer', $id_customer); - - if ($id_obj != false) { - global $wpdb; - $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "ssbhesabix` WHERE `id` = $id_obj"); - - if (is_object($row) && $row->id_hesabix != $code) { - $id_hesabix_old = $row->id_hesabix; - $wpdb->update($wpdb->prefix . 'ssbhesabix', array('id_hesabix' => (int)$code), array('id' => $id_obj)); - - HesabixLogService::log(array("Contact Code changed. Old ID: $id_hesabix_old. New ID: $code")); - } - } - - return true; - } -//================================================================================================================================= - public function getObjectsByIdList($idList, $type) - { - $hesabixApi = new Ssbhesabix_Api(); - $warehouseCode = get_option('ssbhesabix_item_update_quantity_based_on'); - switch ($type) { - case 'item': - if($warehouseCode == '-1') { - $result = $hesabixApi->itemGetById($idList); - } else { - $items = $hesabixApi->itemGetById($idList); - $codeList = []; - foreach ($items->Result as $item) { - array_push($codeList, $item->Code); - } - $result = $hesabixApi->itemGetQuantity($warehouseCode, $codeList); - } - break; - case 'contact': - $result = $hesabixApi->contactGetById($idList); - break; - case 'invoice': - $result = $hesabixApi->invoiceGetInvoices(array("Filters" => array("Property" => "Id", "Operator" => "in", "Value" => $idList))); - break; - case 'WarehouseReceipt': - $result = $hesabixApi->warehouseReceiptGetByIdList($idList); - break; - default: - return false; - } - - if (is_object($result) && $result->Success) { - return $result->Result; - } - - return false; - } -//================================================================================================================================= - public function getObjectsByCodeList($codeList) - { - $hesabixApi = new Ssbhesabix_Api(); - - $warehouse = get_option('ssbhesabix_item_update_quantity_based_on', "-1"); - if ($warehouse == "-1") - $result = $hesabixApi->itemGetItemsByCodes($codeList); - else { - $result = $hesabixApi->itemGetQuantity($warehouse, $codeList); - } - - //$result = $hesabixApi->itemGetItems($queryInfo); - - if (is_object($result) && $result->Success) { - return $warehouse == "-1" ? $result->Result->List : $result->Result; - } - - return false; - } -} +settingGetChanges($lastChange + 1); + + if ($changes->Success) { + update_option('hesabix_business_expired', 0); + + foreach ($changes->Result as $item) { + if (!$item->API) { + switch ($item->ObjectType) { + case 'Invoice': + if ($item->Action == 123) { + $wpFa1 = $wpFaService->getWpFaByHesabixId('order', $item->Extra2); + if ($wpFa1) { + $wpFaService->delete($wpFa1); + HesabixLogService::writeLogStr("The invoice link with the order deleted. Invoice number: " . $item->Extra2 . ", Order id: " . $wpFa1->idWp); + } + } + $this->invoicesObjectId[] = $item->ObjectId; + foreach (explode(',', $item->Extra) as $invoiceItem) { + if ($invoiceItem != '') { + $this->invoiceItemsCode[] = $invoiceItem; + } + } + break; + case 'WarehouseReceipt': + if ($item->Action == 261) { + global $wpdb; + $hesabixApi = new Hesabix_Api(); + $receipt = $hesabixApi->getWarehouseReceipt($item->ObjectId); + + foreach ($receipt->Result->Items as $receiptItem) { + $wpFa = $wpFaService->getWpFaByHesabixId('product', $receiptItem->ItemCode); + $wpdb->insert($wpdb->prefix . 'hesabix', array( + 'id_hesabix' => (int) $item->ObjectId, + 'obj_type' => "receiptItems", + 'id_ps' => $wpFa->idWp, + 'id_ps_attribute' => $wpFa->idWpAttribute + )); + } + + if (get_option('hesabix_item_update_quantity', 'no') == 'no') { + HesabixLogService::writeLogStr("Sync Products Quantity is Off"); + } + } + if ($item->Action == 263) { + global $wpdb; + $rows = $wpdb->get_results("SELECT * FROM `" . $wpdb->prefix . "hesabix` WHERE `id_hesabix` = $item->ObjectId"); + $receiptID = $item->ObjectId; + foreach ($rows as $row) { + $post_id = ($row->id_ps_attribute && $row->id_ps_attribute > 0) ? $row->id_ps_attribute : $row->id_ps; + + + if (get_option('hesabix_item_update_quantity', 'no') == 'no') { + HesabixLogService::writeLogStr("Sync Products Quantity is Off"); + } + + $productId = $row->id_ps; + $attributeId = $row->id_ps_attribute; + + if (get_option('hesabix_item_update_quantity', 'no') == 'yes') + update_post_meta($attributeId, '_manage_stock', 'yes'); + + if ($productId == $attributeId) + $attributeId = 0; + $result = array(); + + $wpFaService = new HesabixWpFaService(); + $wpFa = $wpFaService->getWpFa('product', $productId, $attributeId); + if ($wpFa) { + + $api = new Hesabix_Api(); + // $warehouse = get_option('hesabix_item_update_quantity_based_on', "-1"); + // if ($warehouse == "-1") + // $response = $api->itemGet($wpFa->idHesabix); + // else { + // $response = $api->itemGetQuantity($warehouse, array($wpFa->idHesabix)); + // } + + $response = $api->itemGet($wpFa->idHesabix); + if ($response->Success) { + // $item = $warehouse == "-1" ? $response->Result : $response->Result[0]; + $item = $response->Result; + $newProps = Hesabix_Admin_Functions::setItemChanges($item); + } else { + HesabixLogService::writeLogStr("Product is not defined in Hesabix"); + } + } + } + + $wpdb->delete($wpdb->prefix . 'hesabix', array('id_hesabix' => $receiptID)); + break; + } + $this->warehouseReceiptsObjectId[] = $item->ObjectId; + break; + case 'Product': + if ($item->Action == 53) { + $wpFa = $wpFaService->getWpFaByHesabixId('product', $item->Extra); + if ($wpFa) { + global $wpdb; + $wpdb->delete($wpdb->prefix . 'hesabix', array('id' => $wpFa->id)); + } + break; + } + + $this->itemsObjectId[] = $item->ObjectId; + break; + case 'Contact': + if ($item->Action == 33) { + $id_obj = $wpFaService->getWpFaIdByHesabixId('customer', $item->Extra); + global $wpdb; + $wpdb->delete($wpdb->prefix . 'hesabix', array('id' => $id_obj)); + break; + } + + $this->contactsObjectId[] = $item->ObjectId; + break; + } + } + } + + $this->invoiceItemsCode = array_unique($this->invoiceItemsCode); + $this->contactsObjectId = array_unique($this->contactsObjectId); + $this->itemsObjectId = array_unique($this->itemsObjectId); + $this->invoicesObjectId = array_unique($this->invoicesObjectId); + + $this->setChanges(); + + $lastChange = end($changes->Result); + if (is_object($lastChange)) + update_option('hesabix_last_log_check_id', $lastChange->Id); + else if ($changes->LastId) + update_option('hesabix_last_log_check_id', $changes->LastId); + + } else { + HesabixLogService::log(array("hesabix - Cannot check last changes. Error Message: " . (string) $changes->ErrorMessage . ". Error Code: " . (string) $changes->ErrorCode)); + if ($changes->ErrorCode == 108) { + update_option('hesabix_business_expired', 1); + add_action('admin_notices', array(__CLASS__, 'hesabix_business_expired_notice')); + } + return false; + } + + return true; + } + + public function hesabix_business_expired_notice() + { + echo '

' . __('Cannot connect to Hesabix. Business expired.', 'hesabix') . '

'; + } + + public function setChanges() + { + + $items = array(); + + if (!empty($this->warehouseReceiptsObjectId)) { + $receipts = $this->getObjectsByIdList($this->warehouseReceiptsObjectId, 'WarehouseReceipt'); + if ($receipts != false) { + foreach ($receipts as $receipt) { + foreach ($receipt->Items as $item) + array_push($this->invoiceItemsCode, $item->ItemCode); + } + } + } + + if (!empty($this->itemsObjectId)) { + $objects = $this->getObjectsByIdList($this->itemsObjectId, 'item'); + if ($objects != false) { + foreach ($objects as $object) { + array_push($items, $object); + } + } + } + + if (!empty($this->invoiceItemsCode)) { + $objects = $this->getObjectsByCodeList($this->invoiceItemsCode); + + if ($objects != false) { + foreach ($objects as $object) { + array_push($items, $object); + } + } + } + + if (!empty($items)) { + update_option("hesabix_inside_product_edit", 1); + try { + foreach ($items as $item) { + Hesabix_Admin_Functions::setItemChanges($item); + } + } catch (Exception $e) { + } finally { + update_option("hesabix_inside_product_edit", 0); + } + } + + return true; + } + + public function setInvoiceChanges($invoice) + { + if (!is_object($invoice)) + return false; + + $wpFaService = new HesabixWpFaService(); + + $number = $invoice->Number; + $json = json_decode($invoice->Tag); + if (is_object($json)) { + $id_order = $json->id_order; + } else { + $id_order = 0; + } + + if ($invoice->InvoiceType == 0) { + if ($id_order == 0) { + HesabixLogService::log(array("This invoice is not defined in OnlineStore. Invoice Number: " . $number)); + } else { + + $id_obj = $wpFaService->getWpFaId('order', $id_order); + if ($id_obj != false) { + global $wpdb; + $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "hesabix` WHERE `id` = $id_obj"); + if (is_object($row) && $row->id_hesabix != $number) { + $id_hesabix_old = $row->id_hesabix; + + $wpdb->update($wpdb->prefix . 'hesabix', array('id_hesabix' => $number), array('id' => $id_obj)); + HesabixLogService::log(array("Invoice Number changed. Old Number: $id_hesabix_old. New ID: $number")); + } + } + } + } + } + + public function setContactChanges($contact) + { + if (!is_object($contact)) + return false; + + $code = $contact->Code; + + $json = json_decode($contact->Tag); + if (is_object($json)) { + $id_customer = $json->id_customer; + } else { + $id_customer = 0; + } + + if ($id_customer == 0) { + HesabixLogService::log(array("This Customer is not define in OnlineStore. Customer code: $code")); + return false; + } + + $wpFaService = new HesabixWpFaService(); + $id_obj = $wpFaService->getWpFaId('customer', $id_customer); + + if ($id_obj != false) { + global $wpdb; + $row = $wpdb->get_row("SELECT `id_hesabix` FROM `" . $wpdb->prefix . "hesabix` WHERE `id` = $id_obj"); + + if (is_object($row) && $row->id_hesabix != $code) { + $id_hesabix_old = $row->id_hesabix; + $wpdb->update($wpdb->prefix . 'hesabix', array('id_hesabix' => (int) $code), array('id' => $id_obj)); + + HesabixLogService::log(array("Contact Code changed. Old ID: $id_hesabix_old. New ID: $code")); + } + } + + return true; + } + + public function getObjectsByIdList($idList, $type) + { + $hesabixApi = new Hesabix_Api(); + // $warehouseCode = get_option('hesabix_item_update_quantity_based_on'); + switch ($type) { + case 'item': + // if ($warehouseCode == '-1') { + $result = $hesabixApi->itemGetById($idList); + // } else { + // $items = $hesabixApi->itemGetById($idList); + // $codeList = []; + // foreach ($items->Result as $item) { + // array_push($codeList, $item->Code); + // } + // $result = $hesabixApi->itemGetQuantity($warehouseCode, $codeList); + // } + break; + case 'contact': + $result = $hesabixApi->contactGetById($idList); + break; + case 'invoice': + $result = $hesabixApi->invoiceGetInvoices(array("Filters" => array("Property" => "Id", "Operator" => "in", "Value" => $idList))); + break; + case 'WarehouseReceipt': + $result = $hesabixApi->warehouseReceiptGetByIdList($idList); + break; + default: + return false; + } + + if (is_object($result) && $result->Success) { + return $result->Result; + } + + return false; + } + + public function getObjectsByCodeList($codeList) + { + $hesabixApi = new Hesabix_Api(); + + // $warehouse = get_option('hesabix_item_update_quantity_based_on', "-1"); + // if ($warehouse == "-1") + // $result = $hesabixApi->itemGetItemsByCodes($codeList); + // else { + // $result = $hesabixApi->itemGetQuantity($warehouse, $codeList); + // } + + $result = $hesabixApi->itemGetItemsByCodes($codeList); + + + if (is_object($result) && $result->Success) { + // return $warehouse == "-1" ? $result->Result->List : $result->Result; + return $result->Result->List; + } + + return false; + } +} diff --git a/includes/class-hesabix.php b/includes/class-hesabix.php new file mode 100644 index 0000000..4c2b458 --- /dev/null +++ b/includes/class-hesabix.php @@ -0,0 +1,159 @@ +version = HESABIX_VERSION; + } else { + $this->version = '0.0.1'; + } + $this->plugin_name = 'hesabix'; + $this->load_dependencies(); + $this->set_locale(); + $this->define_admin_hooks(); + } + + private function load_dependencies() + { + require_once plugin_dir_path(dirname(__FILE__)) . '/includes/class-hesabix-loader.php'; + require_once plugin_dir_path(dirname(__FILE__)) . '/includes/class-hesabix-i18n.php'; + require_once plugin_dir_path(dirname(__FILE__)) . '/admin/class-hesabix-admin.php'; + require_once plugin_dir_path(dirname(__FILE__)) . '/includes/class-hesabix-api.php'; + $this->loader = new Hesabix_Loader(); + require_once plugin_dir_path(dirname(__FILE__)) . '/includes/class-hesabix-validation.php'; + $this->loader = new Hesabix_Loader(); + + } + + private function set_locale() + { + $plugin_i18n = new Hesabix_i18n(); + $this->loader->add_action('plugins_loaded', $plugin_i18n, 'load_plugin_textdomain'); + } + + private function define_admin_hooks() + { + $plugin_admin = new Hesabix_Admin($this->get_plugin_name(), $this->get_version()); + + $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_styles'); + $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts'); + $this->loader->add_filter('query_vars', $plugin_admin, 'hesabix_query_vars'); + $this->loader->add_action('parse_request', $plugin_admin, 'hesabix_parse_request'); + $this->loader->add_action('wp_ajax_nopriv_handle_webhook_request', $plugin_admin, 'hesabix_parse_request'); + $this->loader->add_action('wp_ajax_handle_webhook_request', $plugin_admin, 'hesabix_parse_request'); + + if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) { + + $this->loader->add_action('init', $plugin_admin, 'hesabix_init_internal'); + + if (get_option('hesabix_live_mode')) { + if (get_option('hesabix_hesabix_default_currency') === 0) { + $this->loader->add_action('admin_notices', $plugin_admin, 'hesabix_currency_notice'); + } + if (get_option('hesabix_show_hesabix_code_in_excel_export', 'no') == 'yes' || get_option('hesabix_show_hesabix_code_in_excel_export', 0) == 1) { + $this->loader->add_filter('woocommerce_product_export_column_names', $plugin_admin, 'admin_product_add_column'); + $this->loader->add_filter('woocommerce_product_export_product_default_columns', $plugin_admin, 'admin_product_add_column'); + $this->loader->add_filter('woocommerce_product_export_rows', $plugin_admin, 'admin_product_export_rows', 10, 2); + } + if (get_option('hesabix_show_product_code_in_products_page') === 'yes' || get_option('hesabix_show_product_code_in_products_page', 0) == 1) { + $this->loader->add_filter('manage_edit-product_columns', $plugin_admin, 'admin_products_hesabixId_column', 12); + $this->loader->add_action('manage_product_posts_custom_column', $plugin_admin, 'admin_products_hesabixId_column_content', 10, 2); + $this->loader->add_filter('manage_edit-product_sortable_columns', $plugin_admin, 'admin_products_hesabixId_column'); + } + $this->loader->add_action('custom_product_tabs', $plugin_admin, 'hesabix_general_notices'); + $this->loader->add_filter('bulk_actions-edit-shop_order', $plugin_admin, 'custom_orders_list_bulk_action', 20, 1); + $this->loader->add_filter('handle_bulk_actions-edit-shop_order', $plugin_admin, 'custom_orders_list_bulk_action_run', 10, 3); + if (get_option('woocommerce_custom_orders_table_enabled') == 'yes') { + $this->loader->add_filter('woocommerce_shop_order_list_table_columns', $plugin_admin, 'custom_hesabix_column_order_list', 20); + $this->loader->add_action('woocommerce_shop_order_list_table_custom_column', $plugin_admin, 'custom_orders_list_column_content', 10, 2); + } else { + $this->loader->add_filter('manage_edit-shop_order_columns', $plugin_admin, 'custom_hesabix_column_order_list', 20); + $this->loader->add_action('manage_shop_order_posts_custom_column', $plugin_admin, 'custom_orders_list_column_content', 20, 2); + } + $this->loader->add_filter('woocommerce_checkout_fields', $plugin_admin, 'add_additional_fields_to_checkout', 10, 3); + $this->loader->add_action('woocommerce_admin_order_data_after_billing_address', $plugin_admin, 'show_additional_fields_in_order_detail', 10, 3); + $this->loader->add_action('woocommerce_order_status_changed', $plugin_admin, 'hesabix_hook_order_status_change', 10, 3); + $this->loader->add_filter('woocommerce_order_status_changed', $plugin_admin, 'hesabix_hook_payment_confirmation', 11, 3); + $this->loader->add_action('woocommerce_new_order', $plugin_admin, 'hesabix_hook_new_order', 11, 2); + $this->loader->add_action('edit_user_profile', $plugin_admin, 'hesabix_hook_edit_user'); + $this->loader->add_action('user_register', $plugin_admin, 'hesabix_hook_user_register'); + $this->loader->add_action('personal_options_update', $plugin_admin, 'hesabix_hook_user_register'); + $this->loader->add_action('profile_update', $plugin_admin, 'hesabix_hook_user_register'); + $this->loader->add_action('delete_user', $plugin_admin, 'hesabix_hook_delete_user'); + $this->loader->add_action('woocommerce_update_product', $plugin_admin, 'hesabix_hook_new_product'); + $this->loader->add_action('before_delete_post', $plugin_admin, 'hesabix_hook_delete_product'); + $this->loader->add_action('woocommerce_product_options_general_product_data', $plugin_admin, 'hesabix_hook_product_options_general_product_data'); + $this->loader->add_action('woocommerce_process_product_meta', $plugin_admin, 'hesabix_hook_process_product_meta'); + $this->loader->add_action('woocommerce_product_after_variable_attributes', $plugin_admin, 'hesabix_hook_product_after_variable_attributes', 10, 3); + $this->loader->add_action('woocommerce_save_product_variation', $plugin_admin, 'hesabix_hook_save_product_variation', 10, 3); + $this->loader->add_filter('woocommerce_product_data_tabs', $plugin_admin, 'add_hesabix_product_data_tab'); + $this->loader->add_action('woocommerce_product_data_panels', $plugin_admin, 'add_hesabix_product_data_fields'); + + } elseif (!get_option('hesabix_live_mode')) { + if (get_option('hesabix_business_expired')) { + $this->loader->add_action('admin_notices', $plugin_admin, 'hesabix_business_expired_notice'); + } else { + $this->loader->add_action('admin_notices', $plugin_admin, 'hesabix_live_mode_notice'); + } + } + $this->loader->add_filter('wp_ajax_adminExportProducts', $plugin_admin, 'adminExportProductsCallback'); + $this->loader->add_filter('wp_ajax_adminImportProducts', $plugin_admin, 'adminImportProductsCallback'); + $this->loader->add_filter('wp_ajax_adminExportProductsOpeningQuantity', $plugin_admin, 'adminExportProductsOpeningQuantityCallback'); + $this->loader->add_filter('wp_ajax_adminExportCustomers', $plugin_admin, 'adminExportCustomersCallback'); + $this->loader->add_filter('wp_ajax_adminSyncChanges', $plugin_admin, 'adminSyncChangesCallback'); + $this->loader->add_filter('wp_ajax_admin_sync_products', $plugin_admin, 'admin_sync_products_callback'); + $this->loader->add_filter('wp_ajax_admin_sync_orders', $plugin_admin, 'admin_sync_orders_callback'); + $this->loader->add_filter('wp_ajax_admin_update_products', $plugin_admin, 'admin_update_products_callback'); + $this->loader->add_filter('wp_ajax_admin_update_wc_products', $plugin_admin, 'admin_update_wc_products_callback'); + $this->loader->add_filter('wp_ajax_adminUpdateProductsWithFilter', $plugin_admin, 'adminUpdateProductsWithFilterCallback'); + $this->loader->add_filter('wp_ajax_adminSubmitInvoice', $plugin_admin, 'adminSubmitInvoiceCallback'); + $this->loader->add_filter('wp_ajax_hesabix_update_customers', $plugin_admin, 'hesabix_update_customers_ajax'); + $this->loader->add_filter('wp_ajax_adminCleanLogFile', $plugin_admin, 'adminCleanLogFileCallback'); + $this->loader->add_filter('wp_ajax_adminClearPluginData', $plugin_admin, 'adminClearPluginDataCallback', 10, 4); + $this->loader->add_filter('wp_ajax_adminInstallPluginData', $plugin_admin, 'adminInstallPluginDataCallback', 10, 4); + $this->loader->add_filter('wp_ajax_adminChangeProductCode', $plugin_admin, 'adminChangeProductCodeCallback'); + $this->loader->add_filter('wp_ajax_adminDeleteProductLink', $plugin_admin, 'adminDeleteProductLinkCallback'); + $this->loader->add_filter('wp_ajax_adminUpdateProduct', $plugin_admin, 'adminUpdateProductCallback'); + $this->loader->add_filter('wp_ajax_adminChangeProductsCode', $plugin_admin, 'adminChangeProductsCodeCallback'); + $this->loader->add_filter('wp_ajax_adminDeleteProductsLink', $plugin_admin, 'adminDeleteProductsLinkCallback'); + $this->loader->add_filter('wp_ajax_adminUpdateProductAndVariations', $plugin_admin, 'adminUpdateProductAndVariationsCallback'); + $this->loader->add_filter('wp_ajax_admin_get_home_stats', $plugin_admin, 'admin_get_home_stats_callback'); + $this->loader->add_filter('wp_ajax_admin_check_for_updates', $plugin_admin, 'admin_check_for_updates_callback'); + $this->loader->add_filter('wp_ajax_adminSaveApiSettings', $plugin_admin, 'adminSaveApiSettingsCallback'); + $this->loader->add_filter('wp_ajax_adminTestApiConnection', $plugin_admin, 'adminTestApiConnectionCallback'); + + + } + } + + public function run() + { + $this->loader->run(); + } + public function get_plugin_name() + { + return $this->plugin_name; + } + public function get_loader() + { + return $this->loader; + } + public function get_version() + { + return $this->version; + } +} diff --git a/includes/class-ssbhesabix-activator.php b/includes/class-ssbhesabix-activator.php deleted file mode 100644 index 4d58713..0000000 --- a/includes/class-ssbhesabix-activator.php +++ /dev/null @@ -1,69 +0,0 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - */ -class Ssbhesabix_Activator { - public static $ssbhesabix_db_version = '1.1'; - - /** - * Short Description. (use period) - * - * Long Description. - * - * @since 1.0.0 - */ -//=============================================================================================================== - public static function activate() { - add_option('ssbhesabix_webhook_password', bin2hex(openssl_random_pseudo_bytes(16))); - add_option('ssbhesabix_last_log_check_id', 0); - add_option('ssbhesabix_live_mode', 0); - add_option('ssbhesabix_debug_mode', 0); - add_option('ssbhesabix_contact_address_status', 1); - add_option('ssbhesabix_contact_node_family', 'مشتریان فروشگاه آن‌لاین'); - add_option('ssbhesabix_contact_automaatic_save_node_family', 'yes'); - add_option('ssbhesabix_contact_automatically_save_in_hesabix', 'yes'); - add_option('ssbhesabix_activation_date', date("Y-m-d")); - add_option('ssbhesabix_use_export_product_opening_quantity', false); - add_option('ssbhesabix_business_expired', 0); - add_option('ssbhesabix_do_not_submit_product_automatically', "no"); - add_option('ssbhesabix_do_not_update_product_price_in_hesabix', "no"); - add_option('ssbhesabix_contact_add_additional_checkout_fields_hesabix', 1); - - self::ssbhesabix_create_database_table(); - } -//=============================================================================================================== - public static function ssbhesabix_create_database_table() - { - global $wpdb; - $table_name = $wpdb->prefix . "ssbhesabix"; - $charset_collate = $wpdb->get_charset_collate(); - - $sql = " - CREATE TABLE $table_name ( - id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, - obj_type varchar(32) NOT NULL, - id_hesabix int(11) UNSIGNED NOT NULL, - id_ps int(11) UNSIGNED NOT NULL, - id_ps_attribute int(11) UNSIGNED NOT NULL DEFAULT 0, - PRIMARY KEY (id) - ) $charset_collate;"; - - require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); - dbDelta($sql); - - update_option('ssbhesabix_db_version', self::$ssbhesabix_db_version); - } -//=============================================================================================================== -} diff --git a/includes/class-ssbhesabix-deactivator.php b/includes/class-ssbhesabix-deactivator.php deleted file mode 100644 index 86dd543..0000000 --- a/includes/class-ssbhesabix-deactivator.php +++ /dev/null @@ -1,28 +0,0 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - */ -class Ssbhesabix_Deactivator { - - /** - * Short Description. (use period) - * - * Long Description. - * - * @since 1.0.0 - */ - public static function deactivate() { - - } - -} diff --git a/includes/class-ssbhesabix-i18n.php b/includes/class-ssbhesabix-i18n.php deleted file mode 100644 index f0ab1e0..0000000 --- a/includes/class-ssbhesabix-i18n.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - * @author Babak Alizadeh - */ -class Ssbhesabix_i18n { - - - /** - * Load the plugin text domain for translation. - * - * @since 1.0.0 - */ - public function load_plugin_textdomain() { - - load_plugin_textdomain( - 'ssbhesabix', - false, - dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/languages/' - ); - - } -} diff --git a/includes/class-ssbhesabix-loader.php b/includes/class-ssbhesabix-loader.php deleted file mode 100644 index 8a9cc4b..0000000 --- a/includes/class-ssbhesabix-loader.php +++ /dev/null @@ -1,123 +0,0 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - * @author Babak Alizadeh - */ - -class Ssbhesabix_Loader { - - /** - * The array of actions registered with WordPress. - * - * @since 1.0.0 - * @access protected - * @var array $actions The actions registered with WordPress to fire when the plugin loads. - */ - protected $actions; - - /** - * The array of filters registered with WordPress. - * - * @since 1.0.0 - * @access protected - * @var array $filters The filters registered with WordPress to fire when the plugin loads. - */ - protected $filters; - - /** - * Initialize the collections used to maintain the actions and filters. - * - * @since 1.0.0 - */ - public function __construct() { - - $this->actions = array(); - $this->filters = array(); - - } - - /** - * Add a new action to the collection to be registered with WordPress. - * - * @since 1.0.0 - * @param string $hook The name of the WordPress action that is being registered. - * @param object $component A reference to the instance of the object on which the action is defined. - * @param string $callback The name of the function definition on the $component. - * @param int $priority Optional. The priority at which the function should be fired. Default is 10. - * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1. - */ - public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) { - $this->actions = $this->add( $this->actions, $hook, $component, $callback, $priority, $accepted_args ); - } - - /** - * Add a new filter to the collection to be registered with WordPress. - * - * @since 1.0.0 - * @param string $hook The name of the WordPress filter that is being registered. - * @param object $component A reference to the instance of the object on which the filter is defined. - * @param string $callback The name of the function definition on the $component. - * @param int $priority Optional. The priority at which the function should be fired. Default is 10. - * @param int $accepted_args Optional. The number of arguments that should be passed to the $callback. Default is 1 - */ - public function add_filter( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) { - $this->filters = $this->add( $this->filters, $hook, $component, $callback, $priority, $accepted_args ); - } - - /** - * A utility function that is used to register the actions and hooks into a single - * collection. - * - * @since 1.0.0 - * @access private - * @param array $hooks The collection of hooks that is being registered (that is, actions or filters). - * @param string $hook The name of the WordPress filter that is being registered. - * @param object $component A reference to the instance of the object on which the filter is defined. - * @param string $callback The name of the function definition on the $component. - * @param int $priority The priority at which the function should be fired. - * @param int $accepted_args The number of arguments that should be passed to the $callback. - * @return array The collection of actions and filters registered with WordPress. - */ - private function add( $hooks, $hook, $component, $callback, $priority, $accepted_args ) { - - $hooks[] = array( - 'hook' => $hook, - 'component' => $component, - 'callback' => $callback, - 'priority' => $priority, - 'accepted_args' => $accepted_args - ); - - return $hooks; - - } - - /** - * Register the filters and actions with WordPress. - * - * @since 1.0.0 - */ - public function run() { - - foreach ( $this->filters as $hook ) { - add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] ); - } - - foreach ( $this->actions as $hook ) { - add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] ); - } - - } - -} diff --git a/includes/class-ssbhesabix-validation.php b/includes/class-ssbhesabix-validation.php deleted file mode 100644 index 02e23ef..0000000 --- a/includes/class-ssbhesabix-validation.php +++ /dev/null @@ -1,318 +0,0 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - * @author Babak Alizadeh - */ - -class Ssbhesabix_Validation -{ - public static function itemCodeValidation($code) - { - $code = preg_replace('/[^0-9]/', '', $code); - $code = self::formatFarsiNumbers($code); - return mb_substr($code, 0, 5); - } -//============================================================================================= - public static function itemNameValidation($name) - { - $name = self::formatFarsiNumbers($name); - return self::remove_emoji($name, 199); - } -//============================================================================================= - public static function formatFarsiNumbers($str) { - $farsiNumbers = ["۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"]; - $englishNumbers = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; - for ($i = 0; $i < 10; $i++) - $str = str_replace($farsiNumbers[$i], $englishNumbers[$i], $str); - return $str; - } -//============================================================================================= - public static function itemBarcodeValidation($barcode) - { - $barcode = self::formatFarsiNumbers($barcode); - return mb_substr($barcode, 0, 999); - } -//============================================================================================= - public static function itemCategoryValidation($category) {return $category;} -//============================================================================================= - public static function itemDescriptionValidation($description) {return mb_substr($description, 0, 199);} -//============================================================================================= - public static function itemMainUnitValidation($mainUnit) {return mb_substr($mainUnit, 0, 29);} -//============================================================================================= - public static function itemSubUnitValidation($subUnit) {return mb_substr($subUnit, 0, 29);} -//============================================================================================= - public static function itemConversionFactorValidation($conversionFactor) - { - if ($conversionFactor < 0) { - return 0; - } else { - return $conversionFactor; - } - } -//============================================================================================= - public static function itemSalesTaxValidation($salesTax) - { - if ($salesTax >= 0 && $salesTax <= 100) { - return $salesTax; - } else { - return 0; - } - } -//============================================================================================= - public static function itemSalesInfoValidation($salesInfo) {return mb_substr($salesInfo, 0, 99);} -//============================================================================================= - public static function itemPurchaseCostValidation($purchaseCost) - { - if ($purchaseCost >= 0) { - return $purchaseCost; - } else { - return 0; - } - } -//============================================================================================= - public static function itemPurchaseInfoValidation($purchaseInfo) {return mb_substr($purchaseInfo, 0, 99);} -//============================================================================================= - public static function itemTagValidation($tag) {return mb_substr($tag, 0, 254);} -//============================================================================================= - public static function contactCodeValidation($code) - { - $code = preg_replace('/[^0-9]/', '', $code); - return mb_substr($code, 0, 5); - } -//============================================================================================= - public static function contactDisplayNameValidation($displayName) {return mb_substr($displayName, 0, 99);} -//============================================================================================= - public static function contactCompanyValidation($company) {return mb_substr($company, 0, 99);} -//============================================================================================= - public static function contactTitleValidation($title) {return mb_substr($title, 0, 49);} -//============================================================================================= - public static function contactFirstNameValidation($firstName) {return mb_substr($firstName, 0, 49);} -//============================================================================================= - public static function contactLastNameValidation($lastName) {return mb_substr($lastName, 0, 49);} -//============================================================================================= - public static function contactAddressValidation($address) {return mb_substr($address, 0, 149);} -//============================================================================================= - public static function contactCountryValidation($country) {return mb_substr($country, 0, 49);} -//============================================================================================= - public static function contactStateValidation($state) { - if ( is_numeric( $state ) ) { - if(is_plugin_active("persian-woocommerce-shipping/woocommerce-shipping.php")) { - $state = PWS()::get_state( $state ); - } - } - return mb_substr($state, 0, 49); - } -//============================================================================================= - public static function contactCityValidation($city) { - if ( is_numeric( $city ) ) { - if(is_plugin_active("persian-woocommerce-shipping/woocommerce-shipping.php")) { - $city = PWS()::get_city($city); - } - } - return mb_substr($city, 0, 49); - } -//============================================================================================= - public static function contactPostalCodeValidation($postalCode) - { - $postalCode = preg_replace('/[^0-9]/', '', $postalCode); - $postalCode = self::formatFarsiNumbers($postalCode); - return mb_substr($postalCode, 0, 10); - } -//============================================================================================= - public static function contactPhoneValidation($phone) - { - $phone = preg_replace('/[^0-9]/', '', $phone); - $phone = self::formatFarsiNumbers($phone); - return mb_substr($phone, 0, 14); - } -//============================================================================================= - public static function contactMobileValidation($mobile) - { - $mobile = preg_replace('/[^0-9]/', '', $mobile); - return mb_substr($mobile, 0, 14); - } -//============================================================================================= - public static function contactFaxValidation($fax) - { - $fax = preg_replace('/[^0-9]/', '', $fax); - return mb_substr($fax, 0, 14); - } -//============================================================================================= - public static function contactEmailValidation($email) - { - $isValid = true; - $atIndex = strrpos($email, "@"); - if (is_bool($atIndex) && !$atIndex) { - $isValid = false; - } else { - $domain = substr($email, $atIndex + 1); - $local = substr($email, 0, $atIndex); - $localLen = strlen($local); - $domainLen = strlen($domain); - if ($localLen < 1 || $localLen > 64) { - // local part length exceeded - $isValid = false; - } else if ($domainLen < 1 || $domainLen > 255) { - // domain part length exceeded - $isValid = false; - } else if ($local[0] == '.' || $local[$localLen - 1] == '.') { - // local part starts or ends with '.' - $isValid = false; - } else if (preg_match('/\\.\\./', $local)) { - // local part has two consecutive dots - $isValid = false; - } else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) { - // character not valid in domain part - $isValid = false; - } else if (preg_match('/\\.\\./', $domain)) { - // domain part has two consecutive dots - $isValid = false; - } else if - (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', - str_replace("\\\\", "", $local))) { - // character not valid in local part unless - // local part is quoted - if (!preg_match('/^"(\\\\"|[^"])+"$/', - str_replace("\\\\", "", $local))) { - $isValid = false; - } - } - } - - if ($isValid) { - return $email; - } else { - return null; - } - } -//============================================================================================= - public static function contactWebsiteValidation($website) {return mb_substr($website, 0, 119);} -//============================================================================================= - public static function contactNoteValidation($note) {return mb_substr($note, 0, 499);} -//============================================================================================= - public static function contactCategoryValidation($category) {return $category;} -//============================================================================================= - public static function contactTagValidation($tag) {return mb_substr($tag, 0, 254);} -//============================================================================================= - public static function invoiceFinancialYearValidation($financialYear) {return $financialYear;} -//============================================================================================= - public static function invoiceCurrencyRateValidation($currencyRate) - { - if ($currencyRate > 0) { - return $currencyRate; - } else { - return 1; - } - } -//============================================================================================= - public static function invoiceNumberValidation($number) {return mb_substr($number, 0, 49);} -//============================================================================================= - public static function invoiceContactTitleValidation($contactTitle) {return mb_substr($contactTitle, 0, 199);} -//============================================================================================= - public static function invoiceDueDateValidation($dueDate) {return $dueDate;} -//============================================================================================= - public static function invoiceNoteValidation($note) {return mb_substr($note, 0, 499);} -//============================================================================================= - public static function invoiceReferenceValidation($reference) {return mb_substr($reference, 0, 49);} -//============================================================================================= - public static function invoiceTagValidation($tag) {return mb_substr($tag, 0, 254);} -//============================================================================================= - public function invoiceItemsValidation($items) {return $items;} -//============================================================================================= - public static function invoiceItemDescriptionValidation($description) { - return self::remove_emoji($description, 249); - } -//============================================================================================= - public static function invoiceItemQuantityValidation($quantity) - { - if ($quantity > 0) { - return $quantity; - } else { - return 1; - } - } -//============================================================================================= - public static function invoiceItemUnitValidation($unit) {return mb_substr($unit, 0, 29);} -//============================================================================================= - public static function invoiceItemUnitPriceValidation($unitPrice) - { - if ($unitPrice >= 0) { - return $unitPrice; - } else { - return 0; - } - } -//============================================================================================= - public static function invoiceItemAmountValidation($amount) - { - if ($amount >= 0) { - return $amount; - } else { - return 0; - } - } -//============================================================================================= - public static function invoiceItemDiscountValidation($discount) - { - if ($discount >= 0) { - return $discount; - } else { - return 0; - } - } -//============================================================================================= - public static function invoiceItemTaxValidation($tax) - { - if ($tax >= 0) { - return $tax; - } else { - return 0; - } - } -//============================================================================================= - public static function invoiceItemTotalAmountValidation($totalAmount) - { - if ($totalAmount >= 0) { - return $totalAmount; - } else { - return 0; - } - } -//============================================================================================= - public static function remove_emoji($string, $length = 200) : string - { - $regex_alphanumeric = '/[\x{1F100}-\x{1F1FF}]/u'; - $clear_string = preg_replace($regex_alphanumeric, '', $string); - - $regex_symbols = '/[\x{1F300}-\x{1F5FF}]/u'; - $clear_string = preg_replace($regex_symbols, '', $clear_string); - - $regex_emoticons = '/[\x{1F600}-\x{1F64F}]/u'; - $clear_string = preg_replace($regex_emoticons, '', $clear_string); - - $regex_transport = '/[\x{1F680}-\x{1F6FF}]/u'; - $clear_string = preg_replace($regex_transport, '', $clear_string); - - $regex_supplemental = '/[\x{1F900}-\x{1F9FF}]/u'; - $clear_string = preg_replace($regex_supplemental, '', $clear_string); - - $regex_misc = '/[\x{2600}-\x{26FF}\x{1F7E9}-\x{1F7EF}]/u'; - $clear_string = preg_replace($regex_misc, '', $clear_string); - - $regex_dingbats = '/[\x{2700}-\x{27BF}]/u'; - $clear_string = preg_replace($regex_dingbats, '', $clear_string); - - $truncated_string = mb_substr($clear_string, 0, $length); - - return $truncated_string; - } -//============================================================================================= -} diff --git a/includes/class-ssbhesabix.php b/includes/class-ssbhesabix.php deleted file mode 100644 index 2b10951..0000000 --- a/includes/class-ssbhesabix.php +++ /dev/null @@ -1,343 +0,0 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - * @author Babak Alizadeh - */ - -class Ssbhesabix -{ - - /** - * The loader that's responsible for maintaining and registering all hooks that power - * the plugin. - * - * @since 1.0.0 - * @access protected - * @var Ssbhesabix_Loader $loader Maintains and registers all hooks for the plugin. - */ - protected $loader; - - /** - * The unique identifier of this plugin. - * - * @since 1.0.0 - * @access protected - * @var string $plugin_name The string used to uniquely identify this plugin. - */ - protected $plugin_name; - - /** - * The current version of the plugin. - * - * @since 1.0.0 - * @access protected - * @var string $version The current version of the plugin. - */ - protected $version; -//========================================================================================================== - /** - * Define the core functionality of the plugin. - * - * Set the plugin name and the plugin version that can be used throughout the plugin. - * Load the dependencies, define the locale, and set the hooks for the admin area and - * the public-facing side of the site. - * - * @since 1.0.0 - */ - public function __construct() - { - if (defined('SSBHESABIX_VERSION')) { - $this->version = SSBHESABIX_VERSION; - } else { - $this->version = '0.40.1'; - } - $this->plugin_name = 'ssbhesabix'; - - $this->load_dependencies(); - $this->set_locale(); - $this->define_admin_hooks(); - } -//========================================================================================================== - /** - * Load the required dependencies for this plugin. - * - * Include the following files that make up the plugin: - * - * - Ssbhesabix_Loader. Orchestrates the hooks of the plugin. - * - Ssbhesabix_i18n. Defines internationalization functionality. - * - Ssbhesabix_Admin. Defines all hooks for the admin area. - * - Ssbhesabix_Public. Defines all hooks for the public side of the site. - * - * Create an instance of the loader which will be used to register the hooks - * with WordPress. - * - * @since 1.0.0 - * @access private - */ - private function load_dependencies() - { - - /** - * The class responsible for orchestrating the actions and filters of the - * core plugin. - */ - require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-ssbhesabix-loader.php'; - - /** - * The class responsible for defining internationalization functionality - * of the plugin. - */ - require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-ssbhesabix-i18n.php'; - - /** - * The class responsible for defining all actions that occur in the admin area. - */ - require_once plugin_dir_path(dirname(__FILE__)) . 'admin/class-ssbhesabix-admin.php'; - - /** - * The class responsible for defining all hesabix API methods - */ - require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-ssbhesabix-api.php'; - - $this->loader = new Ssbhesabix_Loader(); - - /** - * The class responsible for defining all hesabix data Validations - */ - require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-ssbhesabix-validation.php'; - - $this->loader = new Ssbhesabix_Loader(); - - } -//===================================================================================== - /** - * Define the locale for this plugin for internationalization. - * - * Uses the Plugin_Name_i18n class in order to set the domain and to register the hook - * with WordPress. - * - * @since 1.0.0 - * @access private - */ - private function set_locale() - { - $plugin_i18n = new Ssbhesabix_i18n(); - - $this->loader->add_action('plugins_loaded', $plugin_i18n, 'load_plugin_textdomain'); - } -//===================================================================================== - /** - * Register all of the hooks related to the admin area functionality - * of the plugin. - * - * @since 1.0.0 - * @access private - */ - private function define_admin_hooks() - { - $plugin_admin = new Ssbhesabix_Admin($this->get_plugin_name(), $this->get_version()); - - //Related to check DB ver on plugin update - //$this->loader->add_action('plugins_loaded', $plugin_admin, 'ssbhesabix_update_db_check'); - - $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_styles'); - $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts'); - - //Related to webhook set - $this->loader->add_filter('query_vars', $plugin_admin, 'ssbhesabix_query_vars'); - $this->loader->add_action('parse_request', $plugin_admin, 'ssbhesabix_parse_request'); - - $this->loader->add_action('wp_ajax_nopriv_handle_webhook_request', $plugin_admin, 'ssbhesabix_parse_request'); - $this->loader->add_action('wp_ajax_handle_webhook_request', $plugin_admin, 'ssbhesabix_parse_request'); - - if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) { - - $this->loader->add_action('init', $plugin_admin, 'ssbhesabix_init_internal'); - - //Check plugin live mode - if (get_option('ssbhesabix_live_mode')) { - if (get_option('ssbhesabix_hesabix_default_currency') === 0) { - $this->loader->add_action('admin_notices', $plugin_admin, 'ssbhesabix_currency_notice'); - } - - if(get_option('ssbhesabix_show_hesabix_code_in_excel_export', 'no') == 'yes' || get_option('ssbhesabix_show_hesabix_code_in_excel_export', 0) == 1) { - ///////////ADD COLUMN TO WOOCOMMERCE CSV - $this->loader->add_filter( 'woocommerce_product_export_column_names', $plugin_admin, 'admin_product_add_column' ); - $this->loader->add_filter( 'woocommerce_product_export_product_default_columns', $plugin_admin, 'admin_product_add_column' ); - $this->loader->add_filter('woocommerce_product_export_rows', $plugin_admin, 'admin_product_export_rows', 10, 2); - } - // these lines add hesabix id to the all products list page and make it sortable as well - /////////////////////////////////////////////////////////////////////////////////////////////////////// - if(get_option('ssbhesabix_show_product_code_in_products_page') === 'yes') { - $this->loader->add_filter( 'manage_edit-product_columns', $plugin_admin,'admin_products_hesabixId_column', 12 ); - $this->loader->add_action( 'manage_product_posts_custom_column', $plugin_admin, 'admin_products_hesabixId_column_content', 10, 2 ); - $this->loader->add_filter( 'manage_edit-product_sortable_columns', $plugin_admin,'admin_products_hesabixId_column'); - } - - $this->loader->add_action('custom_product_tabs', $plugin_admin, 'ssbhesabix_general_notices'); - - // add filter and action for woocommerce order list - - $this->loader->add_filter('bulk_actions-edit-shop_order', $plugin_admin, 'custom_orders_list_bulk_action', 20, 1); - $this->loader->add_filter('handle_bulk_actions-edit-shop_order', $plugin_admin, 'custom_orders_list_bulk_action_run', 10, 3); - - if (get_option('woocommerce_custom_orders_table_enabled') == 'yes') { - $this->loader->add_filter( 'woocommerce_shop_order_list_table_columns', $plugin_admin, 'custom_hesabix_column_order_list', 20); - $this->loader->add_action( 'woocommerce_shop_order_list_table_custom_column', $plugin_admin, 'custom_orders_list_column_content', 10, 2 ); - } else { - $this->loader->add_filter('manage_edit-shop_order_columns', $plugin_admin, 'custom_hesabix_column_order_list', 20); - $this->loader->add_action('manage_shop_order_posts_custom_column', $plugin_admin, 'custom_orders_list_column_content', 20, 2); - } - - // check add fields to checkout page by hesabix plugin - if(get_option('ssbhesabix_contact_add_additional_checkout_fields_hesabix') == 1) { - $this->loader->add_filter('woocommerce_checkout_fields', $plugin_admin, 'add_additional_fields_to_checkout', 10, 3); - } - - // show checkout additional fields in order detail - if(get_option('ssbhesabix_contact_add_additional_checkout_fields_hesabix') == 1) { - $this->loader->add_action('woocommerce_admin_order_data_after_billing_address', $plugin_admin, 'show_additional_fields_in_order_detail', 10, 3); - } - - //Runs when a new order added. - $this->loader->add_action('woocommerce_order_status_changed', $plugin_admin, 'ssbhesabix_hook_order_status_change', 10, 3); - - //Runs when an order paid. -// $this->loader->add_action('woocommerce_payment_complete', $plugin_admin, 'ssbhesabix_hook_payment_confirmation', 10, 1); -// $this->loader->add_filter('woocommerce_payment_complete_order_status', $plugin_admin, 'ssbhesabix_hook_payment_confirmation', 10, 1); -// $this->loader->add_filter('woocommerce_order_status_completed', $plugin_admin, 'ssbhesabix_hook_payment_confirmation', 10, 1); - $this->loader->add_filter('woocommerce_order_status_changed', $plugin_admin, 'ssbhesabix_hook_payment_confirmation', 11, 3); - - $this->loader->add_action('woocommerce_new_order', $plugin_admin, 'ssbhesabix_hook_new_order', 11, 2); - - //Runs when a user's profile is first created. - $this->loader->add_action('edit_user_profile', $plugin_admin, 'ssbhesabix_hook_edit_user'); - - $this->loader->add_action('user_register', $plugin_admin, 'ssbhesabix_hook_user_register'); -// $this->loader->add_action('woocommerce_new_customer', $plugin_admin, 'ssbhesabix_hook_user_register'); -// $this->loader->add_action('woocommerce_created_customer', $plugin_admin, 'ssbhesabix_hook_user_register'); - //Runs when a user updates personal options from the admin screen. - $this->loader->add_action('personal_options_update', $plugin_admin, 'ssbhesabix_hook_user_register'); - //Runs when a user's profile is updated. - $this->loader->add_action('profile_update', $plugin_admin, 'ssbhesabix_hook_user_register'); - //Runs when a user is deleted. - $this->loader->add_action('delete_user', $plugin_admin, 'ssbhesabix_hook_delete_user'); - - //Runs when a product is added. -// $this->loader->add_action('woocommerce_new_product', $plugin_admin, 'ssbhesabix_hook_new_product'); -// $this->loader->add_action('woocommerce_new_product_variation', $plugin_admin, 'ssbhesabix_hook_new_product_variation', 10, 2); - //Runs when a product is updated. - $this->loader->add_action('woocommerce_update_product', $plugin_admin, 'ssbhesabix_hook_new_product'); -// $this->loader->add_action('woocommerce_update_product_variation', $plugin_admin, 'ssbhesabix_hook_new_product'); - //Runs when a product is deleted. - $this->loader->add_action('before_delete_post', $plugin_admin, 'ssbhesabix_hook_delete_product'); - //$this->loader->add_action('woocommerce_delete_product_variation', $plugin_admin, 'ssbhesabix_hook_delete_product_variation'); - - //Display hesabix item code in Product data section - $this->loader->add_action('woocommerce_product_options_general_product_data', $plugin_admin, 'ssbhesabix_hook_product_options_general_product_data'); - $this->loader->add_action('woocommerce_process_product_meta', $plugin_admin, 'ssbhesabix_hook_process_product_meta'); - //Display hesabix item code in Product variable attribute section - $this->loader->add_action('woocommerce_product_after_variable_attributes', $plugin_admin, 'ssbhesabix_hook_product_after_variable_attributes', 10, 3); - $this->loader->add_action('woocommerce_save_product_variation', $plugin_admin, 'ssbhesabix_hook_save_product_variation', 10, 3); - - $this->loader->add_filter('woocommerce_product_data_tabs', $plugin_admin, 'add_hesabix_product_data_tab'); - $this->loader->add_action('woocommerce_product_data_panels', $plugin_admin, 'add_hesabix_product_data_fields'); - - } elseif (!get_option('ssbhesabix_live_mode')) { - if (get_option('ssbhesabix_business_expired')) - $this->loader->add_action('admin_notices', $plugin_admin, 'ssbhesabix_business_expired_notice'); - else - $this->loader->add_action('admin_notices', $plugin_admin, 'ssbhesabix_live_mode_notice'); - } - - /* - * Action - Ajax 'Export Tabs' from hesabix/Export - * @since 1.0.0 - */ - $this->loader->add_filter('wp_ajax_adminExportProducts', $plugin_admin, 'adminExportProductsCallback'); - $this->loader->add_filter('wp_ajax_adminImportProducts', $plugin_admin, 'adminImportProductsCallback'); - $this->loader->add_filter('wp_ajax_adminExportProductsOpeningQuantity', $plugin_admin, 'adminExportProductsOpeningQuantityCallback'); - $this->loader->add_filter('wp_ajax_adminExportCustomers', $plugin_admin, 'adminExportCustomersCallback'); - - /* - * Action - Ajax 'Sync Tabs' from hesabix/Sync - * @since 1.0.0 - */ - $this->loader->add_filter('wp_ajax_adminSyncChanges', $plugin_admin, 'adminSyncChangesCallback'); - $this->loader->add_filter('wp_ajax_adminSyncProducts', $plugin_admin, 'adminSyncProductsCallback'); - $this->loader->add_filter('wp_ajax_adminSyncOrders', $plugin_admin, 'adminSyncOrdersCallback'); - $this->loader->add_filter('wp_ajax_adminUpdateProducts', $plugin_admin, 'adminUpdateProductsCallback'); - $this->loader->add_filter('wp_ajax_adminUpdateProductsWithFilter', $plugin_admin, 'adminUpdateProductsWithFilterCallback'); - $this->loader->add_filter('wp_ajax_adminSubmitInvoice', $plugin_admin, 'adminSubmitInvoiceCallback'); - - /* - * Action - Ajax 'Log Tab' from hesabix/Log - * @since 1.0.0 - */ - $this->loader->add_filter('wp_ajax_adminCleanLogFile', $plugin_admin, 'adminCleanLogFileCallback'); - - $this->loader->add_filter('wp_ajax_adminSyncProductsManually', $plugin_admin, 'adminSyncProductsManuallyCallback', 10, 4); - $this->loader->add_filter('wp_ajax_adminClearPluginData', $plugin_admin, 'adminClearPluginDataCallback', 10, 4); - $this->loader->add_filter('wp_ajax_adminInstallPluginData', $plugin_admin, 'adminInstallPluginDataCallback', 10, 4); - - $this->loader->add_filter('wp_ajax_adminChangeProductCode', $plugin_admin, 'adminChangeProductCodeCallback'); - $this->loader->add_filter('wp_ajax_adminDeleteProductLink', $plugin_admin, 'adminDeleteProductLinkCallback'); - $this->loader->add_filter('wp_ajax_adminUpdateProduct', $plugin_admin, 'adminUpdateProductCallback'); - $this->loader->add_filter('wp_ajax_adminChangeProductsCode', $plugin_admin, 'adminChangeProductsCodeCallback'); - $this->loader->add_filter('wp_ajax_adminDeleteProductsLink', $plugin_admin, 'adminDeleteProductsLinkCallback'); - $this->loader->add_filter('wp_ajax_adminUpdateProductAndVariations', $plugin_admin, 'adminUpdateProductAndVariationsCallback'); - - } else { - $this->loader->add_action('admin_notices', $plugin_admin, 'ssbhesabix_missing_notice'); - } - } -//===================================================================================== - /** - * Run the loader to execute all of the hooks with WordPress. - * - * @since 1.0.0 - */ - public function run() {$this->loader->run();} -//===================================================================================== - /** - * The name of the plugin used to uniquely identify it within the context of - * WordPress and to define internationalization functionality. - * - * @return string The name of the plugin. - * @since 1.0.0 - */ - public function get_plugin_name() {return $this->plugin_name;} -//===================================================================================== - /** - * The reference to the class that orchestrates the hooks with the plugin. - * - * @return Ssbhesabix_Loader Orchestrates the hooks of the plugin. - * @since 1.0.0 - */ - public function get_loader() {return $this->loader;} -//===================================================================================== - /** - * Retrieve the version number of the plugin. - * - * @return string The version number of the plugin. - * @since 1.0.0 - */ - public function get_version() {return $this->version;} -//===================================================================================== -} diff --git a/includes/hesabix-webhook.php b/includes/hesabix-webhook.php new file mode 100644 index 0000000..c4f2d93 --- /dev/null +++ b/includes/hesabix-webhook.php @@ -0,0 +1,33 @@ +Password != get_option('hesabix_webhook_password')) { + die('Invalid password.'); +} + +include(dirname(__FILE__) . '/class-hesabix-webhook.php'); +HesabixLogService::writeLogStr("Hesabix Webhook Called"); +new Hesabix_Webhook(); diff --git a/includes/index.php b/includes/index.php deleted file mode 100644 index e71af0e..0000000 --- a/includes/index.php +++ /dev/null @@ -1 +0,0 @@ - - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - * @author Babak Alizadeh - */ - -/* Check security token */ -if (!(defined('STDIN') || (strtolower(php_sapi_name()) == 'cli' && (!isset($_SERVER['REMOTE_ADDR']) - || empty($_SERVER['REMOTE_ADDR']))))) { - if (substr(wp_hash(AUTH_KEY . 'ssbhesabix/webhook'), 0, 10) != $_GET['token']) { - die('Bad token'); - } -} - -$post = file_get_contents('php://input'); -$result = json_decode($post); - -if (!is_object($result)) { - die('Invalid request.'); -} - -if ($result->Password != get_option('ssbhesabix_webhook_password')) { - die('Invalid password.'); -} - -include(dirname(__FILE__) . '/class-ssbhesabix-webhook.php'); -HesabixLogService::writeLogStr("Hesabix Webhook Called"); -new Ssbhesabix_Webhook(); diff --git a/index.php b/index.php deleted file mode 100644 index e71af0e..0000000 --- a/index.php +++ /dev/null @@ -1 +0,0 @@ -Access Tokens Menu" +msgstr "کلید API را در حسابیکس از منوی تنظیمات->توکن دسترسی پیدا کنید" + +msgid "" +"No products were exported, All products were exported or there are no product" +msgstr "" +"هیچ محصولی استخراج نشد، تمامی محصولات قبلا استخراج شده‌اند یا محصولی وجود " +"ندارد." + +msgid "" +"No products were imported, All products were imported or there are no product" +msgstr "" +"هیچ محصولی وارد نشد، تمامی محصولات قبلا وارد شده‌اند یا محصولی وجود ندارد." + +msgid "Export products completed. %s products added/updated." +msgstr "استخراج محصولات به اتمام رسید. ‪‬%s محصول استخراج شد." + +msgid "Import products completed. %s products added/updated." +msgstr "ورود محصولات به اتمام رسید. ‪‬%s محصول وارد شد." + +msgid "Export products fail. Hesabix has already contained products." +msgstr "خروجی محصولات با خطا مواجه شد. حسابیکس از قبل حاوی محصولاتی است." + +msgid "Export products fail. Please check the log file." +msgstr "خروجی محصولات با خطا مواجه شد. لطفا لاگ را بررسی کنید." + +msgid "Import products fail. Please check the log file." +msgstr "ورود محصولات با خطا مواجه شد. لطفا لاگ را بررسی کنید." + +msgid "Export product opening quantity completed." +msgstr "استخراج موجودی اول دوره با موفقیت به پایان رسید." + +msgid "" +"Export product opening quantity fail. No Shareholder exists, Please define " +"Shareholder in Hesabix" +msgstr "" +"استخراج موجودی اول دوره با خطا مواجه شد. سهامدار تعریف نشده است، لطفا ابتدا " +"سهامداران را در حسابیکس تعریف کنید." + +msgid "No product available for Export product opening quantity." +msgstr "محصولی جهت استخراج موجودی اول دوره در دسترس نمی‌باشد." + +msgid "Export product opening quantity fail. Please check the log file." +msgstr "استخراج موجودی اول دوره با خطا مواجه شد. لطفا لاگ را بررسی کنید." + +msgid "" +"No customers were exported, All customers were exported or there are no " +"customer" +msgstr "" +"هیچ مشتری استخراج نشد، تمامی مشتریان قبلا استخراج شده‌اند یا مشتری وجود " +"ندارد." + +msgid "Export customers completed. %s customers added." +msgstr "استخراج مشتریان به اتمام رسید. %s مشتری استخراج شد." + +msgid "Export customers fail. Please check the log file." +msgstr "استخراج مشتریان با خطا مواجه شد. لطفا لاگ را بررسی کنید." + +msgid "Export can take several minutes." +msgstr "استخراج ممکن است چند دقیقه زمان ببرد." + +msgid "Export customers fail. Hesabix has already contained customers." +msgstr "خروجی مشتریان با خطا مواجه شد. حسابیکس از قبل حاوی مشتریان است." + +msgid "Export Products" +msgstr "خروجی محصولات" + +msgid "Import Products" +msgstr "ورود محصولات" + +msgid "Export and add all online store products to Hesabix" +msgstr "افزودن تمامی محصولات فروشگاه آنلاین در حسابیکس" + +msgid "Import and add all products from Hesabix to online store" +msgstr "افزودن تمامی محصولات حسابیکس به فروشگاه آنلاین" + +msgid "Export Products opening quantity" +msgstr "استخراج موجودی اول دوره" + +msgid "" +"Export the products quantity and record the 'products opening quantity' in " +"the Hesabix" +msgstr "استخراج موجودی محصولات و ثبت موجودی اول دوره در حسابیکس" + +msgid "Export Customers" +msgstr "خروجی مشتریان" + +msgid "Export and add all online store customers to Hesabix." +msgstr "افزودن تمامی مشتریان فروشگاه آنلاین در حسابیکس" + +msgid "Sync completed, All hesabix changes synced successfully." +msgstr "همسان‌سازی پایان یافت. تمامی تغییرات با حسابیکس همسان شد." + +msgid "Sync completed, All products price/quantity synced successfully." +msgstr "همسان سازی پایان یافت. قیمت/موجودی تمامی محصولات به روز شدند." + +msgid "Sync products fail. Please check the log file." +msgstr "همسان‌سازی محصولات با خطا مواجه شد. لطفا لاگ را بررسی کنید." + +msgid "Order sync completed. %s order added." +msgstr "همسان‌سازی پایان یافت. %s فاکتور به‌روزرسانی/افزوده شد." + +msgid "The date entered is not within the fiscal year." +msgstr "تاریخ وارد شده در محدوده سال مالی نمی‌باشد." + +msgid "Invoices are not synced before installing the plugin." +msgstr "" +"فاکتورهایی که قبل از زمان نصب این پلاگین صادر شده‌اند، امکان همسان‌سازی " +"ندارند." + +msgid "Cannot sync orders. Please enter valid Date format." +msgstr "امکان همسان سازی سفارشات نیست. لطفا تاریخ معتبری وارد نمایید." + +msgid "Sync can take several minutes." +msgstr "همسان‌سازی ممکن است چند دقیقه زمان ببرد." + +msgid "Enable or Disable Debug Mode" +msgstr "فعال کردن دیباگ مود" + +msgid "" +"Set request amount per batch for sync products based on woocommerce in " +"Hesabix" +msgstr "" +"تعداد درخواست ها در هر پارت برای همسان سازی محصولات در حسابیکس بر اساس " +"فروشگاه آنلاین" + +msgid "" +"Set request amount per batch for sync products based on Hesabix in " +"Woocommerce" +msgstr "" +"تعداد درخواست ها در هر پارت برای همسان سازی محصولات در فروشگاه آنلاین بر " +"اساس حسابیکس" + +msgid "Set request amount per batch for import products" +msgstr "تعداد درخواست ها در هر پارت برای ورود محصولات" + +msgid "Set request amount per batch for export products" +msgstr "تعداد درخواست ها در هر پارت برای استخراج محصولات" + +msgid "select" +msgstr "انتخاب کنید" + +msgid "Plugin Default" +msgstr "مقدار پیش فرض افزونه" + +msgid "Set request amount per batch for export opening quantity of products" +msgstr "تعداد درخواست ها در هر پارت برای استخراج موجودی اول دوره کالا ها" + +msgid "Sync Changes" +msgstr "همسان‌سازی تغییرات" + +msgid "Sync all Hesabix changes with Online Store." +msgstr "همسان‌سازی تمامی تعییرات حسابیکس با فروشگاه آن‌لاین" + +msgid "Sync Products Quantity and Price" +msgstr "همسان‌سازی قیمت و موجودی محصولات" + +msgid "Sync quantity and price of products in hesabix with online store." +msgstr "همسان‌سازی قیمت و موجودی محصولات حسابیکس با فروشگاه آن‌لاین" + +msgid "Sync Orders" +msgstr "همسان‌سازی سفارشات" + +msgid "Sync/Add orders in online store with hesabix from above date." +msgstr "همسان‌سازی سفارشات فروشگاه آن‌لاین با حسابیکس از تاریخ فوق" + +msgid "Cannot check the last change ID. Error Message: " +msgstr "امکان بررسی آخرین تغییرات وجود ندارد. شرح خطا:" + +msgid "" +"The fiscal year has passed or not arrived. Please check the fiscal year " +"settings in Hesabix." +msgstr "" +"سال مالی گذشته است یا هنوز فرا نرسیده است، لطفا تنظیمات سال مالی در حسابیکس " +"را بررسی کنید." + +msgid "Hesabix and WooCommerce default currency must be same." +msgstr "واحد پول پیش‌فرض حسابیکس و ووکامرس باید یکی باشد." + +msgid "Cannot check the Hesabix default currency. Error Message: " +msgstr "امکان دریافت واحد پول پیش‌فرض حسابیکس وجود ندارد. شرح خطا:" + +msgid "API Setting updated. Test Successfully" +msgstr "تنظیمات API به روزرسانی شد، اتصال موفقیت آمیز بود." + +msgid "Cannot set Hesabix webHook. Error Message:" +msgstr "امکان تنظیم وب‌هوک در حسابیکس وجود ندارد. شرح خطا:" + +msgid "Cannot connect to Hesabix. Business expired." +msgstr "امکان اتصال به حسابیکس وجود ندارد، کسب و کار منقضی شده است." + +msgid "" +"Cannot connect to Hesabix servers. Please check your Internet connection" +msgstr "اتصال به حسابیکس برقرار نیست، لطفا اتصال اینترنت را بررسی نمایید." + +msgid "No need to set!" +msgstr "عدم نیاز به تعریف!" + +msgid "Choose" +msgstr "انتخاب کنید" + +msgid "Define at least one bank in Hesabix" +msgstr "حداقل یک حساب بانکی در حسابیکس تعریف کنید." + +msgid "Cannot get Banks detail." +msgstr "امکان دریافت اطلاعات بانک‌ها نیست." + +msgid "Select a page…" +msgstr "انتخاب ‫دسته‌بندی" + +msgid "Settings were saved successfully." +msgstr "تنظیمات به‌روزرسانی شد." + +msgid "https://hesabix.ir/" +msgstr "‏https://hesabix.ir/" + +msgid "Connect Hesabix Online Accounting to WooCommerce." +msgstr "\tاتصال نرم‌افزار حسابداری ابری حسابیکس به ووکامرس" + +msgid "Log" +msgstr "لاگ" + +msgid "Events and bugs log" +msgstr "لاگ رویدادها و خطاها" + +msgid "Clean current log" +msgstr "پاک کردن لاگ جاری" + +msgid "Download log file" +msgstr "دانلود فایل لاگ" + +msgid "The log file was cleared." +msgstr "فایل لاگ پاک شد." + +msgid "Log file not found." +msgstr "فایل لاگ پیدا نشد." + +msgid "Update Products in Hesabix based on store" +msgstr "به روزرسانی محصولات در حسابیکس بر اساس فروشگاه" + +msgid "Update products in hesabix based on products definition in store." +msgstr "" +"به روزرسانی محصولات در حسابیکس بر اساس مشخصات آنها در فروشگاه. محصولات جدید " +"به حسابیکس اضافه می شوند و محصولات قبلی ویرایش می شوند." + +msgid "Update completed successfully." +msgstr "به روزرسانی با موفقیت انجام شد." + +msgid "Update failed. Please check the log file." +msgstr "به روزرسانی ناموفق بود. لطفاً لاگ را بررسی کنید." + +msgid "Number of products in store:" +msgstr "تعداد محصولات در فروشگاه:" + +msgid "Number of products in hesabix:" +msgstr "تعداد محصولات در حسابیکس:" + +msgid "Number of linked products:" +msgstr "تعداد محصولات لینک شده:" + +msgid "Save and next page" +msgstr "ذخیره و صفحه بعد" + +msgid "Invoice in Hesabix" +msgstr "فاکتور حسابیکس" + +msgid "Submit Invoice" +msgstr "ثبت فاکتور" + +msgid "Submit Invoice in Hesabix" +msgstr "ثبت فاکتور در حسابیکس" + +msgid "Submit Product in Hesabix" +msgstr "ثبت محصول در حسابیکس" + +msgid "" +"Do not submit product in Hesabix automatically by saving product in " +"woocommerce" +msgstr "با ذخیره محصول در ووکامرس، محصول را بصورت اتوماتیک در حسابیکس ثبت نکن" + +msgid "Remove The Titles for Attributes When Saving Product To Hesabix" +msgstr "عنوان متغیر های یک محصول را با ذخیره/بروزرسانی در نام محصول حذف کن" + +msgid "Submit Price in Hesabix" +msgstr "ثبت قیمت در حسابیکس" + +msgid "" +"Do not update product price in Hesabix by editing product in woocommerce" +msgstr "با ویرایش محصول در ووکامرس، قیمت محصول را در حسابیکس بروز نکن" + +msgid "Barcode in Hesabix" +msgstr "بارکد در حسابیکس" + +msgid "National Code in Hesabix" +msgstr "کد ملی در حسابیکس" + +msgid "" +"Do not update product barcode in Hesabix by saving product in woocommerce" +msgstr "با ذخیره محصول در ووکامرس، بارکد محصول را در حسابیکس بروز نکن" + +msgid "" +"Do not update product category in Hesabix by saving product in woocommerce" +msgstr "با ذخیره محصول در ووکامرس، دسته بندی محصول را در حسابیکس بروز نکن" + +msgid "Do not update product code in Hesabix by saving product in woocommerce" +msgstr "با ذخیره محصول در ووکامرس، کد محصول را در حسابیکس بروز نکن" + +msgid "Shipping method" +msgstr "روش حمل و نقل" + +msgid "Invoice's Salesman" +msgstr "فروشنده فاکتور" + +msgid "Invoice Salesman Percentage" +msgstr "درصد پورسانت فروشنده فاکتور" + +msgid "Invoice's Project" +msgstr "پروژه فاکتور" + +msgid "Submit Cash in Transit" +msgstr "ثبت در وجوه در راه" + +msgid "Submit Invoice Receipt Cash in Transit" +msgstr "ثبت رسید دریافت فاکتور در وجوه در راه" + +msgid "Default Invoice Transaction Fee Percentage" +msgstr "درصد کارمزد تراکنش به صورت پیش فرض" + +msgid "Plugin Tutorial Video" +msgstr "ویدیوی خودآموز افزونه" + +msgid "Titles" +msgstr "عناوین" + +msgid "Accounting quantity (Total inventory)" +msgstr "موجودی حسابداری (موجودی کل)" + +msgid "Cannot get warehouses." +msgstr "امکان دریافت اطلاعات انبارها نیست." + +msgid "Update product's quantity based on" +msgstr "بروزرسانی موجودی کالا بر اساس" + +msgid "Do not update purchase and sales titles in hesabix" +msgstr "توضیحات (عنوان های) خرید و فروش را در حسابیکس بروز نکن" + +msgid "Warehouse system is not active in Hesabix." +msgstr "سیستم انبارداری در حسابیکس فعال نیست." + +msgid "API Address" +msgstr "آدرس API" + +msgid "Contact Code in Hesabix" +msgstr "کد شخص در حسابیکس" + +msgid "" +"The contact code of this user in Hesabix, if you want to map this user to a " +"contact in Hesabix, enter the Contact code." +msgstr "" +"این فیلد کد شخص در حسابیکس است، اگر می‌خواهید این کاربر را به شخصی در " +"حسابیکس ارتباط دهید، کد شخص را وارد نمایید." + +msgid "" +"To check the phone with national code, you need to enter both billing phone " +"correctly." +msgstr "" +"این فیلد کد ملی شخص در حسابیکس است، اگر می‌خواهید شماره تماس با کد ملی چک " +"شود باید شماره تماس صورتحساب را به درستی وارد نمایید." + +msgid "" +"Error: Select maximum 10 orders. Due to some limitations in Hesabix API, " +"sending too many requests in one minute is not possible." +msgstr "" +"خطا: حداکثر ۱۰ سفارش را انتخاب کنید. بدلیل محدودیت رابط برنامه نویسی " +"حسابیکس، ارسال درخواست های زیاد در یک دقیقه امکان پذیر نیست." + +msgid "Selected orders invoices have been saved. Number of saved invoices: " +msgstr "فاکتور سفارش های انتخاب شده ثبت شد. تعداد فاکتور های ثبت شده: " + +msgid "Update sale price" +msgstr "بروزرسانی قیمت فروش ویژه" + +msgid "The Sale price does not change" +msgstr "قیمت فروش ویژه تغییر نکند" + +msgid "The Sale price gets removed" +msgstr "قیمت فروش ویژه حذف گردد" + +msgid "The sale price get changes in proportion to the regular price" +msgstr "قیمت فروش ویژه به تناسب قیمت اصلی تغییر یابد" + +msgid "Submit invoice base on Dokan orders" +msgstr "ثبت فاکتور بر اساس سفارشات افزونه دکان" + +msgid "Submit parent order" +msgstr "ثبت سفارش مادر" + +msgid "Submit children orders" +msgstr "ثبت زیر سفارش ها" + +msgid "Inactive" +msgstr "غیر فعال" + +msgid "Plugin Features" +msgstr "امکانات افزونه" + +msgid "Complete integration between WooCommerce and Hesabix" +msgstr "یکپارچگی کامل ووکامرس و حسابیکس" + +msgid "Product Management" +msgstr "مدیریت محصولات" + +msgid "" +"Automatic synchronization of products between WooCommerce and Hesabix with " +"inventory management" +msgstr "همگام‌سازی خودکار محصولات بین ووکامرس و حسابیکس همراه با مدیریت موجودی" + +msgid "Customer Management" +msgstr "مدیریت مشتریان" + +msgid "Synchronize customer information and contact details between platforms" +msgstr "همگام‌سازی اطلاعات و جزئیات تماس مشتریان بین پلتفرم‌ها" + +msgid "Invoice Management" +msgstr "مدیریت فاکتورها" + +msgid "Automatic invoice creation and payment tracking in Hesabix" +msgstr "ایجاد خودکار فاکتور و پیگیری پرداخت‌ها در حسابیکس" + +msgid "Real-time Sync" +msgstr "همگام‌سازی لحظه‌ای" + +msgid "" +"Real-time synchronization of data changes between WooCommerce and Hesabix" +msgstr "همگام‌سازی لحظه‌ای تغییرات داده‌ها بین ووکامرس و حسابیکس" + +msgid "Payment Tracking" +msgstr "پیگیری پرداخت‌ها" + +msgid "Automatic payment confirmation and receipt generation in Hesabix" +msgstr "تأیید خودکار پرداخت و صدور رسید در حسابیکس" + +msgid "Advanced Reports" +msgstr "گزارش‌های پیشرفته" + +msgid "Comprehensive reporting and analytics for your business operations" +msgstr "گزارش‌گیری و تحلیل جامع برای عملیات کسب‌وکار شما" + +msgid "Hesabix: WooCommerce" +msgstr "حسابیکس: ووکامرس" + +msgid "Connect Hesabix Online Accounting to WooCommerce" +msgstr "اتصال حسابداری آنلاین حسابیکس به ووکامرس" + +msgid "Version %s" +msgstr "نسخه %s" + +msgid "Login to Hesabix" +msgstr "ورود به حسابیکس" + +msgid "Plugin Guide" +msgstr "راهنمای افزونه" + +msgid "Checking for Updates..." +msgstr "در حال بررسی بروزرسانی..." + +msgid "New version %s is available" +msgstr "نسخه جدید %s موجود است" + +msgid "Current version is up to date" +msgstr "نسخه فعلی بروز است" + +msgid "New version available!" +msgstr "نسخه جدید موجود است!" + +msgid "" +"Version %s of Hesabix plugin has been released. Your current version: %s" +msgstr "نسخه %s از پلاگین حسابیکس منتشر شده است. نسخه فعلی شما: %s" + +msgid "Download new version" +msgstr "دانلود نسخه جدید" + +msgid "Close" +msgstr "بستن" + +msgid "API Connection Status" +msgstr "وضعیت اتصال API" + +msgid "Check your Hesabix API connection status" +msgstr "وضعیت اتصال API حسابیکس خود را بررسی کنید" + +msgid "Connection Status" +msgstr "وضعیت اتصال" + +msgid "API Server" +msgstr "سرور API" + +msgid "Business Information" +msgstr "اطلاعات کسب‌وکار" + +msgid "Your Hesabix business details" +msgstr "جزئیات کسب‌وکار حسابیکس شما" + +msgid "Business Name" +msgstr "نام کسب‌وکار" + +msgid "Subscription Plan" +msgstr "طرح اشتراک" + +msgid "Document Credit" +msgstr "اعتبار سند" + +msgid "Expiry Date" +msgstr "تاریخ انقضا" + +msgid "API Configuration" +msgstr "پیکربندی API" + +msgid "Configure your Hesabix API settings" +msgstr "تنظیمات API حسابیکس خود را پیکربندی کنید" + +msgid "Important Notes" +msgstr "نکات مهم" + +msgid "" +"To connect to Hesabix API and activate this plugin, you need to enter your " +"API key and login token here." +msgstr "" +"برای اتصال به API حسابیکس و فعال‌سازی این افزونه، باید کلید API و توکن ورود " +"خود را در اینجا وارد کنید." + +msgid "" +"If you use login token for Hesabix API connection, you don't need to enter " +"email and password." +msgstr "" +"اگر از توکن ورود برای اتصال API حسابیکس استفاده می‌کنید، نیازی به وارد کردن " +"ایمیل و رمز عبور نیست." + +msgid "" +"To find login token and API key, go to Settings > API Settings in Hesabix." +msgstr "" +"برای یافتن توکن ورود و کلید API، در حسابیکس به تنظیمات > تنظیمات API مراجعه " +"کنید." + +msgid "" +"If you want to connect another business to the plugin, first remove and " +"reinstall the plugin to clear the previous business connections." +msgstr "" +"اگر می‌خواهید کسب‌وکار دیگری را به افزونه متصل کنید، ابتدا افزونه را حذف و " +"مجدد نصب کنید تا ارتباطات کسب‌وکار قبلی پاک شود." + +msgid "Save Changes" +msgstr "ذخیره تغییرات" + +msgid "Warning" +msgstr "هشدار" + +msgid "" +"To connect another business to the plugin, first remove and reinstall the " +"plugin to clear the previous business connections." +msgstr "" +"برای اتصال کسب‌وکار دیگری به افزونه، ابتدا افزونه را حذف و مجدد نصب کنید تا " +"ارتباطات کسب‌وکار قبلی پاک شود." + +msgid "Test Connection" +msgstr "تست اتصال" + +msgid "Settings saved successfully" +msgstr "تنظیمات با موفقیت ذخیره شد" + +msgid "Connection successful!" +msgstr "اتصال موفقیت‌ آمیز بود!" + +msgid "Connection failed. Please check your API key and try again." +msgstr "اتصال ناموفق بود. لطفاً کلید API خود را بررسی کرده و دوباره تلاش کنید." + +msgid "API key not configured" +msgstr "کلید API پیکربندی نشده است" + +msgid "Error saving settings" +msgstr "خطا در ذخیره تنظیمات" + +msgid "Error testing connection" +msgstr "خطا در تست اتصال" + +msgid "Configure your Hesabix API connection and settings" +msgstr "اتصال و تنظیمات API حسابیکس را پیکربندی کنید" + +msgid "" +"Configure product sync and catalog options between WooCommerce and Hesabix" +msgstr "تنظیم گزینه‌های همگام‌سازی و کاتالوگ محصولات بین ووکامرس و حسابیکس" + +msgid "Changes synchronization completed successfully." +msgstr "همگام‌سازی تغییرات با موفقیت انجام شد." + +msgid "Product price and inventory synchronization completed successfully." +msgstr "همگام‌سازی قیمت و موجودی محصولات با موفقیت انجام شد." + +msgid "Error in product synchronization. Please check the log." +msgstr "خطا در همگام‌سازی محصولات. لطفاً لاگ را بررسی کنید." + +msgid "Order synchronization completed successfully." +msgstr "همگام‌سازی سفارشات با موفقیت انجام شد." + +msgid "%s orders added" +msgstr "%s سفارش افزوده شد" + +msgid "Error in order synchronization. Please enter a valid date." +msgstr "خطا در همگام‌سازی سفارشات. لطفاً تاریخ معتبر وارد کنید." + +msgid "Product update completed successfully." +msgstr "بروزرسانی محصولات با موفقیت انجام شد." + +msgid "Error in product update." +msgstr "خطا در بروزرسانی محصولات." + +msgid "Product update (filtered) completed successfully." +msgstr "بروزرسانی محصولات (فیلتر) با موفقیت انجام شد." + +msgid "Error in product update (filtered)." +msgstr "خطا در بروزرسانی محصولات (فیلتر)." + +msgid "" +"This page is for synchronizing information between the store and Hesabix. " +"Please check the settings before starting." +msgstr "" +"این صفحه برای همگام‌سازی اطلاعات بین فروشگاه و حسابیکس است. لطفاً قبل از " +"شروع، تنظیمات را بررسی کنید." + +msgid "Information Synchronization" +msgstr "همگام‌سازی اطلاعات" + +msgid "Store Products Count" +msgstr "تعداد محصولات فروشگاه" + +msgid "Hesabix Products Count" +msgstr "تعداد محصولات حسابیکس" + +msgid "Linked Products" +msgstr "محصولات لینک‌ شده" + +msgid "General Changes Synchronization" +msgstr "همگام‌سازی تغییرات کلی" + +msgid "Synchronize Changes" +msgstr "همگام‌سازی تغییرات" + +msgid "This operation synchronizes all changes (products, customers, orders)." +msgstr "این عملیات همه تغییرات (کالا، مشتری، سفارش) را همگام می‌کند." + +msgid "Product Price and Inventory Synchronization" +msgstr "همگام‌سازی قیمت و موجودی محصولات" + +msgid "Synchronize Price and Inventory" +msgstr "همگام‌سازی قیمت و موجودی" + +msgid "" +"Based on the products tab settings, product prices and inventory are " +"synchronized." +msgstr "بر اساس تنظیمات تب محصولات، قیمت و موجودی محصولات همگام می‌شود." + +msgid "Order Synchronization (Time Range)" +msgstr "همگام‌سازی سفارشات (بازه زمانی)" + +msgid "to" +msgstr "تا" + +msgid "Synchronize Orders" +msgstr "همگام‌سازی سفارشات" + +msgid "" +"Store orders that are not registered in Hesabix are checked and registered " +"in the selected range." +msgstr "" +"سفارشات فروشگاه که در حسابیکس ثبت نشده‌اند، در بازه انتخابی بررسی و ثبت " +"می‌شوند." + +msgid "Update Hesabix Products Based on Woocommerce" +msgstr "بروزرسانی محصولات حسابیکس بر اساس ووکامرس" + +msgid "Update Hesabix Products" +msgstr "بروزرسانی محصولات حسابیکس" + +msgid "" +"Product features such as name and price in Hesabix are updated based on the " +"store (inventory does not change)." +msgstr "" +"ویژگی محصولات مثل نام و قیمت در حسابیکس، بر اساس فروشگاه بروزرسانی می‌شود " +"(موجودی تغییر نمی‌کند)." + +msgid "Error" +msgstr "خطا" + +msgid "Operation in Progress..." +msgstr "عملیات در حال انجام..." + +msgid "Please wait while the synchronization is being completed." +msgstr "لطفاً منتظر بمانید تا همگام‌سازی کامل شود." + +msgid "Quick Select:" +msgstr "انتخاب سریع:" + +msgid "Last 7 Days" +msgstr "۷ روز اخیر" + +msgid "Last 30 Days" +msgstr "۳۰ روز اخیر" + +msgid "Last 3 Months" +msgstr "۳ ماه اخیر" + +msgid "Custom Range" +msgstr "بازه دلخواه" + +msgid "From Date:" +msgstr "از تاریخ:" + +msgid "To Date:" +msgstr "تا تاریخ:" + +msgid "Please enter date in Jalali format (YYYY/MM/DD)" +msgstr "لطفاً تاریخ را به فرمت جلالی وارد کنید (YYYY/MM/DD)" + +msgid "Invalid Jalali date format" +msgstr "فرمت تاریخ جلالی نامعتبر است" + +msgid "End date must be after start date." +msgstr "تاریخ پایان باید بعد از تاریخ شروع باشد." + +msgid "Selected Range:" +msgstr "بازه انتخاب شده:" + +msgid "" +"Customers existing in the store that are not registered in Hesabix will be " +"checked and registered in Hesabix." +msgstr "" +"مشتریانی که در فروشگاه وجود دارند اما در حسابیکس ثبت نشده‌اند، بررسی و در " +"حسابیکس ثبت خواهند شد." + +msgid "" +"Store orders that are not registered in Hesabix are checked and registered " +"in the selected date range. Choose a preset option or select a custom date " +"range." +msgstr "" +"سفارشات فروشگاه که در حسابیکس ثبت نشده‌اند، در بازه زمانی انتخاب شده بررسی و " +"ثبت می‌شوند. یک گزینه از پیش تعریف شده انتخاب کنید یا بازه زمانی دلخواه خود " +"را انتخاب کنید." + +msgid "Update Woocommerce Products Based on Hesabix" +msgstr "بروزرسانی محصولات ووکامرس بر اساس حسابیکس" + +msgid "Update Woocommerce Products" +msgstr "بروزرسانی محصولات ووکامرس" + +msgid "" +"Configure when invoices should be created in Hesabix and when return " +"invoices should be generated for orders." +msgstr "" +"تنظیم کنید که فاکتورها چه زمانی در حسابیکس ایجاد شوند و چه زمانی برای " +"سفارشات فاکتور برگشت تولید شود." + +msgid "Important Notice" +msgstr "اطلاعیه مهم" + +msgid "" +"If you choose to save shipping costs as a service, you must first create a " +"service in Hesabix and enter its code in the Freight Service Code field." +msgstr "" +"اگر هزینه حمل و نقل را به عنوان خدمت ذخیره کنید، ابتدا باید خدمتی در حسابیکس " +"ایجاد کنید و کد آن را در فیلد کد خدمت حمل و نقل وارد کنید." + +msgid "The \"Save as Service\" option is for tax compliance systems." +msgstr "گزینه \"ذخیره به عنوان خدمت\" برای سیستم‌های انطباق مالیاتی است." + +msgid "" +"Please ensure this field is correctly entered to avoid invoice creation " +"issues." +msgstr "" +"لطفاً اطمینان حاصل کنید که این فیلد به درستی وارد شده تا از مشکلات ایجاد " +"فاکتور جلوگیری شود." + +msgid "Configure invoice generation and freight settings" +msgstr "تنظیم تولید فاکتور و تنظیمات حمل و نقل" + +msgid "Pirouz" +msgstr "پیروز" + +msgid "Update Hesabix Customers" +msgstr "بروزرسانی مشتریان حسابیکس" + +msgid "days" +msgstr "روز" + +msgid "" +"Product features such as name and price in Woocommerce are updated based on " +"Hesabix (inventory does not change)." +msgstr "" +"ویژگی‌های محصول مانند نام و قیمت در ووکامرس بر اساس حسابیکس بروزرسانی می‌شود " +"(موجودی تغییر نمی‌کند)." + +msgid "Configure customer management and additional checkout fields" +msgstr "تنظیم مدیریت مشتریان و فیلدهای اضافی تسویه حساب" + +msgid "Basic Settings" +msgstr "تنظیمات پایه" + +msgid "" +"Configure additional fields that will be displayed on the checkout page for " +"customer information collection." +msgstr "" +"فیلدهای اضافی که در صفحه تسویه حساب برای جمع‌آوری اطلاعات مشتری نمایش داده " +"می‌شوند را تنظیم کنید." + +msgid "Field Source" +msgstr "منبع فیلد" + +msgid "Additional Checkout Fields" +msgstr "فیلدهای اضافی تسویه حساب" + +msgid "Customer Settings" +msgstr "تنظیمات مشتری" + +msgid "Save Shipping Costs" +msgstr "ذخیره هزینه حمل و نقل" + +msgid "Don't Save" +msgstr "ذخیره نکن" + +msgid "Save as Service" +msgstr "ذخیره به عنوان خدمت" + +msgid "Choose how shipping costs should be handled in invoices" +msgstr "انتخاب کنید که هزینه حمل و نقل چگونه در فاکتورها مدیریت شود" + +msgid "Enter Freight Service Code" +msgstr "کد خدمت حمل و نقل را وارد کنید" + +msgid "" +"Required when \"Save as Service\" is selected. Create this service in " +"Hesabix first." +msgstr "" +"هنگامی که \"ذخیره به عنوان خدمت\" انتخاب شده، الزامی است. ابتدا این خدمت را " +"در حسابیکس ایجاد کنید." + +msgid "Please read these warnings carefully" +msgstr "لطفاً این هشدارها را با دقت بخوانید" + +msgid "Code Management" +msgstr "مدیریت کد" + +msgid "" +"The plugin uses product codes, customer codes, and invoice numbers for " +"identification. Do not change these codes in Hesabix after they have been " +"created." +msgstr "" +"این افزونه از کدهای محصول، کدهای مشتری و شماره‌های فاکتور برای شناسایی " +"استفاده می‌کند. پس از ایجاد این کدها در حسابیکس، آن‌ها را تغییر ندهید." + +msgid "Plugin Removal" +msgstr "حذف افزونه" + +msgid "" +"Removing the plugin from WordPress will delete the relationship table from " +"the database and all connections will be lost." +msgstr "" +"حذف افزونه از وردپرس جدول روابط را از پایگاه داده حذف می‌کند و تمام اتصالات " +"از دست خواهد رفت." + +msgid "Need Help?" +msgstr "نیاز به کمک دارید؟" + +msgid "Get support and documentation" +msgstr "دریافت پشتیبانی و مستندات" + +msgid "Complete Guide" +msgstr "راهنمای کامل" + +msgid "Go to Hesabix" +msgstr "رفتن به حسابیکس" + +msgid "Visit Website" +msgstr "بازدید از وب‌سایت" + +msgid "Important Warnings" +msgstr "هشدارهای مهم" + +msgid "This page is for advanced plugin settings." +msgstr "این صفحه برای تنظیمات پیشرفته افزونه می‌باشد." + +msgid "" +"Number of concurrent requests for synchronizing Hesabix products in " +"WooCommerce" +msgstr "تعداد درخواست همزمان برای همگام‌سازی محصولات حسابیکس در ووکامرس" + +msgid "Plugin default: 100" +msgstr "پیش‌فرض افزونه: 100" + +msgid "Failed to save settings" +msgstr "خطا در ذخیره تنظیمات" + +msgid "Customer fields saved successfully" +msgstr "فیلدهای مشتری با موفقیت ذخیره شد" + +msgid "Hesabix Plugin developed with" +msgstr "افزونه حسابیکس با" + +msgid "by" +msgstr "توسط" + +msgid "Mohammad Rezai" +msgstr "محمد رضائی" + +msgid "Online Store Customers" +msgstr "مشتریان فروشگاه آن‌لاین" + +msgid "Hesabix Settings" +msgstr "تنظیمات حسابیکس" + +msgid "Manual Product Synchronization with Hesabix" +msgstr "همسان سازی دستی کالاهای فروشگاه با حسابیکس" + +msgid "View Important Tips" +msgstr "مشاهده نکات مهم" + +msgid "The following codes were not found in Hesabix:" +msgstr "کدهای زیر در حسابیکس پیدا نشد:" + +msgid "Attention!" +msgstr "توجه!" + +msgid "Save changes for each page before going to the next page." +msgstr "تغییرات هر صفحه را ذخیره کنید و سپس به صفحه بعد بروید." + +msgid "Hesabix code is the 6-digit code (accounting item code)." +msgstr "کد حسابیکس همان کد 6 رقمی (کد حسابداری کالا) است." + +msgid "Make sure the item is defined in Hesabix." +msgstr "از وجود تعریف کالا در حسابیکس اطمینان حاصل کنید." + +msgid "" +"This page is for when you have already defined an item in both the store and " +"Hesabix but there is no connection between them. You can manually establish " +"this connection using this page." +msgstr "" +"این صفحه برای زمانی است که شما از قبل یک کالا را هم در فروشگاه و هم در " +"حسابیکس تعریف کرده اید اما اتصالی بین آنها وجود ندارد. به کمک این صفحه می " +"توانید این اتصال را بصورت دستی برقرار کنید." + +msgid "" +"For convenience, this table is sorted by product name, so also sort the list " +"of items in Hesabix by name and start entering the corresponding codes in " +"this table." +msgstr "" +"برای راحتی کار، این جدول بر اساس نام محصول مرتب سازی شده است، بنابراین در " +"حسابیکس نیز لیست کالاها را بر اساس نام مرتب سازی کرده و از روی آن شروع به " +"وارد کردن کدهای متناظر در این جدول نمایید." + +msgid "Product Name" +msgstr "نام کالا" + +msgid "Product ID" +msgstr "شناسه محصول" + +msgid "Hesabix Code" +msgstr "کد حسابیکس" + +msgid "records" +msgstr "رکورد" + +msgid "pages" +msgstr "صفحه" + +msgid "Current page:" +msgstr "صفحه جاری:" + +msgid "Go" +msgstr "برو" + +msgid "rows per page" +msgstr "ردیف در هر صفحه" + +msgid "< Previous page" +msgstr "< صفحه قبل" + +msgid "Next page >" +msgstr "صفحه بعد >" + +msgid "Duplicate Product Codes" +msgstr "کد محصولات تکراری" + +msgid "Attribute ID" +msgstr "شناسه متغیر" + +msgid "Hesabix Plugin Tools" +msgstr "ابزارهای افزونه حسابیکس" + +msgid "Delete Plugin Data" +msgstr "حذف دیتای افزونه" + +msgid "Install Plugin Data" +msgstr "نصب دیتای افزونه" + +msgid "Freight service code is not defined" +msgstr "کد هزینه حمل و نقل تعریف نشده است" + +msgid "Freight Cost" +msgstr "هزینه حمل و نقل" + +msgid "Cash in Transit not found in Hesabix" +msgstr "وجوه در راه در حسابیکس یافت نشد" + +msgid "Cash in Transit" +msgstr "وجوه در راه" + +msgid "Range ID should not be more than 200" +msgstr "بازه ID نباید بیشتر از 200 عدد باشد" + +msgid "Please enter a valid product code" +msgstr "کد کالای معتبر وارد نمایید" + +msgid "Disconnected" +msgstr "قطع" + +msgid "Comprehensive Hesabix System Information" +msgstr "اطلاعات جامع سیستم حسابیکس" + +msgid "Main Information" +msgstr "اطلاعات اصلی" + +msgid "Plugin Version:" +msgstr "نسخه افزونه:" + +msgid "Connection Status:" +msgstr "وضعیت اتصال:" + +msgid "Order Pending Payment" +msgstr "سفارش در انتظار پرداخت" + +msgid "Order Processing" +msgstr "سفارش در حال پردازش" + +msgid "Order On Hold" +msgstr "سفارش در حالت انتظار" + +msgid "Order Completed" +msgstr "سفارش تکمیل شده" + +msgid "Order Cancelled" +msgstr "سفارش لغو شده" + +msgid "Order Refunded" +msgstr "سفارش بازپرداخت شده" + +msgid "Order Failed" +msgstr "سفارش ناموفق" + +msgid "Order Draft" +msgstr "سفارش پیش‌نویس" + +msgid "Order Status" +msgstr "وضعیت سفارش" + +msgid "Freight cost is not saved in the invoice." +msgstr "هزینه حمل و نقل در فاکتور ذخیره نمی‌شود" + +msgid "Freight cost is saved as a product." +msgstr "هزینه حمل و نقل به عنوان بار ذخیره می‌شود" + +msgid "Freight cost is saved as a service." +msgstr "هزینه حمل و نقل به عنوان خدمت ذخیره می‌شود" + +msgid "Persons:" +msgstr "اشخاص :" + +msgid "Customer" +msgstr "مشتری" + +msgid "Marketer" +msgstr "بازاریاب" + +msgid "Employee" +msgstr "کارمند" + +msgid "Supplier" +msgstr "تامین‌کننده" + +msgid "Colleague" +msgstr "همکار" + +msgid "Salesman" +msgstr "فروشنده" + +msgid "Business Name:" +msgstr "نام کسب‌وکار:" + +msgid "Server Information" +msgstr "اطلاعات سرور" + +msgid "PHP Version:" +msgstr "نسخه PHP:" + +msgid "WordPress Version:" +msgstr "نسخه وردپرس:" + +msgid "WooCommerce Version:" +msgstr "نسخه ووکامرس:" + +msgid "MySQL Version:" +msgstr "نسخه MySQL:" + +msgid "Server Settings" +msgstr "تنظیمات سرور" + +msgid "Maximum Execution Time:" +msgstr "حداکثر زمان اجرا:" + +msgid "seconds" +msgstr "ثانیه" + +msgid "Memory Limit:" +msgstr "محدودیت حافظه:" + +msgid "Maximum Upload:" +msgstr "حداکثر آپلود:" + +msgid "Maximum POST:" +msgstr "حداکثر POST:" + +msgid "" +"Number of concurrent requests for synchronizing WooCommerce products in " +"Hesabix" +msgstr "تعداد درخواست همزمان برای همگام‌سازی محصولات ووکامرس در حسابیکس" + +msgid "Select" +msgstr "انتخاب کنید" + +msgid "Plugin default: 500" +msgstr "پیش‌فرض افزونه: 500" + +msgid "Orders synchronized successfully." +msgstr "همگام‌سازی سفارشات با موفقیت انجام شد." + +msgid "Number of concurrent requests for importing products" +msgstr "تعداد درخواست همزمان برای ایمپورت محصولات" + +msgid "Number of concurrent requests for exporting products" +msgstr "تعداد درخواست همزمان برای اکسپورت محصولات" + +msgid "Number of concurrent requests for exporting initial product inventory" +msgstr "تعداد درخواست همزمان برای اکسپورت موجودی اولیه محصولات" + +msgid "" +"By clicking the \"Delete All Logs\" button, all log files will be deleted." +msgstr "با کلیک روی دکمه \"حذف تمام لاگ‌ها\"، تمام فایل‌های لاگ حذف خواهند شد." + +msgid "" +"To delete the current log, click the \"Delete Current Log\" button when the " +"log file is selected." +msgstr "" +"برای حذف لاگ فعلی، وقتی فایل لاگ انتخاب شده روی دکمه \"حذف لاگ فعلی\" کلیک " +"کنید." + +msgid "The log history list displays logs from the last 10 days." +msgstr "لیست تاریخچه لاگ، لاگ‌های 10 روز گذشته را نمایش می‌دهد." + +msgid "Delete All Logs" +msgstr "حذف تمام لاگ‌ها" + +msgid "Download Current Log" +msgstr "دانلود لاگ فعلی" + +msgid "Delete Current Log" +msgstr "حذف لاگ فعلی" + +msgid "Log History (Last 10 Days)" +msgstr "تاریخچه لاگ (10 روز گذشته)" + +msgid "No logs found." +msgstr "هیچ لاگی یافت نشد." + +msgid "Log Content" +msgstr "محتوای لاگ" + +msgid "Loading..." +msgstr "در حال بارگذاری..." + +msgid "Error fetching log!" +msgstr "خطا در دریافت لاگ!" + +msgid "Error connecting to server!" +msgstr "خطا در اتصال به سرور!" + +msgid "log loaded successfully." +msgstr "لاگ با موفقیت بارگذاری شد." + +msgid "Are you sure you want to delete this log?" +msgstr "آیا مطمئن هستید که می‌خواهید این لاگ را حذف کنید؟" + +msgid "Log deleted." +msgstr "لاگ حذف شد." + +msgid "Log deleted successfully." +msgstr "لاگ با موفقیت حذف شد." + +msgid "Error deleting log!" +msgstr "خطا در حذف لاگ!" + +msgid "Are you sure you want to delete all logs?" +msgstr "آیا مطمئن هستید که می‌خواهید تمام لاگ‌ها را حذف کنید؟" + +msgid "All logs deleted." +msgstr "تمام لاگ‌ها حذف شدند." + +msgid "All logs deleted successfully." +msgstr "تمام لاگ‌ها با موفقیت حذف شدند." + +msgid "Error deleting all logs!" +msgstr "خطا در حذف تمام لاگ‌ها!" + +msgid "Custom Address" +msgstr "آدرس سفارشی" + +msgid "Custom API Address" +msgstr "آدرس API سفارشی" + +msgid "Enter your custom API address (e.g., your-domain.com)" +msgstr "آدرس API سفارشی خود را وارد کنید (مثال: your-domain.com)" + +msgid "API Connection Required" +msgstr "اتصال API مورد نیاز است" + +msgid "" +"This tab requires a valid API connection. Please configure your API settings " +"from the API tab first." +msgstr "" +"این تب نیازمند اتصال API معتبر است. لطفا ابتدا تنظیمات API خود را از تب API " +"پیکربندی کنید." + +msgid "Go to API Settings" +msgstr "رفتن به تنظیمات API" + +msgid "Customers successfully updated in Hesabix." +msgstr "مشتریان با موفقیت در حسابیکس بروزرسانی شدند." + +msgid "Error updating customers: " +msgstr "خطا در بروزرسانی مشتریان: " + +msgid "Additional checkout fields configuration" +msgstr "تنظیمات فیلدهای اضافی تسویه حساب" + +msgid "Show national code field" +msgstr "نمایش فیلد کد ملی" + +msgid "Make national code field required" +msgstr "اجباری کردن فیلد کد ملی" + +msgid "Enter meta code" +msgstr "کد متا را وارد کنید" + +msgid "Meta code for national code field" +msgstr "کد متا برای فیلد کد ملی" + +msgid "Show economic code field" +msgstr "نمایش فیلد کد اقتصادی" + +msgid "Make economic code field required" +msgstr "اجباری کردن فیلد کد اقتصادی" + +msgid "Meta code for economic code field" +msgstr "کد متا برای فیلد کد اقتصادی" + +msgid "Show registration number field" +msgstr "نمایش فیلد شماره ثبت" + +msgid "Make registration number field required" +msgstr "اجباری کردن فیلد شماره ثبت" + +msgid "Meta code for registration number field" +msgstr "کد متا برای فیلد شماره ثبت" + +msgid "Show website field" +msgstr "نمایش فیلد وب‌سایت" + +msgid "Make website field required" +msgstr "اجباری کردن فیلد وب‌سایت" + +msgid "Meta code for website field" +msgstr "کد متا برای فیلد وب‌سایت" + +msgid "Save Additional Fields" +msgstr "ذخیره فیلدهای اضافی" + +msgid "Failed to save customer fields" +msgstr "ذخیره فیلدهای مشتریان ناموفق بود" + +msgid "Error saving customer fields: " +msgstr "خطا در ذخیره فیلدهای مشتریان: " + +msgid "changes synced successfully" +msgstr "تغییرات با موفقیت همگام‌سازی شد" + +msgid "Error syncing prices and inventory. Please check the logs." +msgstr "خطا در همگام‌سازی قیمت‌ها و موجودی. لطفا لاگ‌ها را بررسی کنید." + +msgid "Prices and inventory synced successfully" +msgstr "قیمت‌ها و موجودی با موفقیت همگام‌سازی شد" + +msgid "Error updating products. Please check the logs." +msgstr "خطا در بروزرسانی محصولات. لطفا لاگ‌ها را بررسی کنید." + +msgid "Products updated successfully" +msgstr "محصولات با موفقیت بروزرسانی شدند" + +msgid "Security check failed" +msgstr "بررسی امنیتی ناموفق بود" + +msgid "Invalid nonce" +msgstr "نونس نامعتبر" diff --git a/languages/hesabix.pot b/languages/hesabix.pot new file mode 100644 index 0000000..05b0ea2 --- /dev/null +++ b/languages/hesabix.pot @@ -0,0 +1,1605 @@ +# Copyright (C) 2025 Mohammad Rezai +# This file is distributed under the GPL-3.0+. +msgid "" +msgstr "" +"Project-Id-Version: Hesabix: WooCommerce 1.0.0\n" +"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/hesabixWCPlugin\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"POT-Creation-Date: 2025-08-05T11:01:45+00:00\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"X-Generator: WP-CLI 2.12.0\n" +"X-Domain: hesabix\n" + +#. Plugin Name of the plugin +#: hesabix.php +#: admin/partials/hesabix-admin-display.php:238 +msgid "Hesabix: WooCommerce" +msgstr "" + +#. Plugin URI of the plugin +#: hesabix.php +msgid "https://hesabix.ir/" +msgstr "" + +#. Description of the plugin +#: hesabix.php +msgid "Connect Hesabix Online Accounting to WooCommerce." +msgstr "" + +#. Author of the plugin +#: hesabix.php +#: hesabix.php:60 +msgid "Mohammad Rezai" +msgstr "" + +#. Author URI of the plugin +#: hesabix.php +msgid "https://pirouz.xyz" +msgstr "" + +#: admin/class-hesabix-admin.php:178 +#, php-format +msgid "Hesabix Plugin requires the %s to work!" +msgstr "" + +#: admin/class-hesabix-admin.php:178 +msgid "WooCommerce" +msgstr "" + +#: admin/class-hesabix-admin.php:183 +msgid "Hesabix Plugin need to connect to Hesabix Accounting, Please check the API credential!" +msgstr "" + +#: admin/class-hesabix-admin.php:188 +#: admin/partials/hesabix-admin-setting.php:2038 +#: includes/class-hesabix-webhook.php:166 +msgid "Cannot connect to Hesabix. Business expired." +msgstr "" + +#: admin/class-hesabix-admin.php:193 +msgid "Hesabix Plugin cannot works! because WooCommerce currency in not match with Hesabix." +msgstr "" + +#: admin/class-hesabix-admin.php:202 +msgid "Error: Select maximum 10 orders. Due to some limitations in Hesabix API, sending too many requests in one minute is not possible." +msgstr "" + +#: admin/class-hesabix-admin.php:206 +msgid "Selected orders invoices have been saved. Number of saved invoices: " +msgstr "" + +#: admin/class-hesabix-admin.php:325 +msgid "changes synced successfully" +msgstr "" + +#: admin/class-hesabix-admin.php:345 +msgid "Error syncing prices and inventory. Please check the logs." +msgstr "" + +#: admin/class-hesabix-admin.php:350 +msgid "Prices and inventory synced successfully" +msgstr "" + +#: admin/class-hesabix-admin.php:370 +msgid "Orders synchronized successfully." +msgstr "" + +#: admin/class-hesabix-admin.php:394 +#: admin/class-hesabix-admin.php:422 +msgid "Error updating products. Please check the logs." +msgstr "" + +#: admin/class-hesabix-admin.php:399 +#: admin/class-hesabix-admin.php:427 +msgid "Products updated successfully" +msgstr "" + +#: admin/class-hesabix-admin.php:624 +msgid "Invoice in Hesabix" +msgstr "" + +#: admin/class-hesabix-admin.php:625 +#: admin/class-hesabix-admin.php:661 +#: admin/class-hesabix-admin.php:681 +msgid "Submit Invoice" +msgstr "" + +#: admin/class-hesabix-admin.php:698 +msgid "Submit Invoice in Hesabix" +msgstr "" + +#: admin/class-hesabix-admin.php:742 +msgid "Contact Code in Hesabix" +msgstr "" + +#: admin/class-hesabix-admin.php:748 +msgid "The contact code of this user in Hesabix, if you want to map this user to a contact in Hesabix, enter the Contact code." +msgstr "" + +#: admin/class-hesabix-admin.php:970 +#: admin/class-hesabix-admin.php:1082 +msgid "The new Item code already used for another Item" +msgstr "" + +#: admin/class-hesabix-admin.php:1061 +msgid "Hesabix base item code" +msgstr "" + +#: admin/class-hesabix-admin.php:1063 +msgid "The base Item code of this product in Hesabix, if you want to map this product to another item in Hesabix, enter the new Item code." +msgstr "" + +#: admin/class-hesabix-admin.php:1113 +msgid "Hesabix variable item code" +msgstr "" + +#: admin/class-hesabix-admin.php:1115 +msgid "The variable Item code of this product variable in Hesabix, if you want to map this product to another item in Hesabix, enter the new Item code." +msgstr "" + +#: admin/class-hesabix-admin.php:1141 +#: admin/partials/hesabix-admin-display.php:13 +#: admin/partials/hesabix-admin-display.php:235 +msgid "Hesabix" +msgstr "" + +#: admin/class-hesabix-admin.php:1599 +#: admin/class-hesabix-admin.php:1662 +#: admin/partials/hesabix-admin-setting.php:855 +msgid "National code" +msgstr "" + +#: admin/class-hesabix-admin.php:1600 +msgid "please enter your National code" +msgstr "" + +#: admin/class-hesabix-admin.php:1610 +#: admin/class-hesabix-admin.php:1666 +#: admin/partials/hesabix-admin-setting.php:879 +msgid "Economic code" +msgstr "" + +#: admin/class-hesabix-admin.php:1611 +msgid "please enter your Economic code" +msgstr "" + +#: admin/class-hesabix-admin.php:1620 +#: admin/class-hesabix-admin.php:1669 +#: admin/partials/hesabix-admin-setting.php:905 +msgid "Registration number" +msgstr "" + +#: admin/class-hesabix-admin.php:1621 +msgid "please enter your Registration number" +msgstr "" + +#: admin/class-hesabix-admin.php:1631 +#: admin/class-hesabix-admin.php:1672 +#: admin/partials/hesabix-admin-setting.php:929 +msgid "Website" +msgstr "" + +#: admin/class-hesabix-admin.php:1632 +msgid "please enter your Website address" +msgstr "" + +#: admin/class-hesabix-admin.php:1699 +#: admin/partials/hesabix-admin-setting.php:279 +msgid "Connected" +msgstr "" + +#: admin/class-hesabix-admin.php:1699 +msgid "Not Connected" +msgstr "" + +#: admin/class-hesabix-admin.php:1700 +msgid "Total Products" +msgstr "" + +#: admin/class-hesabix-admin.php:1701 +msgid "Total Customers" +msgstr "" + +#: admin/class-hesabix-admin.php:1702 +msgid "Total Orders" +msgstr "" + +#: admin/class-hesabix-admin.php:1703 +msgid "Hesabix Status" +msgstr "" + +#: admin/class-hesabix-admin.php:1799 +#: admin/class-hesabix-admin.php:1805 +msgid "Failed to check for updates" +msgstr "" + +#: admin/class-hesabix-admin.php:1811 +msgid "Error checking for updates" +msgstr "" + +#: admin/class-hesabix-admin.php:1835 +#: admin/partials/hesabix-admin-setting.php:2455 +#: admin/partials/hesabix-admin-setting.php:2540 +#: admin/partials/hesabix-admin-setting.php:2578 +#: admin/partials/hesabix-admin-setting.php:2608 +msgid "Settings saved successfully" +msgstr "" + +#: admin/class-hesabix-admin.php:1852 +msgid "API key not configured" +msgstr "" + +#: admin/class-hesabix-admin.php:1859 +msgid "Connection failed. Please check your API key and try again." +msgstr "" + +#: admin/class-hesabix-admin.php:1864 +msgid "Connection successful!" +msgstr "" + +#: admin/class-hesabix-admin.php:1913 +msgid "API Connection Required" +msgstr "" + +#: admin/class-hesabix-admin.php:1914 +msgid "This tab requires a valid API connection. Please configure your API settings from the API tab first." +msgstr "" + +#: admin/class-hesabix-admin.php:1918 +msgid "Go to API Settings" +msgstr "" + +#: admin/class-hesabix-admin.php:2006 +msgid "Customers successfully updated in Hesabix." +msgstr "" + +#: admin/class-hesabix-admin.php:2018 +msgid "Error updating customers: " +msgstr "" + +#: admin/class-hesabix-admin.php:2057 +msgid "Customer fields saved successfully" +msgstr "" + +#: admin/class-hesabix-admin.php:2059 +msgid "Failed to save customer fields" +msgstr "" + +#: admin/class-hesabix-admin.php:2063 +msgid "Error saving customer fields: " +msgstr "" + +#: admin/partials/hesabix-admin-display.php:14 +msgid "Hesabix Settings" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:52 +msgid "Duplicate Product Codes" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:58 +msgid "Hesabix Code" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:59 +msgid "Product ID" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:60 +msgid "Attribute ID" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:84 +msgid "Hesabix Plugin Tools" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:88 +msgid "Delete Plugin Data" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:91 +msgid "Install Plugin Data" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:163 +msgid "Home" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:164 +msgid "API" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:165 +msgid "Catalog" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:166 +msgid "Customers" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:167 +msgid "Invoice" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:168 +msgid "Sync" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:169 +msgid "Log" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:170 +#: admin/partials/hesabix-admin-setting.php:257 +msgid "Extra Settings" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:218 +msgid "Hesabix Plugin requires the WooCommerce to work!" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:219 +msgid "Please install/activate woocommerce and try again" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:239 +msgid "Connect Hesabix Online Accounting to WooCommerce" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:242 +#: admin/partials/hesabix-admin-display.php:263 +#, php-format +msgid "Version %s" +msgstr "" + +#: admin/partials/hesabix-admin-display.php:248 +#: admin/partials/hesabix-admin-display.php:271 +msgid "Checking..." +msgstr "" + +#: admin/partials/hesabix-admin-display.php:257 +#: admin/partials/hesabix-admin-display.php:280 +msgid "Plugin Guide" +msgstr "" + +#: admin/partials/hesabix-admin-functions.php:45 +msgid "date is not in fiscal year" +msgstr "" + +#: admin/partials/hesabix-admin-functions.php:49 +#: admin/partials/hesabix-admin-functions.php:52 +#: admin/partials/hesabix-admin-functions.php:55 +msgid "Cannot connect to Hesabix for get FiscalDate." +msgstr "" + +#: admin/partials/hesabix-admin-functions.php:398 +msgid "Shipping method" +msgstr "" + +#: admin/partials/hesabix-admin-functions.php:406 +msgid "Freight service code is not defined" +msgstr "" + +#: admin/partials/hesabix-admin-functions.php:419 +msgid "Freight Cost" +msgstr "" + +#: admin/partials/hesabix-admin-functions.php:428 +msgid "Freight method" +msgstr "" + +#: admin/partials/hesabix-admin-functions.php:673 +msgid "Cash in Transit not found in Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-functions.php:1263 +msgid "no orders found" +msgstr "" + +#: admin/partials/hesabix-admin-functions.php:1811 +msgid "Range ID should not be more than 200" +msgstr "" + +#: admin/partials/hesabix-admin-functions.php:1814 +msgid "Please enter a valid product code" +msgstr "" + +#: admin/partials/hesabix-admin-functions.php:2093 +#: admin/partials/hesabix-admin-functions.php:2097 +#: admin/partials/hesabix-admin-functions.php:2102 +msgid "please enter a valid national code" +msgstr "" + +#: admin/partials/hesabix-admin-functions.php:2131 +msgid "please enter a valid Website URL" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:43 +msgid "Current Statistics" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:45 +msgid "Overview of your store and Hesabix integration" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:98 +msgid "Setup Guide" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:99 +msgid "Follow these steps to complete the integration" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:106 +msgid "Register in Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:107 +msgid "Visit hesabix.ir and create a free account. Choose your business and get your API keys from the settings menu." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:114 +msgid "Configure API Settings" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:115 +msgid "Go to the API tab and enter your Hesabix API key, business ID, and fiscal year information." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:122 +msgid "Configure Sync Settings" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:123 +msgid "Set up your catalog, customer, and invoice synchronization preferences in their respective tabs." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:130 +msgid "Start Synchronization" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:131 +msgid "Use the sync tab to manually synchronize your existing data or let the automatic sync handle new data." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:139 +msgid "Important Warnings" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:140 +msgid "Please read these warnings carefully" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:149 +msgid "Code Management" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:152 +msgid "The plugin uses product codes, customer codes, and invoice numbers for identification. Do not change these codes in Hesabix after they have been created." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:162 +msgid "Plugin Removal" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:165 +msgid "Removing the plugin from WordPress will delete the relationship table from the database and all connections will be lost." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:173 +msgid "Need Help?" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:174 +msgid "Get support and documentation" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:189 +msgid "Complete Guide" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:202 +msgid "Go to Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:215 +msgid "Visit Website" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:223 +msgid "Plugin Tutorial Video" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:237 +msgid "Enable or Disable Debug Mode" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:255 +msgid "This page is for advanced plugin settings." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:270 +#: admin/partials/hesabix-admin-setting.php:1010 +msgid "Inactive" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:279 +msgid "Disconnected" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:304 +msgid "Comprehensive Hesabix System Information" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:309 +msgid "Main Information" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:312 +msgid "Plugin Version:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:316 +msgid "Connection Status:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:323 +msgid "Business Name:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:331 +msgid "Server Information" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:334 +msgid "PHP Version:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:338 +msgid "WordPress Version:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:342 +msgid "WooCommerce Version:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:346 +msgid "MySQL Version:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:353 +msgid "Server Settings" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:357 +msgid "Maximum Execution Time:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:359 +msgid "seconds" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:362 +msgid "Memory Limit:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:366 +msgid "Maximum Upload:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:370 +msgid "Maximum POST:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:384 +msgid "Number of concurrent requests for synchronizing WooCommerce products in Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:389 +#: admin/partials/hesabix-admin-setting.php:422 +#: admin/partials/hesabix-admin-setting.php:448 +#: admin/partials/hesabix-admin-setting.php:463 +#: admin/partials/hesabix-admin-setting.php:488 +msgid "Select" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:412 +#: admin/partials/hesabix-admin-setting.php:479 +#: admin/partials/hesabix-admin-setting.php:510 +msgid "Plugin default: 500" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:416 +msgid "Number of concurrent requests for synchronizing Hesabix products in WooCommerce" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:443 +msgid "تعداد درخواست همزمان برای ایمپورت محصولات" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:454 +msgid "Plugin default: 100" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:458 +msgid "تعداد درخواست همزمان برای اکسپورت محصولات" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:483 +msgid "تعداد درخواست همزمان برای اکسپورت موجودی اولیه محصولات" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:519 +#: admin/partials/hesabix-admin-setting.php:689 +#: admin/partials/hesabix-admin-setting.php:797 +#: admin/partials/hesabix-admin-setting.php:1068 +#: admin/partials/hesabix-admin-setting.php:1239 +msgid "Save Changes" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:540 +#: admin/partials/hesabix-admin-setting.php:673 +msgid "Catalog Settings" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:547 +msgid "Update Price" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:548 +msgid "Update Price after change in Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:555 +msgid "Update Quantity" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:556 +msgid "Update Quantity after change in Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:563 +msgid "Update product's quantity based on" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:571 +msgid "Remove The Titles for Attributes When Saving Product To Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:579 +msgid "Do not update purchase and sales titles in hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:587 +msgid "Do not submit product in Hesabix automatically by saving product in woocommerce" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:595 +msgid "Do not update product price in Hesabix by editing product in woocommerce" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:603 +msgid "Do not update product barcode in Hesabix by saving product in woocommerce" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:611 +msgid "Do not update product category in Hesabix by saving product in woocommerce" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:619 +msgid "Do not update product code in Hesabix by saving product in woocommerce" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:627 +msgid "Show Hesabix ID in Products Page" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:635 +msgid "Show Hesabix Code in Woocommerce Excel Export" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:643 +msgid "Set Special Sale as Discount in invoice" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:650 +msgid "The Sale price does not change" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:651 +msgid "The Sale price gets removed" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:652 +msgid "The sale price get changes in proportion to the regular price" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:655 +msgid "Update sale price" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:675 +msgid "Configure product sync and catalog options between WooCommerce and Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:708 +msgid "Customers Settings" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:715 +msgid "Update Customer Address" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:716 +msgid "Choose when update Customer address in Hesabix." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:720 +msgid "Use first customer address" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:721 +msgid "update address with Invoice address" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:722 +msgid "update address with Delivery address" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:727 +msgid "Customer's Group" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:728 +msgid "Enter a Customer's Group in Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:735 +msgid "Save Customer's group" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:736 +msgid "Automatically save Customer's group in hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:742 +msgid "Customer's detail auto save and update" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:743 +msgid "Save and update Customer's detail automatically in hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:779 +msgid "Customer Settings" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:781 +msgid "Configure customer management and additional checkout fields" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:786 +msgid "Basic Settings" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:804 +msgid "Additional Checkout Fields" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:806 +msgid "Configure additional fields that will be displayed on the checkout page for customer information collection." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:810 +msgid "Field Source" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:816 +msgid "Customer add field to checkout by hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:822 +msgid "Customer add field to checkout by postmeta" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:829 +msgid "Additional checkout fields configuration" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:832 +msgid "Show" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:833 +msgid "Required" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:834 +msgid "Title" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:835 +msgid "Meta code in Postmeta" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:844 +msgid "Show national code field" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:852 +msgid "Make national code field required" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:859 +#: admin/partials/hesabix-admin-setting.php:883 +#: admin/partials/hesabix-admin-setting.php:910 +#: admin/partials/hesabix-admin-setting.php:933 +msgid "Enter meta code" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:860 +msgid "Meta code for national code field" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:868 +msgid "Show economic code field" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:876 +msgid "Make economic code field required" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:884 +msgid "Meta code for economic code field" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:893 +msgid "Show registration number field" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:902 +msgid "Make registration number field required" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:911 +msgid "Meta code for registration number field" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:919 +msgid "Show website field" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:926 +msgid "Make website field required" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:934 +msgid "Meta code for website field" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:946 +msgid "Save Additional Fields" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:962 +#: admin/partials/hesabix-admin-setting.php:1030 +msgid "Invoice Settings" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:969 +msgid "Add invoice in which status" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:973 +msgid "Pending payment" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:974 +msgid "Processing" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:975 +msgid "On hold" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:976 +msgid "Completed" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:977 +msgid "Cancelled" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:978 +msgid "Refunded" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:979 +msgid "Failed" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:980 +msgid "Draft" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:985 +msgid "Save Shipping Costs" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:989 +msgid "Don't Save" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:990 +msgid "Save as Freight" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:991 +msgid "Save as Service" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:993 +msgid "Choose how shipping costs should be handled in invoices" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:997 +msgid "Service Code For Freight" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1000 +msgid "Enter Freight Service Code" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1001 +msgid "Required when \"Save as Service\" is selected. Create this service in Hesabix first." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1006 +msgid "Submit invoice base on Dokan orders" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1011 +msgid "Submit parent order" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1012 +msgid "Submit children orders" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1032 +msgid "Configure invoice generation and freight settings" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1043 +#: admin/partials/hesabix-admin-setting.php:2203 +msgid "Important Notice" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1046 +msgid "Configure when invoices should be created in Hesabix and when return invoices should be generated for orders." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1048 +msgid "If you choose to save shipping costs as a service, you must first create a service in Hesabix and enter its code in the Freight Service Code field." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1050 +msgid "The \"Save as Service\" option is for tax compliance systems." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1052 +msgid "Please ensure this field is correctly entered to avoid invoice creation issues." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1097 +#: admin/partials/hesabix-admin-setting.php:1149 +msgid "API Settings" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1104 +msgid "API Key" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1105 +msgid "Find API key in Setting->Access Tokens Menu" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1111 +msgid "API Address" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1118 +msgid "Custom Address" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1123 +msgid "Custom API Address" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1124 +msgid "Enter your custom API address (e.g., your-domain.com)" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1151 +msgid "Configure your Hesabix API connection and settings" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1157 +msgid "Business Information" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1167 +msgid "Business Name" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1178 +msgid "Subscription Plan" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1189 +msgid "Document Credit" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1200 +msgid "Expiry Date" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1207 +msgid "API Configuration" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1215 +msgid "Important Notes" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1219 +msgid "To connect to Hesabix API and activate this plugin, you need to enter your API key and login token here." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1221 +msgid "If you use login token for Hesabix API connection, you don't need to enter email and password." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1223 +msgid "To find login token and API key, go to Settings > API Settings in Hesabix." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1225 +msgid "If you want to connect another business to the plugin, first remove and reinstall the plugin to clear the previous business connections." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1246 +msgid "Test Connection" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1258 +msgid "Warning" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1261 +msgid "To connect another business to the plugin, first remove and reinstall the plugin to clear the previous business connections." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1288 +msgid "No products were exported, All products were exported or there are no product" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1292 +#, php-format +msgid "Export products completed. %s products added/updated." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1298 +msgid "Export products fail. Hesabix has already contained products." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1302 +msgid "Export products fail. Please check the log file." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1311 +msgid "No products were imported, All products were imported or there are no product" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1315 +#, php-format +msgid "Import products completed. %s products added/updated." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1320 +msgid "Import products fail. Please check the log file." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1326 +msgid "Export product opening quantity completed." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1333 +msgid "Export product opening quantity fail. No Shareholder exists, Please define Shareholder in Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1337 +msgid "No product available for Export product opening quantity." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1341 +msgid "Export product opening quantity fail. Please check the log file." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1351 +msgid "No customers were exported, All customers were exported or there are no customer" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1355 +#, php-format +msgid "Export customers completed. %s customers added." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1361 +msgid "Export customers fail. Hesabix has already contained customers." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1365 +msgid "Export customers fail. Please check the log file." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1372 +msgid "Export can take several minutes." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1382 +msgid "Export Products" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1386 +msgid "Export and add all online store products to Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1419 +msgid "Export Products opening quantity" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1423 +msgid "Export the products quantity and record the 'products opening quantity' in the Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1452 +msgid "Export Customers" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1456 +msgid "Export and add all online store customers to Hesabix." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1483 +msgid "Import Products" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1487 +msgid "Import and add all products from Hesabix to online store" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1522 +msgid "This page is for synchronizing information between the store and Hesabix. Please check the settings before starting." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1525 +msgid "Information Synchronization" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1535 +msgid "Store Products Count" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1547 +msgid "Hesabix Products Count" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1568 +msgid "Linked Products" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1575 +msgid "General Changes Synchronization" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1585 +msgid "Synchronize Changes" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1589 +msgid "This operation synchronizes all changes (products, customers, orders)." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1595 +msgid "Update Hesabix Products Based on Woocommerce" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1606 +msgid "Update Hesabix Products" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1610 +msgid "Product features such as name and price in Hesabix are updated based on the store (inventory does not change)." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1616 +msgid "Product Price and Inventory Synchronization" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1628 +#: admin/partials/hesabix-admin-setting.php:1637 +msgid "Synchronize Price and Inventory" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1642 +msgid "Based on the products tab settings, product prices and inventory are synchronized." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1647 +msgid "Order Synchronization (Time Range)" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1655 +msgid "Quick Select:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1659 +msgid "Last 7 Days" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1662 +msgid "Last 30 Days" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1665 +msgid "Last 3 Months" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1668 +msgid "Custom Range" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1677 +msgid "From Date:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1690 +msgid "To Date:" +msgstr "" + +msgid "Please enter date in Jalali format (YYYY/MM/DD)" +msgstr "" + +msgid "Invalid Jalali date format" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1698 +msgid "End date must be after start date." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1710 +msgid "Selected Range:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1725 +msgid "Synchronize Orders" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1730 +msgid "Store orders that are not registered in Hesabix are checked and registered in the selected date range. Choose a preset option or select a custom date range." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1734 +#: admin/partials/hesabix-admin-setting.php:1746 +msgid "Update Hesabix Customers" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1750 +msgid "Customers existing in the store that are not registered in Hesabix will be checked and registered in Hesabix." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1756 +msgid "Update Woocommerce Products Based on Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1769 +msgid "Update Woocommerce Products" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1773 +msgid "Product features such as name and price in Woocommerce are updated based on Hesabix (inventory does not change)." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1783 +msgid "Operation in Progress..." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:1993 +msgid "The fiscal year has passed or not arrived. Please check the fiscal year settings in Hesabix." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2013 +msgid "Hesabix and WooCommerce default currency must be same." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2020 +msgid "Cannot check the Hesabix default currency. Error Message: " +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2029 +msgid "API Setting updated. Test Successfully" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2045 +msgid "Cannot set Hesabix webHook. Error Message:" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2058 +msgid "Cannot connect to Hesabix servers. Please check your Internet connection" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2075 +#: admin/partials/hesabix-admin-setting.php:2123 +#: admin/partials/hesabix-admin-setting.php:2147 +msgid "Choose" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2083 +msgid "Define at least one bank in Hesabix" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2091 +#: admin/partials/hesabix-admin-setting.php:2096 +msgid "Cannot get Banks detail." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2132 +msgid "Cannot get Projects detail." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2136 +msgid "Cannot get projects detail." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2156 +msgid "Cannot get Salesmen detail." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2160 +msgid "Cannot get salesmen detail." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2170 +msgid "The log file was cleared." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2174 +msgid "Log file not found." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2206 +msgid "By clicking the \"Delete All Logs\" button, all log files will be deleted." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2208 +msgid "To delete the current log, click the \"Delete Current Log\" button when the log file is selected." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2210 +msgid "The log history list displays logs from the last 10 days." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2214 +msgid "Events and bugs log" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2225 +msgid "Delete All Logs" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2234 +msgid "Download Current Log" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2243 +msgid "Delete Current Log" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2248 +msgid "Log History (Last 10 Days)" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2256 +#: admin/partials/hesabix-admin-setting.php:2266 +#: admin/partials/hesabix-admin-setting.php:2341 +#: admin/partials/hesabix-admin-setting.php:2342 +#: admin/partials/hesabix-admin-setting.php:2368 +#: admin/partials/hesabix-admin-setting.php:2369 +msgid "No logs found." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2263 +msgid "Log Content" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2282 +#: admin/partials/hesabix-admin-setting.php:2304 +msgid "Loading..." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2291 +#: admin/partials/hesabix-admin-setting.php:2314 +#: admin/partials/hesabix-admin-setting.php:2315 +msgid "Error fetching log!" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2295 +#: admin/partials/hesabix-admin-setting.php:2319 +#: admin/partials/hesabix-admin-setting.php:2320 +#: admin/partials/hesabix-admin-setting.php:2349 +#: admin/partials/hesabix-admin-setting.php:2375 +msgid "Error connecting to server!" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2312 +msgid "log loaded successfully." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2326 +msgid "Are you sure you want to delete this log?" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2334 +msgid "Log deleted." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2335 +msgid "Log deleted successfully." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2345 +msgid "Error deleting log!" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2354 +msgid "Are you sure you want to delete all logs?" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2362 +msgid "All logs deleted." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2363 +msgid "All logs deleted successfully." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2371 +msgid "Error deleting all logs!" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2391 +#: admin/partials/hesabix-admin-setting.php:2398 +msgid "Accounting quantity (Total inventory)" +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2407 +#: admin/partials/hesabix-admin-setting.php:2411 +msgid "Cannot get warehouses." +msgstr "" + +#: admin/partials/hesabix-admin-setting.php:2457 +#: admin/partials/hesabix-admin-setting.php:2542 +#: admin/partials/hesabix-admin-setting.php:2580 +#: admin/partials/hesabix-admin-setting.php:2610 +msgid "Failed to save settings" +msgstr "" + +#: admin/partials/hesabix-html-output.php:220 +msgid "Order Pending Payment" +msgstr "" + +#: admin/partials/hesabix-html-output.php:223 +msgid "Order Processing" +msgstr "" + +#: admin/partials/hesabix-html-output.php:226 +msgid "Order On Hold" +msgstr "" + +#: admin/partials/hesabix-html-output.php:229 +msgid "Order Completed" +msgstr "" + +#: admin/partials/hesabix-html-output.php:232 +msgid "Order Cancelled" +msgstr "" + +#: admin/partials/hesabix-html-output.php:235 +msgid "Order Refunded" +msgstr "" + +#: admin/partials/hesabix-html-output.php:238 +msgid "Order Failed" +msgstr "" + +#: admin/partials/hesabix-html-output.php:241 +msgid "Order Draft" +msgstr "" + +#: admin/partials/hesabix-html-output.php:333 +msgid "Freight cost is not saved in the invoice." +msgstr "" + +#: admin/partials/hesabix-html-output.php:336 +msgid "Freight cost is saved as a product." +msgstr "" + +#: admin/partials/hesabix-html-output.php:339 +msgid "Freight cost is saved as a service." +msgstr "" + +#: admin/services/hesabixCustomerService.php:17 +msgid "Not Defined" +msgstr "" + +#: admin/services/hesabixCustomerService.php:25 +#: admin/services/hesabixCustomerService.php:104 +msgid "Persons:" +msgstr "" + +#: admin/services/hesabixCustomerService.php:59 +msgid "Customer ID in OnlineStore: " +msgstr "" + +#: admin/services/hesabixCustomerService.php:79 +msgid "Customer" +msgstr "" + +#: admin/services/hesabixCustomerService.php:80 +msgid "Marketer" +msgstr "" + +#: admin/services/hesabixCustomerService.php:81 +msgid "Employee" +msgstr "" + +#: admin/services/hesabixCustomerService.php:82 +msgid "Supplier" +msgstr "" + +#: admin/services/hesabixCustomerService.php:83 +msgid "Colleague" +msgstr "" + +#: admin/services/hesabixCustomerService.php:84 +msgid "Salesman" +msgstr "" + +#: admin/services/hesabixCustomerService.php:102 +msgid "Guest Customer" +msgstr "" + +#: admin/services/hesabixCustomerService.php:146 +msgid "Customer registered as a GuestCustomer." +msgstr "" + +#: hesabix.php:57 +msgid "Hesabix Plugin developed with" +msgstr "" + +#: hesabix.php:59 +msgid "by" +msgstr "" + +#: hesabix.php:69 +msgid "Pirouz" +msgstr "" + +#: includes/class-hesabix-activator.php:11 +msgid "Online Store Customers" +msgstr "" diff --git a/languages/ssbhesabix-fa_IR.mo b/languages/ssbhesabix-fa_IR.mo deleted file mode 100644 index 35da3f1..0000000 Binary files a/languages/ssbhesabix-fa_IR.mo and /dev/null differ diff --git a/languages/ssbhesabix-fa_IR.po b/languages/ssbhesabix-fa_IR.po deleted file mode 100644 index d763ba1..0000000 --- a/languages/ssbhesabix-fa_IR.po +++ /dev/null @@ -1,1002 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Hesabix Accounting\n" -"POT-Creation-Date: 2021-01-08 14:20+0330\n" -"PO-Revision-Date: 2021-01-08 14:20+0330\n" -"Last-Translator: \n" -"Language-Team: \n" -"Language: fa_IR\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.4.2\n" -"X-Poedit-Basepath: ..\n" -"X-Poedit-WPHeader: ssbhesabix.php\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"X-Poedit-SourceCharset: UTF-8\n" -"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;" -"esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;" -"_nx_noop:3c,1,2;__ngettext_noop:1,2\n" -"X-Poedit-SearchPath-0: .\n" -"X-Poedit-SearchPathExcluded-0: *.js\n" - -#: admin/class-ssbhesabix-admin.php:137 -#, php-format -msgid "Hesabix Plugin requires the %s to work!" -msgstr "افزونه حسابیکس نیازمند %s است!" - -#: admin/class-ssbhesabix-admin.php:137 -msgid "WooCommerce" -msgstr "ووکامرس" - -#: admin/class-ssbhesabix-admin.php:146 -msgid "" -"Hesabix Plugin need to connect to Hesabix Accounting, Please check the API " -"credential!" -msgstr "" -"افزونه حسابیکس نیازمند\t اتصال به نرم‌افزار حسابداری حسابیکس است، لطفا اطلاعات " -"دسترسی به API حسابیکس را بررسی کنید!" - -#: admin/class-ssbhesabix-admin.php:155 -msgid "" -"Hesabix Plugin cannot works! because WooCommerce currency in not match with " -"Hesabix." -msgstr "" -"افزونه حسابیکس نمی‌تواند به درستی عمل کند! واحد پول پیش‌فرض ووکامرس با واحد پول " -"پیش‌فرض حسابیکس همخوانی ندارد." - -#: admin/class-ssbhesabix-admin.php:410 admin/class-ssbhesabix-admin.php:502 -msgid "The new Item code already used for another Item" -msgstr "این کد قبلا برای کالایی دیگر استفاده شده است." - -#: admin/class-ssbhesabix-admin.php:483 -msgid "Hesabix base item code" -msgstr "کد کالای پایه در حسابیکس" - -#: admin/class-ssbhesabix-admin.php:485 -msgid "" -"The base Item code of this product in Hesabix, if you want to map this product " -"to another item in Hesabix, enter the new Item code." -msgstr "" -"این فیلد کد کالای پایه در حسابیکس است، اگر می‌خواهید این کالا را به کالای دیگری " -"در حسابیکس ارتباط دهید، کد کالای جدید را وارد نمایید." - -#: admin/class-ssbhesabix-admin.php:521 -msgid "Hesabix variable item code" -msgstr "کد کالای متغیر در حسابیکس" - -#: admin/class-ssbhesabix-admin.php:523 -msgid "" -"The variable Item code of this product variable in Hesabix, if you want to map " -"this product to another item in Hesabix, enter the new Item code." -msgstr "" -"این فیلد کد کالای متغییر در حسابیکس است، اگر می‌خواهید این کالا را به کالای " -"دیگری در حسابیکس ارتباط دهید، کد کالای جدید را وارد نمایید." - -#: admin/partials/ssbhesabix-admin-display.php:305 -msgid "Extra Settings" -msgstr "تنظیمات پیشرفته" - -#: admin/partials/ssbhesabix-admin-display.php:338 -msgid "Sync Last Change ID" -msgstr "بروزرسانی ID آخرین تغییر" - -#: admin/partials/ssbhesabix-admin-display.php:28 -msgid "Hesabix Options" -msgstr "تنظیمات افزونه حسابیکس" - -#: admin/partials/ssbhesabix-admin-display.php:28 -msgid "Hesabix" -msgstr "حسابیکس" - -#: admin/partials/ssbhesabix-admin-display.php:38 -msgid "Home" -msgstr "خانه" - -#: admin/partials/ssbhesabix-admin-display.php:39 -msgid "API" -msgstr "‏API" - -#: admin/partials/ssbhesabix-admin-display.php:40 -msgid "Catalog" -msgstr "محصولات" - -#: admin/partials/ssbhesabix-admin-display.php:41 -msgid "Customers" -msgstr "مشتریان" - -#: admin/partials/ssbhesabix-admin-display.php:42 -msgid "Invoice" -msgstr "فاکتور" - -#: admin/partials/ssbhesabix-admin-display.php:43 -msgid "Payment Methods" -msgstr "روش‌های پرداخت" - -#: admin/partials/ssbhesabix-admin-display.php:44 -msgid "Export" -msgstr "خروجی" - -msgid "Import and export data" -msgstr "ورود و خروج اطلاعات" - -#: admin/partials/ssbhesabix-admin-display.php:45 -msgid "Sync" -msgstr "همسان‌سازی" - -#: admin/partials/ssbhesabix-admin-display.php:65 -msgid "" -"Hesabix Plugin requires the WooCommerce to work!, Please install/activate " -"woocommerce and try again" -msgstr "" -"افزونه حسابیکس جهت راه‌اندازی نیاز به ووکامرس دارد! لطفا ووکامرس را نصب/فعال " -"کنید و مجدد سعی کنید." - -#: admin/partials/ssbhesabix-admin-functions.php:269 -#: admin/partials/ssbhesabix-admin-functions.php:964 -msgid "Not Defined" -msgstr "وارد نشده" - -#: admin/partials/ssbhesabix-admin-functions.php:290 -#: admin/partials/ssbhesabix-admin-functions.php:311 -#: admin/partials/ssbhesabix-admin-functions.php:332 -#: admin/partials/ssbhesabix-admin-functions.php:981 -msgid "Customer ID in OnlineStore: " -msgstr "شناسه مشتری در فروشگاه آن‌لاین:" - -#: admin/partials/ssbhesabix-admin-functions.php:383 -msgid "Guest Customer" -msgstr "مشتری مهمان" - -#: admin/partials/ssbhesabix-admin-functions.php:402 -msgid "Customer registered as a GuestCustomer." -msgstr "مشتری به عنوان مهمان ثبت‌نام کرده است." - -#. Plugin Name of the plugin/theme -#: admin/partials/ssbhesabix-admin-setting.php:44 -msgid "Hesabix Accounting" -msgstr "نرم‌افزار حسابداری آنلاین حسابیکس" - -#: admin/partials/ssbhesabix-admin-setting.php:186 -msgid "Enable or Disable Advanced Log" -msgstr "تب لاگ پیشرفته" - -#: admin/partials/ssbhesabix-admin-setting.php:1455 -msgid "Start ID" -msgstr "از شناسه (کد کالای ووکامرس)" -#: admin/partials/ssbhesabix-admin-setting.php:1456 -msgid "End ID" -msgstr "تا شناسه (کد کالای ووکامرس)" -#: admin/partials/ssbhesabix-admin-setting.php:1456 -msgid "Update Products in Hesabix based on store with filter" -msgstr "بروزرسانی محصولات در حسابیکس بر اساس فروشگاه در بازه ID مشخص شده" - -#: admin/partials/ssbhesabix-admin-setting.php:189 -msgid "Performance Optimization Settings" -msgstr "تنظیمات بهینه سازی عملکرد" - -#: admin/partials/ssbhesabix-admin-setting.php:189 -msgid "Disable The Advanced Log" -msgstr "غیرفعال کردن تب لاگ پیشرفته" - -#: admin/partials/ssbhesabix-admin-setting.php:190 -msgid "Enable The Advanced Log" -msgstr "فعال کردن تب لاگ پیشرفته" - -#: admin/partials/ssbhesabix-admin-setting.php:45 -msgid "" -"This module helps connect your (online) store to Hesabix online accounting " -"software. By using this module, saving products, contacts, and orders in your " -"store will also save them automatically in your Hesabix account. Besides that, " -"just after a client pays a bill, the receipt document will be stored in " -"Hesabix as well. Of course, you have to register your account in Hesabix " -"first. To do so, visit Hesabix at the link here hesabix.ir and sign up " -"for free. After you signed up and entered your account, choose your business, " -"then in the settings menu/API, you can find the API keys for the business and " -"import them to the plugin’s settings. Now your module is ready to use." -msgstr "" -"این ماژول فروشگاه شما را به نرم افزار حسابداری آنلاین حسابیکس متصل می کند. به " -"وسیله ی این ماژول کالاها، مشتریان و سفارشات شما به محض ثبت در سیستم فروشگاه، " -"در حسابیکس نیز بصورت خودکار ثبت و ذخیره می شوند. همچنین با پرداخت مشتری، سند " -"دریافت وجه از مشتری نیز در حسابیکس ثبت می شود. بدیهی است برای استفاده از این " -"افزونه باید ابتدا یک حساب کاربری در حسابیکس داشته باشید. برای این کار می توانید " -"به وب سایت حسابیکس به آدرس hesabix.ir سر بزنید و به رایگان ثبت نام کنید. " -"پس از ثبت نام در حسابیکس و ورود به حساب خود، و سپس ورود به یک کسب و کار، در " -"قسمت تنظیمات / API می توانید کلید API مربوط به کسب و کار خود را دریافت و در " -"قسمت تنظیمات این ماژول وارد نمایید. پس از آن ماژول شما آماده استفاده است." - -#: admin/partials/ssbhesabix-admin-setting.php:46 -msgid "" -"For more information and a full guide to how to use Hesabix and WooCommerce " -"Plugin, visit Hesabix’s website and go to the “Guides and Tutorials” menu." -msgstr "" -"برای کسب اطلاعات بیشتر و راهنمای استفاده از حسابیکس و افزونه ووکامرس به وب سایت " -"حسابیکس، قسمت راهنما ها و خودآموز ها مراجعه کنید." - -#: admin/partials/ssbhesabix-admin-setting.php:53 -msgid "Catalog Settings" -msgstr "تنظیمات محصولات" - -#: admin/partials/ssbhesabix-admin-setting.php:56 -msgid "Update Price" -msgstr "به‌روزرسانی قیمت" - -#: admin/partials/ssbhesabix-admin-setting.php:57 -msgid "Update Price after change in Hesabix" -msgstr "به‌روزرسانی قیمت بعد از تغییر در حسابیکس" - -#: admin/partials/ssbhesabix-admin-setting.php:64 -msgid "Update Quantity" -msgstr "به‌روزرسانی موجودی" - -#: admin/partials/ssbhesabix-admin-setting.php:65 -msgid "Update Quantity after change in Hesabix" -msgstr "به‌روزرسانی موجودی بعد از تغییر در حسابیکس" - -#: admin/partials/ssbhesabix-admin-setting.php:240 -msgid "Show Hesabix ID in Products Page" -msgstr "نمایش کد حسابیکس در صفحه همه محصولات" - -#: admin/partials/ssbhesabix-admin-setting.php:240 -msgid "Show Hesabix Code in Woocommerce Excel Export" -msgstr "نمایش کد حسابیکس در خروجی اکسل ووکامرس" - -#: admin/partials/ssbhesabix-admin-setting.php:679 -msgid "Default Payment Gateway By Using this Option, all Invoices Will Have this Payment Gateway as Their Payment Gateway" -msgstr "درگاه پرداخت پیش فرض" - -#: admin/partials/ssbhesabix-admin-setting.php:695 -msgid "Default Bank Code" -msgstr "کد بانک پیش فرض" - -#: admin/partials/ssbhesabix-admin-setting.php:689 -msgid "Default Bank Name" -msgstr "نام بانک پیش فرض" - -#: admin/partials/ssbhesabix-admin-setting.php:683 -msgid "Save Default Bank as the Payment Gateway" -msgstr "بانک پیش فرض به عنوان درگاه پرداخت ذخیره شود" - -#: admin/partials/ssbhesabix-admin-setting.php:684 -msgid "Save Other Payment Methods as the Payment Gateway" -msgstr "روش های دیگر پرداخت به عنوان درگاه پرداخت ذخیره شود" - -#: admin/partials/ssbhesabix-admin-setting.php:246 -msgid "Set Special Sale as Discount in invoice" -msgstr "ثبت فروش ویژه به عنوان تخفیف در فاکتور" - -#: admin/partials/ssbhesabix-admin-setting.php:693 -msgid "Enter Bank Code" -msgstr "کد بانک را وارد نمایید" - -#: admin/partials/ssbhesabix-admin-setting.php:700 -msgid "Enter Bank Name" -msgstr "نام بانک را وارد نمایید" - -#: admin/partials/ssbhesabix-admin-setting.php:700 -msgid "Enter Freight Code" -msgstr "کد هزینه حمل و نقل را وارد نمایید" - -#: admin/partials/ssbhesabix-admin-setting.php:1642 -msgid "Delete Logs Between These Tow Dates" -msgstr "حذف لاگ ها در بازه مشخص شده" - -#: admin/partials/ssbhesabix-admin-setting.php:1633 -msgid "Log History" -msgstr "تاریخچه لاگ ها" -#: admin/partials/ssbhesabix-admin-setting.php:1648 -#: admin/partials/ssbhesabix-admin-setting.php:1680 -msgid "Delete All Log Files" -msgstr "پاک کردن کل لاگ ها" -#: admin/partials/ssbhesabix-admin-setting.php:1613 -msgid "Find Log File" -msgstr "جستجوی فایل لاگ براساس تاریخ" - -#: admin/partials/ssbhesabix-admin-setting.php:84 -#: admin/partials/ssbhesabix-admin-setting.php:130 -#: admin/partials/ssbhesabix-admin-setting.php:191 -#: admin/partials/ssbhesabix-admin-setting.php:250 -#: admin/partials/ssbhesabix-admin-setting.php:301 -msgid "Save changes" -msgstr "ذخیره تغییرات" - -msgid "Save" -msgstr "ذخیره" - -#: admin/partials/ssbhesabix-admin-setting.php:99 -msgid "Customers Settings" -msgstr "تنظیمات مشتری" - -#: admin/partials/ssbhesabix-admin-setting.php:102 -msgid "Update Customer Address" -msgstr "به روزرسانی آدرس مشتریان" - -#: admin/partials/ssbhesabix-admin-setting.php:103 -msgid "Choose when update Customer address in Hesabix." -msgstr "انتخاب کنید که در چه حالتی آدرس مشتری در حسابیکس به‌روزرسانی شود" - -#: admin/partials/ssbhesabix-admin-setting.php:106 -msgid "Use first customer address" -msgstr "اولین آدرس مشتری" - -#: admin/partials/ssbhesabix-admin-setting.php:106 -msgid "update address with Invoice address" -msgstr "به روزرسانی با آدرس فاکتور سفارش" - -#: admin/partials/ssbhesabix-admin-setting.php:106 -msgid "update address with Delivery address" -msgstr "به‌روزرسانی با آدرس ارسال سفارش" - -#: admin/partials/ssbhesabix-admin-setting.php:110 -msgid "Customer's Group" -msgstr "دسته‌بندی مشتریان" - -#: admin/partials/ssbhesabix-admin-setting.php:111 -msgid "Enter a Customer's Group in Hesabix" -msgstr "نام دسته‌بندی مشتریان در حسابیکس را وارد کنید" - - - -#: admin/partials/ssbhesabix-admin-setting.php:110 -msgid "Save Customer's group" -msgstr "ذخیره دسته بندی مشتریان" - - -#: admin/partials/ssbhesabix-admin-setting.php:110 -msgid "Automatically save Customer's group in hesabix" -msgstr "به صورت خودکار دسته بندی مشتریان را در حسابیکس ذخیره کن" - - -#: admin/partials/ssbhesabix-admin-setting.php:111 -msgid "Customer's detail auto save and update" -msgstr "ذخیره خودکار مشتریان" - -#: admin/partials/ssbhesabix-admin-setting.php:111 -msgid "Check customer's phone with national code in user edit page" -msgstr "بررسی تطابق شماره صورتحساب کاربر با کدملی" - -#: admin/partials/ssbhesabix-admin-setting.php:111 -msgid Check customer's phone with national code in user edit page and don't allow to save in hesabix" -msgstr "بررسی تطابق شماره صورتحساب کاربر با کدملی توسط سامانه استعلام در صفحه ویرایش کاربر" - -#: admin/partials/ssbhesabix-admin-setting.php:111 -msgid "Save and update Customer's detail automatically in hesabix" -msgstr "ثبت و ذخیره خودکار اطلاعات مشتریان در حسابیکس" - -msgid "Add additional fields to checkout page" -msgstr "افزودن فیلد های دلخواه به صفحه پرداخت" - - -msgid "Customer add field to checkout by hesabix" -msgstr "افزودن فیلد ها توسط افزونه حسابیکس" - - -msgid "Customer add field to checkout by postmeta" -msgstr "استفاده از فیلد های موجود در جدول متا (که توسط افزونه های دیگر اضافه شده است)" - - -msgid "Show" -msgstr "نمایش" - -msgid "Title" -msgstr "عنوان" - -msgid "Meta code in Postmeta" -msgstr "کد متا در جدول پست متا" - -msgid "National code" -msgstr "کد ملی" - -msgid "Economic code" -msgstr "کد اقتصادی" - -msgid "Registration number" -msgstr "شماره ثبت" - -msgid "Website" -msgstr "وب سایت" - -msgid "Required" -msgstr "اجباری" - -msgid "please enter your National code" -msgstr "لطفا کد ملی خود را وارد کتید" - -msgid "please enter a valid national code" -msgstr "لطفا کد ملی معتبر وارد نمایید" - -msgid "please enter your Economic code" -msgstr "لطفا کد اقتصادی خود را وارد کتید" - -msgid "please enter your Registration number" -msgstr "لطفا شماره ثبت خود را وارد کتید" - -msgid "please enter your Website address" -msgstr "لطفا آدرس سایت خود را وارد کنید" - -msgid "please enter a valid Website URL" -msgstr "لطفا آدرس سایت معتبر وارد نمایید" - -#: admin/partials/ssbhesabix-admin-setting.php:144 -msgid "Invoice Settings" -msgstr "تنظیمات فاکتور" - -#: admin/partials/ssbhesabix-admin-setting.php:147 -msgid "Add invoice in which status" -msgstr "افزودن فاکتور در وضعیت:" - -#: admin/partials/ssbhesabix-admin-setting.php:380 -msgid "Save invoice in draft mode in Hesabix" -msgstr "ثبت فاکتور بصورت پیش نویس در حسابیکس" - -#: admin/partials/ssbhesabix-admin-setting.php:557 -msgid "Save Freight" -msgstr "ذخیره هزینه حمل و نقل" - -#: admin/partials/ssbhesabix-admin-setting.php:561 -msgid "Save as Freight" -msgstr "ذخیره به عنوان هزینه" - -#: admin/partials/ssbhesabix-admin-setting.php:562 -msgid "Save as a Service" -msgstr "ذخیره به عنوان یک خدمت" - -#: admin/partials/ssbhesabix-admin-setting.php:562 -msgid "Service Code For Freight" -msgstr "کد خدمت حمل و نقل ذخیره شده در حسابیکس" - -#: admin/partials/ssbhesabix-admin-setting.php:151 -#: admin/partials/ssbhesabix-admin-setting.php:167 -#: admin/partials/ssbhesabix-admin-setting.php:217 -msgid "Pending payment" -msgstr "در انتظار پرداخت" - -#: admin/partials/ssbhesabix-admin-setting.php:152 -#: admin/partials/ssbhesabix-admin-setting.php:168 -#: admin/partials/ssbhesabix-admin-setting.php:218 -msgid "Processing" -msgstr "در حال انجام" - -#: admin/partials/ssbhesabix-admin-setting.php:153 -#: admin/partials/ssbhesabix-admin-setting.php:169 -#: admin/partials/ssbhesabix-admin-setting.php:219 -msgid "On hold" -msgstr "در انتظار بررسی" - -#: admin/partials/ssbhesabix-admin-setting.php:154 -#: admin/partials/ssbhesabix-admin-setting.php:170 -#: admin/partials/ssbhesabix-admin-setting.php:220 -msgid "Completed" -msgstr "تکمیل شده" - -#: admin/partials/ssbhesabix-admin-setting.php:155 -#: admin/partials/ssbhesabix-admin-setting.php:171 -#: admin/partials/ssbhesabix-admin-setting.php:221 -msgid "Cancelled" -msgstr "لغو شده" - -#: admin/partials/ssbhesabix-admin-setting.php:156 -#: admin/partials/ssbhesabix-admin-setting.php:172 -#: admin/partials/ssbhesabix-admin-setting.php:222 -msgid "Refunded" -msgstr "مسترد شده" - -#: admin/partials/ssbhesabix-admin-setting.php:157 -#: admin/partials/ssbhesabix-admin-setting.php:173 -#: admin/partials/ssbhesabix-admin-setting.php:223 -msgid "Failed" -msgstr "ناموفق" - -#: admin/partials/ssbhesabix-admin-setting.php:158 -#: admin/partials/ssbhesabix-admin-setting.php:174 -#: admin/partials/ssbhesabix-admin-setting.php:224 -msgid "Draft" -msgstr "پیش‌نویس" - -#: admin/partials/ssbhesabix-admin-setting.php:163 -msgid "Return sale invoice status" -msgstr "ثبت فاکتور برگشت از فروش در وضعیت" - -#: admin/partials/ssbhesabix-admin-setting.php:210 -msgid "Payment methods Settings" -msgstr "تنظیمات روش پرداخت" - -#: admin/partials/ssbhesabix-admin-setting.php:213 -msgid "Add payment in which status" -msgstr "افزودن پرداخت در وضعیت:" - -#: admin/partials/ssbhesabix-admin-setting.php:265 -msgid "API Settings" -msgstr "تنظیمات API" - -#: admin/partials/ssbhesabix-admin-setting.php:268 -msgid "Email" -msgstr "آدرس ایمیل" - -#: admin/partials/ssbhesabix-admin-setting.php:269 -msgid "Enter a Hesabix email account" -msgstr "آدرس ایمیل اکانت حسابیکس را وارد کنید" - -#: admin/partials/ssbhesabix-admin-setting.php:275 -msgid "Password" -msgstr "رمزعبور" - -#: admin/partials/ssbhesabix-admin-setting.php:276 -msgid "Enter a Hesabix password" -msgstr "رمزعبور حسابیکس را وارد کنید" - -#: admin/partials/ssbhesabix-admin-setting.php:282 -msgid "API Key" -msgstr "کلید API" - -msgid "Login token" -msgstr "توکن ورود" - -#: admin/partials/ssbhesabix-admin-setting.php:283 -msgid "Find API key in Setting->Financial Settings->API Menu" -msgstr "کلید API را در حسابیکس از منوی تنظیمات->تنظیمات مالی->API پیدا کنید" - -msgid "Find Login token in Setting->Financial Settings->API Menu" -msgstr "توکن ورود را در حسابیکس از منوی تنظیمات->تنظیمات مالی->API پیدا کنید" - -#: admin/partials/ssbhesabix-admin-setting.php:323 -msgid "" -"No products were exported, All products were exported or there are no product" -msgstr "" -"هیچ محصولی استخراج نشد، تمامی محصولات قبلا استخراج شده‌اند یا محصولی وجود ندارد." - -msgid "" -"No products were imported, All products were imported or there are no product" -msgstr "" -"هیچ محصولی وارد نشد، تمامی محصولات قبلا وارد شده‌اند یا محصولی وجود ندارد." - - -#: admin/partials/ssbhesabix-admin-setting.php:327 -#, php-format -msgid "Export products completed. %s products added/updated." -msgstr "استخراج محصولات به اتمام رسید. ‪‬%s محصول استخراج شد." - -msgid "Import products completed. %s products added/updated." -msgstr "ورود محصولات به اتمام رسید. ‪‬%s محصول وارد شد." - -#: admin/partials/ssbhesabix-admin-setting.php:335 -msgid "Export products fail. Hesabix has already contained products." -msgstr "خروجی محصولات با خطا مواجه شد. حسابیکس از قبل حاوی محصولاتی است." - -#: admin/partials/ssbhesabix-admin-setting.php:339 -msgid "Export products fail. Please check the log file." -msgstr "خروجی محصولات با خطا مواجه شد. لطفا لاگ را بررسی کنید." - -msgid "Import products fail. Please check the log file." -msgstr "ورود محصولات با خطا مواجه شد. لطفا لاگ را بررسی کنید." - -#: admin/partials/ssbhesabix-admin-setting.php:340 -msgid "Export product opening quantity completed." -msgstr "استخراج موجودی اول دوره با موفقیت به پایان رسید." - -#: admin/partials/ssbhesabix-admin-setting.php:347 -msgid "" -"Export product opening quantity fail. No Shareholder exists, Please define " -"Shareholder in Hesabix" -msgstr "" -"استخراج موجودی اول دوره با خطا مواجه شد. سهامدار تعریف نشده است، لطفا ابتدا " -"سهامداران را در حسابیکس تعریف کنید." - -#: admin/partials/ssbhesabix-admin-setting.php:351 -msgid "No product available for Export product opening quantity." -msgstr "محصولی جهت استخراج موجودی اول دوره در دسترس نمی‌باشد." - -#: admin/partials/ssbhesabix-admin-setting.php:355 -msgid "Export product opening quantity fail. Please check the log file." -msgstr "استخراج موجودی اول دوره با خطا مواجه شد. لطفا لاگ را بررسی کنید." - -#: admin/partials/ssbhesabix-admin-setting.php:366 -msgid "" -"No customers were exported, All customers were exported or there are no " -"customer" -msgstr "" -"هیچ مشتری استخراج نشد، تمامی مشتریان قبلا استخراج شده‌اند یا مشتری وجود ندارد." - -#: admin/partials/ssbhesabix-admin-setting.php:370 -#, php-format -msgid "Export customers completed. %s customers added." -msgstr "استخراج مشتریان به اتمام رسید. %s مشتری استخراج شد." - -#: admin/partials/ssbhesabix-admin-setting.php:375 -msgid "Export customers fail. Please check the log file." -msgstr "استخراج مشتریان با خطا مواجه شد. لطفا لاگ را بررسی کنید." - -#: admin/partials/ssbhesabix-admin-setting.php:381 -msgid "Export can take several minutes." -msgstr "استخراج ممکن است چند دقیقه زمان ببرد." - -msgid "Export customers fail. Hesabix has already contained customers." -msgstr "خروجی مشتریان با خطا مواجه شد. حسابیکس از قبل حاوی مشتریان است." - -#: admin/partials/ssbhesabix-admin-setting.php:392 -msgid "Export Products" -msgstr "خروجی محصولات" - -msgid "Import Products" -msgstr "ورود محصولات" - -#: admin/partials/ssbhesabix-admin-setting.php:395 -msgid "Export and add all online store products to Hesabix" -msgstr "افزودن تمامی محصولات فروشگاه آنلاین در حسابیکس" - -msgid "Import and add all products from Hesabix to online store" -msgstr "افزودن تمامی محصولات حسابیکس به فروشگاه آنلاین" - -#: admin/partials/ssbhesabix-admin-setting.php:407 -msgid "Export Products opening quantity" -msgstr "استخراج موجودی اول دوره" - -#: admin/partials/ssbhesabix-admin-setting.php:410 -msgid "" -"Export the products quantity and record the 'products opening quantity' in the " -"Hesabix" -msgstr "استخراج موجودی محصولات و ثبت موجودی اول دوره در حسابیکس" - -#: admin/partials/ssbhesabix-admin-setting.php:422 -msgid "Export Customers" -msgstr "خروجی مشتریان" - -#: admin/partials/ssbhesabix-admin-setting.php:425 -msgid "Export and add all online store customers to Hesabix." -msgstr "افزودن تمامی مشتریان فروشگاه آنلاین در حسابیکس" - -#: admin/partials/ssbhesabix-admin-setting.php:437 -msgid "Sync completed, All hesabix changes synced successfully." -msgstr "همسان‌سازی پایان یافت. تمامی تغییرات با حسابیکس همسان شد." - -#: admin/partials/ssbhesabix-admin-setting.php:445 -msgid "Sync completed, All products price/quantity synced successfully." -msgstr "همسان سازی پایان یافت. قیمت/موجودی تمامی محصولات به روز شدند." - -#: admin/partials/ssbhesabix-admin-setting.php:449 -msgid "Sync products fail. Please check the log file." -msgstr "همسان‌سازی محصولات با خطا مواجه شد. لطفا لاگ را بررسی کنید." - -#: admin/partials/ssbhesabix-admin-setting.php:459 -#, php-format -msgid "Order sync completed. %s order added." -msgstr "همسان‌سازی پایان یافت. %s فاکتور به‌روزرسانی/افزوده شد." - -#: admin/partials/ssbhesabix-admin-setting.php:467 -msgid "The date entered is not within the fiscal year." -msgstr "تاریخ وارد شده در محدوده سال مالی نمی‌باشد." - -#: admin/partials/ssbhesabix-admin-setting.php:471 -msgid "Invoices are not synced before installing the plugin." -msgstr "" -"فاکتورهایی که قبل از زمان نصب این پلاگین صادر شده‌اند، امکان همسان‌سازی ندارند." - -#: admin/partials/ssbhesabix-admin-setting.php:475 -msgid "Cannot sync orders. Please enter valid Date format." -msgstr "امکان همسان سازی سفارشات نیست. لطفا تاریخ معتبری وارد نمایید." - -#: admin/partials/ssbhesabix-admin-setting.php:482 -msgid "Sync can take several minutes." -msgstr "همسان‌سازی ممکن است چند دقیقه زمان ببرد." - -#: admin/partials/ssbhesabix-admin-setting.php:183 -msgid "Enable or Disable Debug Mode" -msgstr "فعال کردن دیباگ مود" - -#: admin/partials/ssbhesabix-admin-setting.php:246 -msgid "Set request amount per batch for sync products based on woocommerce in Hesabix" -msgstr "تعداد درخواست ها در هر پارت برای همسان سازی محصولات در حسابیکس بر اساس فروشگاه آنلاین" - -#: admin/partials/ssbhesabix-admin-setting.php:263 -msgid "Set request amount per batch for sync products based on Hesabix in Woocommerce" -msgstr "تعداد درخواست ها در هر پارت برای همسان سازی محصولات در فروشگاه آنلاین بر اساس حسابیکس" - -#: admin/partials/ssbhesabix-admin-setting.php:280 -msgid "Set request amount per batch for import products" -msgstr "تعداد درخواست ها در هر پارت برای ورود محصولات" - -#: admin/partials/ssbhesabix-admin-setting.php:297 -msgid "Set request amount per batch for export products" -msgstr "تعداد درخواست ها در هر پارت برای استخراج محصولات" - -#: admin/partials/ssbhesabix-admin-setting.php:308 -msgid "select" -msgstr "انتخاب کنید" - -#: admin/partials/ssbhesabix-admin-setting.php:317 -msgid "Plugin Default" -msgstr "مقدار پیش فرض افزونه" - -#: admin/partials/ssbhesabix-admin-setting.php:314 -msgid "Set request amount per batch for export opening quantity of products" -msgstr "تعداد درخواست ها در هر پارت برای استخراج موجودی اول دوره کالا ها" - -#: admin/partials/ssbhesabix-admin-setting.php:494 -msgid "Sync Changes" -msgstr "همسان‌سازی تغییرات" - -#: admin/partials/ssbhesabix-admin-setting.php:497 -msgid "Sync all Hesabix changes with Online Store." -msgstr "همسان‌سازی تمامی تعییرات حسابیکس با فروشگاه آن‌لاین" - -#: admin/partials/ssbhesabix-admin-setting.php:509 -msgid "Sync Products Quantity and Price" -msgstr "همسان‌سازی قیمت و موجودی محصولات" - -#: admin/partials/ssbhesabix-admin-setting.php:512 -msgid "Sync quantity and price of products in hesabix with online store." -msgstr "همسان‌سازی قیمت و موجودی محصولات حسابیکس با فروشگاه آن‌لاین" - -#: admin/partials/ssbhesabix-admin-setting.php:525 -msgid "Sync Orders" -msgstr "همسان‌سازی سفارشات" - -#: admin/partials/ssbhesabix-admin-setting.php:528 -msgid "Sync/Add orders in online store with hesabix from above date." -msgstr "همسان‌سازی سفارشات فروشگاه آن‌لاین با حسابیکس از تاریخ فوق" - -#: admin/partials/ssbhesabix-admin-setting.php:557 -msgid "Cannot check the last change ID. Error Message: " -msgstr "امکان بررسی آخرین تغییرات وجود ندارد. شرح خطا:" - -#: admin/partials/ssbhesabix-admin-setting.php:567 -msgid "" -"The fiscal year has passed or not arrived. Please check the fiscal year " -"settings in Hesabix." -msgstr "" -"سال مالی گذشته است یا هنوز فرا نرسیده است، لطفا تنظیمات سال مالی در حسابیکس را " -"بررسی کنید." - -#: admin/partials/ssbhesabix-admin-setting.php:585 -msgid "Hesabix and WooCommerce default currency must be same." -msgstr "واحد پول پیش‌فرض حسابیکس و ووکامرس باید یکی باشد." - -#: admin/partials/ssbhesabix-admin-setting.php:590 -msgid "Cannot check the Hesabix default currency. Error Message: " -msgstr "امکان دریافت واحد پول پیش‌فرض حسابیکس وجود ندارد. شرح خطا:" - -#: admin/partials/ssbhesabix-admin-setting.php:598 -msgid "API Setting updated. Test Successfully" -msgstr "تنظیمات API به روزرسانی شد، اتصال موفقیت آمیز بود." - -#: admin/partials/ssbhesabix-admin-setting.php:605 -msgid "Cannot set Hesabix webHook. Error Message:" -msgstr "امکان تنظیم وب‌هوک در حسابیکس وجود ندارد. شرح خطا:" - -msgid "Cannot connect to Hesabix. Business expired." -msgstr "امکان اتصال به حسابیکس وجود ندارد، کسب و کار منقضی شده است." - -#: admin/partials/ssbhesabix-admin-setting.php:614 -msgid "Cannot connect to Hesabix servers. Please check your Internet connection" -msgstr "اتصال به حسابیکس برقرار نیست، لطفا اتصال اینترنت را بررسی نمایید." - -#: admin/partials/ssbhesabix-admin-setting.php:630 -msgid "No need to set!" -msgstr "عدم نیاز به تعریف!" - -#: admin/partials/ssbhesabix-admin-setting.php:630 -msgid "Choose" -msgstr "انتخاب کنید" - -#: admin/partials/ssbhesabix-admin-setting.php:638 -msgid "Define at least one bank in Hesabix" -msgstr "حداقل یک حساب بانکی در حسابیکس تعریف کنید." - -#: admin/partials/ssbhesabix-admin-setting.php:646 -#: admin/partials/ssbhesabix-admin-setting.php:650 -msgid "Cannot get Banks detail." -msgstr "امکان دریافت اطلاعات بانک‌ها نیست." - -#: admin/partials/ssbhesabix-html-output.php:288 -msgid "Select a page…" -msgstr "انتخاب ‫دسته‌بندی" - -#: admin/partials/ssbhesabix-html-output.php:379 -msgid "Settings were saved successfully." -msgstr "تنظیمات به‌روزرسانی شد." - -#. Plugin URI of the plugin/theme -msgid "https://hesabix.ir/" -msgstr "‏https://hesabix.ir/" - -#. Description of the plugin/theme -msgid "Connect Hesabix Online Accounting to WooCommerce." -msgstr "\tاتصال نرم‌افزار حسابداری ابری حسابیکس به ووکامرس" - -#. Author of the plugin/theme -msgid "Saeed Sattar Beglou" -msgstr "سعید ستاربگلو" - -msgid "Log" -msgstr "لاگ" - -msgid "Events and bugs log" -msgstr "لاگ رویدادها و خطاها" - -msgid "Clean current log" -msgstr "پاک کردن لاگ جاری" - -msgid "Download log file" -msgstr "دانلود فایل لاگ" - -msgid "The log file was cleared." -msgstr "فایل لاگ پاک شد." - -msgid "Log file not found." -msgstr "فایل لاگ پیدا نشد." - -msgid "Update Products in Hesabix based on store" -msgstr "به روزرسانی محصولات در حسابیکس بر اساس فروشگاه" - -msgid "Update products in hesabix based on products definition in store." -msgstr "به روزرسانی محصولات در حسابیکس بر اساس مشخصات آنها در فروشگاه. محصولات جدید به حسابیکس اضافه می شوند و محصولات قبلی ویرایش می شوند." - -msgid "Update completed successfully." -msgstr "به روزرسانی با موفقیت انجام شد." - -msgid "Update failed. Please check the log file." -msgstr "به روزرسانی ناموفق بود. لطفاً لاگ را بررسی کنید." - -msgid "Number of products in store:" -msgstr "تعداد محصولات در فروشگاه:" - -msgid "Number of products in hesabix:" -msgstr "تعداد محصولات در حسابیکس:" - -msgid "Number of linked products:" -msgstr "تعداد محصولات لینک شده:" - -msgid "Save and next page" -msgstr "ذخیره و صفحه بعد" - -msgid "Invoice in Hesabix" -msgstr "فاکتور حسابیکس" - -msgid "Submit Invoice" -msgstr "ثبت فاکتور" - -msgid "Submit Invoice in Hesabix" -msgstr "ثبت فاکتور در حسابیکس" - -msgid "Submit Product in Hesabix" -msgstr "ثبت محصول در حسابیکس" - -msgid "Do not submit product in Hesabix automatically by saving product in woocommerce" -msgstr "با ذخیره محصول در ووکامرس، محصول را بصورت اتوماتیک در حسابیکس ثبت نکن" - -msgid "Remove The Titles for Attributes When Saving Product To Hesabix" -msgstr "عنوان متغیر های یک محصول را با ذخیره/بروزرسانی در نام محصول حذف کن" - -msgid "Submit Price in Hesabix" -msgstr "ثبت قیمت در حسابیکس" - -msgid "Do not update product price in Hesabix by editing product in woocommerce" -msgstr "با ویرایش محصول در ووکامرس، قیمت محصول را در حسابیکس بروز نکن" - -msgid "Barcode in Hesabix" -msgstr "بارکد در حسابیکس" - -msgid "National Code in Hesabix" -msgstr "کد ملی در حسابیکس" - -msgid "Do not update product barcode in Hesabix by saving product in woocommerce" -msgstr "با ذخیره محصول در ووکامرس، بارکد محصول را در حسابیکس بروز نکن" - -msgid "Do not update product category in Hesabix by saving product in woocommerce" -msgstr "با ذخیره محصول در ووکامرس، دسته بندی محصول را در حسابیکس بروز نکن" - -msgid "Do not update product code in Hesabix by saving product in woocommerce" -msgstr "با ذخیره محصول در ووکامرس، کد محصول را در حسابیکس بروز نکن" - -msgid "Shipping method" -msgstr "روش حمل و نقل" - -msgid "Invoice's Salesman" -msgstr "فروشنده فاکتور" - -msgid "Invoice Salesman Percentage" -msgstr "درصد پورسانت فروشنده فاکتور" - -msgid "Invoice's Project" -msgstr "پروژه فاکتور" - -msgid "Submit Cash in Transit" -msgstr "ثبت در وجوه در راه" - -msgid "Submit Invoice Receipt Cash in Transit" -msgstr "ثبت رسید دریافت فاکتور در وجوه در راه" - -msgid "Default Invoice Transaction Fee Percentage" -msgstr "درصد کارمزد تراکنش به صورت پیش فرض" - -msgid "Plugin Tutorial Video" -msgstr "ویدیوی خودآموز افزونه" - -msgid "Titles" -msgstr "عناوین" - -msgid "Accounting quantity (Total inventory)" -msgstr "موجودی حسابداری (موجودی کل)" - -msgid "Cannot get warehouses." -msgstr "امکان دریافت اطلاعات انبارها نیست." - -msgid "Update product's quantity based on" -msgstr "بروزرسانی موجودی کالا بر اساس" - -msgid "Do not update purchase and sales titles in hesabix" -msgstr "توضیحات (عنوان های) خرید و فروش را در حسابیکس بروز نکن" - -msgid "Warehouse system is not active in Hesabix." -msgstr "سیستم انبارداری در حسابیکس فعال نیست." - -msgid "API Address" -msgstr "آدرس API" - -msgid "Contact Code in Hesabix" -msgstr "کد شخص در حسابیکس" - -msgid "" -"The contact code of this user in Hesabix, if you want to map this user " -"to a contact in Hesabix, enter the Contact code." -msgstr "" -"این فیلد کد شخص در حسابیکس است، اگر می‌خواهید این کاربر را به شخصی " -"در حسابیکس ارتباط دهید، کد شخص را وارد نمایید." - -msgid "" -"To check the phone with national code, " -"you need to enter both billing phone correctly." -msgstr "" -"این فیلد کد ملی شخص در حسابیکس است، اگر می‌خواهید شماره تماس با کد ملی چک شود " -"باید شماره تماس صورتحساب را به درستی وارد نمایید." - -msgid "Error: Select maximum 10 orders. Due to some limitations in Hesabix API, sending too many requests in one minute is not possible." -msgstr "خطا: حداکثر ۱۰ سفارش را انتخاب کنید. بدلیل محدودیت رابط برنامه نویسی حسابیکس، ارسال درخواست های زیاد در یک دقیقه امکان پذیر نیست." - -msgid "Selected orders invoices have been saved. Number of saved invoices: " -msgstr "فاکتور سفارش های انتخاب شده ثبت شد. تعداد فاکتور های ثبت شده: " - -msgid "Update sale price" -msgstr "بروزرسانی قیمت فروش ویژه" - -msgid "The Sale price does not change" -msgstr "قیمت فروش ویژه تغییر نکند" - -msgid "The Sale price gets removed" -msgstr "قیمت فروش ویژه حذف گردد" - -msgid "The sale price get changes in proportion to the regular price" -msgstr "قیمت فروش ویژه به تناسب قیمت اصلی تغییر یابد" - -msgid "Submit invoice base on Dokan orders" -msgstr "ثبت فاکتور بر اساس سفارشات افزونه دکان" - -msgid "Submit parent order" -msgstr "ثبت سفارش مادر" - -msgid "Submit children orders" -msgstr "ثبت زیر سفارش ها" - -msgid "Inactive" -msgstr "غیر فعال" - -#~ msgid "Sync completed, All products added/updated." -#~ msgstr "همسان‌سازی پایان یافت. تمامی محصولات به‌روزرسانی/افزوده شدند." - -#~ msgid "Sync completed, No product added/updated." -#~ msgstr "همسان‌سازی پایان یافت. هیچ محصولی به‌روزرسانی/افزوده شدند." - -#~ msgid "Sync completed; All hesabix changes synced successfully." -#~ msgstr "همسان‌سازی پایان یافت. تمامی تغییرات با حسابیکس همسان شد." - -#~ msgid "Sync completed; All products added/updated." -#~ msgstr "همسان‌سازی پایان یافت. تمامی محصولات به‌روزرسانی/افزوده شدند." - -#~ msgid "Sync completed; No product added/updated." -#~ msgstr "همسان‌سازی پایان یافت. هیچ محصولی به‌روزرسانی/افزوده شدند." - -#~ msgid "Export product completed. %s product added/updated." -#~ msgstr "استخراج پایان یافت. %s محصول به‌روزرسانی/افزوده شد." - -#~ msgid "Export customers completed. %s product added/updated." -#~ msgstr "استخراج مشتریان پایان یافت. %s مشتری به‌روزرسانی/افزوده شد." \ No newline at end of file diff --git a/ssbhesabix.php b/ssbhesabix.php deleted file mode 100644 index f50e764..0000000 --- a/ssbhesabix.php +++ /dev/null @@ -1,72 +0,0 @@ -run(); -} - -run_ssbhesabix(); diff --git a/uninstall.php b/uninstall.php index ee1d5f1..1ae5fb2 100644 --- a/uninstall.php +++ b/uninstall.php @@ -1,33 +1,28 @@ - * @author HamidReza Gharahzadeh - * @author Sepehr Najafi - * @since 1.0.0 - * - * @package ssbhesabix + * Hesabix Uninstall + * + * @package Hesabix + * @author Mohammad Rezai + * @author URI https://pirouz.xyz + * @since 1.0.0 */ -// If uninstall not called from WordPress, then exit. -if (!defined( 'WP_UNINSTALL_PLUGIN')) { - exit; +if (!defined('WP_UNINSTALL_PLUGIN')) { + exit; } -include_once(plugin_dir_path(__DIR__) . 'admin/services/hesabixLogService.php'); -require 'includes/class-ssbhesabix-api.php'; - -// delete tags in hesabix -$hesabixApi = new Ssbhesabix_Api(); -$result = $hesabixApi->fixClearTags(); -if (!$result->Success) { - hesabixLogService::log(array("ssbhesabix - Cannot clear tags. Error Message: " . (string)$result->ErrorMessage . ". Error Code: " . (string)$result->ErrorCode)); +if (defined('ABSPATH')) { + global $wpdb; + if (isset($wpdb->options)) { + $options = $wpdb->get_results("SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%hesabix%'"); + if ($options) { + foreach ($options as $option) { + delete_option($option->option_name); + } + } + } + if (isset($wpdb->prefix)) { + $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}hesabix"); + } } - -global $wpdb; -$options = $wpdb->get_results("SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%ssbhesabix%'"); -foreach ($options as $option) { - delete_option($option->option_name); -} - -$wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}ssbhesabix");