--- a/primer-mydata/admin/class-primer-admin.php
+++ b/primer-mydata/admin/class-primer-admin.php
@@ -155,6 +155,9 @@
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => $primer_nonce
));
+
+
+
}
/**
@@ -628,22 +631,23 @@
* Add Invoice Type column
* @param $column
*/
- public function primer_icon_to_order_notes_column( $column ) {
- global $post, $the_order;
+ public function primer_icon_to_order_notes_column( $column, $post_id ): void
+ {
+ if ( $column !== 'order_number' ) {
+ return;
+ }
+ $order = wc_get_order($post_id);
+ if ( ! $order ) {
+ return;
+ }
- // Added WC 3.2+ compatibility
- if ( $column == 'order_notes' || $column == 'order_number' ) {
- // Added WC 3+ compatibility
- $order_id = method_exists( $the_order, 'get_id' ) ? $the_order->get_id() : $the_order->id;
+ $primer_type = $order->get_meta('_billing_invoice_type');
- $order = wc_get_order($order_id);
- $primer_type = $order->get_meta('_billing_invoice_type');
- if ( $primer_type == 'primer_invoice' ) {
- $style = $column == 'order_notes' ? 'style="margin-top:5px;" ' : 'style="margin-left:8px;padding:5px;"';
- echo '<span class="dashicons dashicons-format-aside" '.$style.'title="'. __('Invoice Type', 'primer').'"></span>';
- }
- }
- }
+ if ( $primer_type === 'primer_invoice' ) {
+ $style = 'style="margin:5px;"';
+ echo '<span class="dashicons dashicons-format-aside" ' . $style . ' title="' . esc_attr__('Invoice Type: Invoice', 'primer') . '"></span>';
+ }
+ }
public function primer_add_woocommerce_found_customer_details($customer_data, $user_id, $type_to_load) {
@@ -742,22 +746,17 @@
public function primer_editable_order_meta_general( $order ) { ?>
<br class="clear" />
- <h4>Invoice Type <a href="#" class="edit_address">Edit</a></h4>
<?php
$invoice_type_primer = $order->get_meta('_billing_invoice_type');
- if($invoice_type_primer == 'primer_invoice'){
- $get_invoice_type = 'primer_invoice';
- }else{
- $get_invoice_type = $order->get_meta('_billing_invoice_type');
- }
?>
- <div class="edit_address">
+ <div>
<?php
if(function_exists('woocommerce_wp_radio')) {
woocommerce_wp_radio(array(
'id' => '_billing_invoice_type',
'label' => 'Invoice Type',
+ 'value' => $invoice_type_primer,
'options' => array(
'receipt' => 'Receipt',
'primer_invoice' => 'Invoice'
@@ -1452,3 +1451,66 @@
return $plugin_edition;
}
+
+function primer_make_refund_from_page() {
+ if (!current_user_can('manage_woocommerce')) {
+ wp_send_json_error(array('message' => __('Permission denied.', 'primer')));
+ wp_die();
+ }
+
+ check_ajax_referer('primer_refund_nonce', 'nonce');
+
+ if (!isset($_POST['order_id'])) {
+ wp_send_json_error(array('message' => __('Missing order ID.', 'primer')));
+ wp_die();
+ }
+
+ if (!isset($_POST['refund_amount']) || !is_numeric($_POST['refund_amount'])) {
+ wp_send_json_error(array('message' => __('Missing or invalid refund amount in request.', 'primer')));
+ wp_die();
+ }
+
+ $order_id = absint($_POST['order_id']);
+ $order = wc_get_order($order_id);
+
+ if (!$order) {
+ wp_send_json_error(array('message' => __('Invalid order.', 'primer')));
+ wp_die();
+ }
+
+ $max_refund = wc_format_decimal($order->get_total() - $order->get_total_refunded(), 2);
+ $refund_amount_posted = wc_format_decimal($_POST['refund_amount'], 2);
+
+ if ($refund_amount_posted <= 0) {
+ wp_send_json_error(array('message' => __('Refund amount must be positive.', 'primer')));
+ wp_die();
+ }
+
+ if ($refund_amount_posted > $max_refund) {
+ wp_send_json_error(array('message' => sprintf(__('Refund amount %s exceeds maximum available amount %s.', 'primer'), wc_price($refund_amount_posted), wc_price($max_refund))));
+ wp_die();
+ }
+
+ $final_refund_amount = $refund_amount_posted;
+ $formatted_amount_clean = wp_strip_all_tags(wc_price($final_refund_amount));
+
+ $refund_reason = sprintf(__('Refund requested via Primer Payments Page by %1$s. Refunded amount: %2$s.', 'primer'), wp_get_current_user()->display_name, $formatted_amount_clean);
+
+ $refund = wc_create_refund(array(
+ 'amount' => $final_refund_amount,
+ 'reason' => $refund_reason,
+ 'order_id' => $order_id,
+ 'refund_payment' => true,
+ ));
+
+ if (is_wp_error($refund)) {
+ wp_send_json_error(array('message' => sprintf(__('Refund failed for order #%d. Error: %s', 'primer'), $order_id, $refund->get_error_message())));
+ wp_die();
+ }
+
+ wp_send_json_success(array(
+ 'message' => sprintf(__('Order #%d successfully refunded for %s.', 'primer'), $order_id, wc_price($final_refund_amount, array('currency' => $order->get_currency())))
+ ));
+ wp_die();
+}
+add_action('wp_ajax_primer_make_full_refund', 'primer_make_refund_from_page');
--- a/primer-mydata/admin/includes/primer-admin-options.php
+++ b/primer-mydata/admin/includes/primer-admin-options.php
@@ -38,6 +38,10 @@
protected $menu_title = '';
+ protected bool $payment_switch = false;
+
+
+
public function __construct() {
add_action('admin_menu', array(&$this, 'menu'));
add_action('wp_print_scripts', array(&$this, 'data_include_script'));
@@ -103,6 +107,13 @@
add_submenu_page(null, __('Receipts Logs', 'primer'), __('Receipts Logs', 'primer'), 'manage_options', 'primer_receipts_logs', array(&$this, "admin_page_receipt_log_display"));
add_submenu_page(null, __('Automation Logs', 'primer'), __('Automation Logs', 'primer'), 'manage_options', 'primer_receipts_logs_automation', array(&$this, "admin_page_receipt_log_automation_display"));
+
+ /// rsvirsky
+ if ($this->payment_switch && get_option('primer_generals')['primer_payments_gateway'] == 'on') {
+ add_submenu_page('wp_ajax_list_order', __('Payments', 'primer'), __('Payments', 'primer'), 'manage_options', 'primer_payments', array(&$this, "admin_page_payments_display"));
+ }
+ /// rsvirsky
+
add_submenu_page('wp_ajax_list_order', __('Settings', 'primer'), __('Settings', 'primer'), 'manage_options', 'primer_settings', array(&$this, "admin_settings_page_display"));
$this->options_pages[] = add_submenu_page('wp_ajax_list_order', __('License and General Settings', 'primer'), __('License and General Settings', 'primer'), 'manage_options', 'primer_licenses', array(&$this, "admin_settings_page_display"));
$this->options_pages[] = add_submenu_page(null, $this->menu_title, 'General Settings', 'manage_options', 'primer_generals', array($this, 'admin_settings_page_display'));
@@ -292,8 +303,25 @@
'on' => __('On', 'primer'),
),
'default' => 'on'
-
);
+
+ if ($this->payment_switch) {
+ $general_tab['fields'][] = array(
+ 'name' => __('Primer Payments', 'primer'),
+ 'id' => 'primer_payments_gateway',
+ 'type' => 'radio_inline',
+ 'options' => array(
+ 'off' => __('Off', 'primer'),
+ 'on' => __('On', 'primer'),
+ ),
+ );
+ } else {
+ $generals = get_option('primer_generals', array());
+ $generals['primer_payments_gateway'] = 'off';
+ update_option('primer_generals', $generals);
+ }
+
+
$general_tab['fields'][] = array(
'name' => __("Accept zero total value orders", 'primer'),
'desc' => __("If enabled the plugin will convert the orders that have 0 euros total value but the value send to AADE will be 0.02 euros(0.01 net value + 0.01 vat value), because AADE does not accept 0 values.", 'primer'),
@@ -533,6 +561,8 @@
)
);
+
+
if ($licenses['deliveryNote']) {
$mydata_tab['fields'][] = array(
'name' => __('Activation Dispatch Note', 'primer'),
@@ -567,6 +597,25 @@
);
}
+ /// rsvirsky
+ if ($this->payment_switch) {
+ $mydata_tab['fields'][] = array(
+ 'name' => __('Issue credit receipt/invoice if refund', 'primer'),
+ 'desc' => __('Enable/Disable issue credit receipt/invoice if refund. CAUTION! Ony if there is a receipt/invoice issued before for this order', 'primer'),
+ 'id' => 'issue_credit_on_refund',
+ 'type' => 'radio_inline',
+ 'options' => array(
+ 'off' => __('Off', 'primer'),
+ 'on' => __('On', 'primer'),
+ ),
+ );
+ } else {
+ $mydata_options_pay = get_option('primer_mydata', array());
+ $mydata_options_pay['issue_credit_on_refund'] = 'off';
+ update_option('primer_mydata', $mydata_options_pay);
+ }
+ /// rsvirsky
+
$mydata_tab['fields'][] = array(
'name' => __('MyData Package:', 'primer'),
'desc' => '',
@@ -1869,9 +1918,32 @@
'id' => 'export_select_invoice_type',
'type' => 'select',
'options' => $this->get_alpha_char(),
- 'after_row' => '</div></div>'
),
-
+ array(
+ 'name' => __('Payment Method', 'primer'),
+ 'id' => 'export_payment_method',
+ 'type' => 'select',
+ 'options' => $this->get_alpha_char(),
+ ),
+ array(
+ 'name' => __('UID', 'primer'),
+ 'id' => 'export_receipt_uid',
+ 'type' => 'select',
+ 'options' => $this->get_alpha_char(),
+ ),
+ array(
+ 'name' => __('Μ.ΑΡ.Κ.', 'primer'),
+ 'id' => 'export_receipt_mark',
+ 'type' => 'select',
+ 'options' => $this->get_alpha_char(),
+ ),
+ array(
+ 'name' => __('AUTHENTICATION CODE', 'primer'),
+ 'id' => 'export_authentication_code',
+ 'type' => 'select',
+ 'options' => $this->get_alpha_char(),
+ 'after_row' => '</div></div>'
+ ),
array(
'name' => __('Export settings', 'primer'),
'id' => 'export_settings_title',
@@ -1962,22 +2034,6 @@
),
array(
'name' => __(" ", 'primer'),
- 'desc' => __("Export to Path", 'primer'),
- 'id' => 'export_path',
- 'type' => 'checkbox',
- ),
- array(
- 'name' => __("Export path", 'primer'),
- 'desc' => __("Default export path is $export_dir_file. Check that the folder you enter has the correct write permissions.", 'primer'),
- 'id' => 'export_path_files',
- 'type' => 'text',
- 'attributes' => array(
- 'data-conditional-id' => 'export_path',
- 'data-conditional-value' => 'on',
- ),
- ),
- array(
- 'name' => __(" ", 'primer'),
'desc' => __("Send Email", 'primer'),
'id' => 'export_email_check',
'type' => 'checkbox',
@@ -2029,8 +2085,7 @@
'id' => 'license_key',
'type' => 'text_medium',
'default' => "$primer_license_key",
- 'after_field' => '<p>
-<a href="#" id="first_time" class="button-secondary">' . __('Activate', 'primer') . '</a></p>',
+ 'after_field' => '<p><a href="#" id="first_time" class="button-secondary">' . __('Activate', 'primer') . '</a></p>',
),
array(
'name' => __('Username', 'primer'),
@@ -3295,6 +3350,16 @@
$primer_receipt->handle_main_primer_receipt_admin_menu();
}
+ /// rsvirsky
+ public function admin_page_payments_display() {
+ if ($this->payment_switch && get_option('primer_generals')['primer_payments_gateway'] == 'on') {
+ include_once(PRIMER_PATH . 'admin/includes/primer-admin-payments-page.php');
+ $primer_receipt = new PrimerPaymentsPage();
+ $primer_receipt->handle_main_primer_payments_admin_menu();
+ }
+ }
+ /// rsvirsky
+
/**
*
* Resends a receipt to the customer.
@@ -5552,7 +5617,7 @@
$alpha_chars = array();
$alpha_chars[''] = __('Select', 'primer');
- foreach (range('A', 'U') as $item) {
+ foreach (range('A', 'X') as $item) {
$alpha_chars[$item] = $item;
}
--- a/primer-mydata/admin/includes/primer-admin-payments-page.php
+++ b/primer-mydata/admin/includes/primer-admin-payments-page.php
@@ -0,0 +1,549 @@
+<?php
+
+if (!class_exists('WP_List_Table')) {
+ require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
+}
+
+class PrimerPaymentsPage extends WP_List_Table {
+
+ public function __construct() {
+ parent::__construct(array(
+ 'singular' => 'payment',
+ 'plural' => 'payments',
+ 'ajax' => false
+ ));
+ }
+
+ function handle_main_primer_payments_admin_menu() {
+ do_action('primer_payments_menu_start');
+ $payments = get_piraeusbank_transactions();
+ $processed_order_ids = array();
+
+ wp_enqueue_script('jquery');
+
+ $search_query = isset($_GET['order_search']) ? sanitize_text_field($_GET['order_search']) : '';
+
+ $orders_data = array();
+ foreach ($payments as $payment) {
+ $order_id = $payment['order_id'];
+ if (in_array($order_id, $processed_order_ids)) {
+ continue;
+ }
+ $order = wc_get_order($order_id);
+ if ($order) {
+ $receipt_id = $order->get_meta('order_id_from_receipt');
+ $tickets_display = $order->get_transaction_id();
+ $refund_total = array();
+ $refunds = $order->get_refunds();
+
+ if (!empty($search_query)) {
+ $order_number = $order->get_order_number();
+ if ((string)$order_id !== $search_query && $order_number !== $search_query) {
+ continue;
+ }
+ }
+
+ $peiraeus_refunds = $order->get_meta('_piraeus_refunds', true);
+ if (!empty($peiraeus_refunds) && is_array($peiraeus_refunds)) {
+ $refund_messages = array();
+ foreach ($peiraeus_refunds as $refund) {
+ if (!is_array($refund) || !isset($refund['amount'])) {
+ continue;
+ }
+ $refund_messages[] = sprintf(__('Refunded amount: %1$s <br>Date: %2$s<br>Transaction ID: %3$s <br>Trace ID: %4$s', 'primer'),
+ wc_price($refund['amount'], array('currency' => $order->get_currency())),
+ date('Y-m-d H:i:s', strtotime($refund['date'])), $refund['transaction_id'] ?? 'N/A', $refund['trace_id'] ?? 'N/A');
+ }
+ $peiraeus_refunds_message = !empty($refund_messages) ? implode('<br><br>', $refund_messages) : 'No refunds found.';
+ } else {
+ $peiraeus_refunds_message = '';
+ }
+
+ if (!empty($refunds)) {
+ foreach ($refunds as $refund) {
+ if (is_a($refund, 'WC_Order_Refund')) {
+ $refund_total[] = $refund->get_amount();
+ }
+ }
+ }
+
+ $has_refunds = !empty($order->get_refunds());
+ $pre_message = $has_refunds ? (array_sum($refund_total) == $order->get_total() ? 'Refunded' : 'Partially Refunded') : 'Paid';
+ $refund_color = $pre_message == 'Refunded' ? 'red' : ($pre_message == 'Partially Refunded' ? 'orange' : 'green');
+
+ $refund_nonce = wp_create_nonce('primer_refund_nonce');
+ $order_total_paid = $order->get_total() - $order->get_total_refunded();
+ $eligible_statuses = apply_filters('woocommerce_valid_order_statuses_for_refund', array('processing', 'completed', 'on-hold', 'pending', 'failed', 'cancelled', 'refunded', 'trash', 'custom'));
+ $show_refund_button = ($order_total_paid > 0.001) && in_array($order->get_status(), $eligible_statuses);
+
+ if ($show_refund_button) {
+ $order_id_esc = esc_attr($order->get_id());
+ $refund_nonce_esc = esc_attr($refund_nonce);
+ $button_text = esc_html(__('Make Refund', 'primer'));
+ $total_paid_esc = esc_attr(wc_format_decimal($order_total_paid, 2));
+ $refund_button = "<button type='button' class='button button-primary' data-max-refund='{$total_paid_esc}' onclick="makeRefund({$order_id_esc}, this, '{$refund_nonce_esc}')"> {$button_text} </button>";
+ } else {
+ $refund_button = '';
+ }
+
+ $orders_data[] = array(
+ 'order_id' => $order->get_id(),
+ 'order_number' => $order->get_order_number(),
+ 'customer_name' => trim($order->get_billing_first_name() . ' ' . $order->get_billing_last_name()),
+ 'receipt' => $receipt_id,
+ 'date' => $payment['timestamp'],
+ 'status' => $order->get_status(),
+ 'total' => $order->get_formatted_order_total(),
+ 'refunds' => $peiraeus_refunds_message,
+ 'trans_ticket' => $tickets_display,
+ 'merch_ref' => $payment['merch_ref'],
+ 'refund_message' => $pre_message,
+ 'refund_color' => $refund_color,
+ 'refund' => $refund_button
+ );
+ $processed_order_ids[] = $order_id;
+ }
+ }
+
+ $orders_data = $this->apply_filters($orders_data);
+
+ $total_items = count($orders_data);
+ $screen = get_current_screen();
+ $per_page_option = $screen ? ($screen->get_option('per_page') ?: 'per_page') : 'per_page';
+ $per_page = absint(get_user_option($per_page_option) ?: 20);
+ $current_page = $this->get_pagenum();
+ $offset = max(0, ($current_page - 1) * $per_page);
+ $current_page_orders = array_slice($orders_data, $offset, $per_page);
+
+ $this->set_pagination_args(array(
+ 'total_items' => $total_items,
+ 'per_page' => $per_page,
+ 'total_pages' => ceil($total_items / $per_page)
+ ));
+ $orders_data = $current_page_orders;
+
+ ?>
+ <div class="wrap">
+ <h1 class="page-payments-head"><?php _e('Payments', 'primer'); ?></h1>
+
+ <form method="get" style="display: inline-block; float: right;">
+ <?php
+ $allowed_params = array('page', 'status', 'date_from', 'date_to');
+ foreach ($_GET as $key => $value) {
+ if (in_array($key, $allowed_params)) {
+ printf('<input type="hidden" name="%s" value="%s" />', esc_attr($key), esc_attr($value));
+ }
+ }
+ ?>
+ <p class="search-box" style="float: right; margin: 0;">
+ <label class="screen-reader-text" for="order-search-input"><?php _e('Search by Order ID:', 'primer'); ?></label>
+ <input type="search" id="order-search-input" name="order_search" value="<?php echo esc_attr($search_query); ?>" placeholder="<?php esc_attr_e('', 'primer'); ?>">
+ <?php submit_button(__('Search', 'primer'), 'button', 'order_search_submit', false); ?>
+ </p>
+ </form>
+
+ </br></br></br>
+
+ <?php $this->render_filters(); ?>
+
+ <?php if ($total_items > 20) { ?>
+ <div style="margin-bottom: 10px; float: right; "><?php echo $this->pagination('top'); ?></div>
+ <?php } ?>
+
+ <?php if (!empty($orders_data)) : ?>
+ <table class="wp-list-table widefat fixed striped table-view-list ">
+ <thead>
+ <tr>
+ <th><?php _e('Order', 'primer'); ?></th>
+ <th><?php _e('Transaction ID', 'primer'); ?></th>
+ <th><?php _e('Merchant Ref', 'primer'); ?></th>
+ <th><?php _e('Receipts', 'primer'); ?></th>
+ <th><?php _e('Payment Date', 'primer'); ?></th>
+ <th><?php _e('Order Status', 'primer'); ?></th>
+ <th><?php _e('Total', 'primer'); ?></th>
+ <th><?php _e('Refunds', 'primer'); ?></th>
+ <th><?php _e('Refund', 'primer'); ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <?php foreach ($orders_data as $order) : ?>
+ <tr>
+ <td>
+ <a style="font-weight: 700;" href="<?php echo admin_url('post.php?post=' . $order['order_id'] . '&action=edit'); ?>">
+ #<?php echo esc_html($order['order_number']); ?>
+ </a>
+ <?php echo '<p style="color:' . $order['refund_color'] . '; margin: 0;font-weight: 500">' . __($order['refund_message'], 'primer') . '</p>'; ?>
+ <p><?php echo esc_html($order['customer_name']); ?></p>
+ </td>
+ <td>
+ <?php
+ if (is_array($order['trans_ticket'])) {
+ echo implode('<br>', array_map('esc_html', $order['trans_ticket']));
+ } else {
+ echo esc_html($order['trans_ticket']);
+ }
+ ?>
+ </td>
+ <td><?php echo esc_html($order['merch_ref']); ?></td>
+ <td>
+ <?php if (!empty($order['receipt'])):
+ $receipt_url = home_url('primer_receipt/receipt-for-order-' . $order['order_number'] . '/?receipt=view');
+ if (!empty($trasmission_failure)) {
+ $receipt_url = home_url('primer_receipt/receipt-for-order-' . $order['order_number'] . '-failed/?receipt=view');
+ }
+ ?>
+ <a href="<?php echo esc_url($receipt_url); ?>" target="_blank" class="payments-links">
+ <?php echo _e('Issued', 'primer'); ?>
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="15" viewBox="0 0 16 16" fill="#bababa" style="margin-top: 2px;">
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M2 0H14V16H12L10 14L8 16L6 14L4 16H2V0ZM5 4H11V6H5V4ZM11 8H5V10H11V8Z"/>
+ </svg>
+ </a>
+ <?php else: ?>
+ <span class="payment-weight-400"> <?php _e('Not Issued', 'primer') ?></span>
+ <?php endif; ?>
+ </td>
+ <td><?php echo esc_html($order['date']); ?></td>
+ <td><?php echo esc_html(wc_get_order_status_name($order['status'])); ?></td>
+ <td class="payment-weight-500"><?php echo $order['total']; ?></td>
+ <td style="font-size: 12px; padding: 8px 0;"><?php echo $order['refunds']; ?></td>
+ <td style="vertical-align: middle; text-align: center;"><?php echo $order['refund']; ?></td>
+ </tr>
+ <?php endforeach; ?>
+ </tbody>
+ </table>
+
+ <?php if ($total_items > 20) { ?>
+ <div style="margin-top: 10px; float: right; "><?php echo $this->pagination('button'); ?></div>
+ <?php } ?>
+
+ <?php else : ?>
+ <table class="wp-list-table widefat fixed striped table-view-list ">
+ <thead>
+ <tr>
+ <th><?php _e('Order', 'primer'); ?></th>
+ <th><?php _e('Transaction ID', 'primer'); ?></th>
+ <th><?php _e('Merchant Ref', 'primer'); ?></th>
+ <th><?php _e('Receipts', 'primer'); ?></th>
+ <th><?php _e('Payment Date', 'primer'); ?></th>
+ <th><?php _e('Order Status', 'primer'); ?></th>
+ <th><?php _e('Total', 'primer'); ?></th>
+ <th><?php _e('Refunds', 'primer'); ?></th>
+ <th><?php _e('Refund', 'primer'); ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td colspan="9" style="text-align: center; padding: 20px;">
+ <?php _e('No payments transactions found.', 'primer'); ?>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <?php endif; ?>
+ </div>
+
+ <script type="text/javascript">
+ let currentOrderId;
+ let currentNonce;
+ let currentMaxRefund;
+ let currentButton;
+
+ function makeRefund(orderId, button, nonceValue) {
+ if (!orderId || !button || !nonceValue) {
+ console.error('Invalid parameters for makeRefund: orderId, button, or nonceValue is missing.');
+ return;
+ }
+ currentOrderId = orderId;
+ currentNonce = nonceValue;
+ currentButton = button;
+ const maxRefundText = button.getAttribute('data-max-refund');
+ currentMaxRefund = parseFloat(maxRefundText);
+ jQuery('#modal-order-number').text(`#${orderId}`);
+ jQuery('#modal-max-refund').text(maxRefundText);
+ jQuery('#refund-amount-input').val(maxRefundText);
+ jQuery('#refund-error-message').hide().text('');
+ jQuery('#refund-modal-overlay').fadeIn(300);
+ }
+
+ function processRefundAjax(refundAmount) {
+ jQuery('#refund-modal-overlay').fadeOut(100);
+ const originalButton = {
+ html : currentButton.innerHTML,
+ disabled: currentButton.disabled
+ };
+ currentButton.disabled = true;
+ currentButton.innerHTML = '<span class="spinner is-active" style="float: none; margin: 0 5px 0 0;"></span> ' + 'Processing...';
+ jQuery.ajax({
+ url : ajaxurl,
+ type : 'POST',
+ contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
+ data : {
+ action : 'primer_make_full_refund',
+ order_id : currentOrderId,
+ nonce : currentNonce,
+ refund_amount: refundAmount.toFixed(2)
+ },
+ dataType : 'json',
+ success : function (response) {
+ const notice = document.createElement('div');
+ if (response.success) {
+ notice.className = 'notice notice-success is-dismissible';
+ notice.innerHTML = `<p>${response.data.message}</p>`;
+ document.querySelector('.wrap h1').after(notice);
+ setTimeout(() => window.location.reload(), 2000);
+ } else {
+ const errorMessage = response.data?.message || 'Error processing refund.';
+ notice.className = 'notice notice-error is-dismissible';
+ notice.innerHTML = `<p>${errorMessage}</p>`;
+ document.querySelector('.wrap h1').after(notice);
+ }
+ },
+ error : function (xhr, status, error) {
+ console.error('AJAX Error:', xhr.responseText);
+ const notice = document.createElement('div');
+ notice.className = 'notice notice-error is-dismissible';
+ notice.innerHTML = `<p>System Error: ${status} ${error}. Check console.</p>`;
+ document.querySelector('.wrap h1').after(notice);
+ },
+ complete : function () {
+ if (!document.querySelector('.notice-success')) {
+ currentButton.disabled = originalButton.disabled;
+ currentButton.innerHTML = originalButton.html;
+ }
+ }
+ });
+ }
+
+ document.addEventListener('DOMContentLoaded', function () {
+ const pagedInput = document.querySelector('input[name="paged"]');
+ if (pagedInput) {
+ pagedInput.addEventListener('keydown', function (e) {
+ if (e.key === 'Enter') {
+ e.preventDefault();
+ const newPage = parseInt(this.value, 10);
+ if (isNaN(newPage) || newPage < 1) {
+ return;
+ }
+ const form = this.closest('form');
+ if (form) {
+ form.submit();
+ } else {
+ const url = new URL(window.location.href);
+ url.searchParams.set('paged', newPage);
+ window.location.href = url.toString();
+ }
+ }
+ });
+ }
+ const dateFromInput = document.getElementById('date_from');
+ const dateToInput = document.getElementById('date_to');
+ const today = new Date();
+
+ function formatDate(date) {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, '0');
+ const day = String(date.getDate()).padStart(2, '0');
+ return `${year}-${month}-${day}`;
+ }
+
+ const maxDate = formatDate(today);
+ const minDate = '2020-01-01';
+ if (dateFromInput) {
+ dateFromInput.min = minDate;
+ dateFromInput.max = maxDate;
+ }
+ if (dateToInput) {
+ dateToInput.min = minDate;
+ dateToInput.max = maxDate;
+ }
+ const modalOverlay = jQuery('#refund-modal-overlay');
+ const refundInput = jQuery('#refund-amount-input');
+ const errorMsg = jQuery('#refund-error-message');
+ jQuery('.cancel-refund').on('click', function () {
+ modalOverlay.fadeOut(100);
+ });
+ jQuery('.confirm-refund').on('click', function () {
+ const amount = parseFloat(refundInput.val());
+ errorMsg.hide().text('');
+
+ if (isNaN(amount) || amount <= 0) {
+ errorMsg.text('<?php _e('Please enter a valid positive number for the refund amount.', 'primer'); ?>').fadeIn(200);
+ return;
+ }
+ if (amount > currentMaxRefund) {
+ const errorMessage = '<?php _e('The requested refund amount (%s €), exceeds the maximum allowed refund amount (%s €). Please adjust the value.', 'primer'); ?>';
+ const translatedError = errorMessage.replace('%s', amount.toFixed(2)).replace('%s', currentMaxRefund.toFixed(2));
+ errorMsg.text(translatedError).fadeIn(200);
+ return;
+ }
+ processRefundAjax(amount);
+ });
+ });
+ </script>
+ <?php
+
+ echo $this->render_refund_modal();
+ }
+
+ protected function render_filters() {
+ $date_from = isset($_GET['date_from']) ? sanitize_text_field($_GET['date_from']) : '';
+ $date_to = isset($_GET['date_to']) ? sanitize_text_field($_GET['date_to']) : '';
+ $receipt = isset($_GET['receipt_filter']) ? sanitize_key($_GET['receipt_filter']) : '';
+ $refund = isset($_GET['refund_filter']) ? sanitize_key($_GET['refund_filter']) : '';
+ $status = isset($_GET['status_filter']) ? sanitize_key($_GET['status_filter']) : '';
+
+ $order_statuses = wc_get_order_statuses();
+
+ ?>
+ <form method="get">
+ <input type="hidden" name="page" value="<?php echo esc_attr($_REQUEST['page']); ?>"/>
+ <div class="alignleft actions filters-payments" style="margin-bottom: 10px;">
+ <label for="date_from" class="payment-filers-labels-no-margin"><?php _e('Date From:', 'primer'); ?></label>
+ <input type="date" name="date_from" id="date_from" value="<?php echo esc_attr($date_from); ?>"/>
+
+ <label for="date_to" class="payment-filers-labels"><?php _e('Date To:', 'primer'); ?></label>
+ <input type="date" name="date_to" id="date_to" value="<?php echo esc_attr($date_to); ?>"/>
+
+ <label for="receipt_filter" class="payment-filers-labels"><?php _e('', 'primer'); ?></label>
+ <select name="receipt_filter" id="receipt_filter">
+ <option value=""><?php _e('All receipts statuses', 'primer'); ?></option>
+ <option value="issued" <?php selected($receipt, 'issued'); ?>><?php _e('Issued', 'primer'); ?></option>
+ <option value="not_issued" <?php selected($receipt, 'not_issued'); ?>><?php _e('Not Issued', 'primer'); ?></option>
+ </select>
+
+ <label for="refund_filter" class="payment-filers-labels"><?php _e('', 'primer'); ?></label>
+ <select name="refund_filter" id="refund_filter">
+ <option value=""><?php _e('All payments status', 'primer'); ?></option>
+ <option value="paid" <?php selected($refund, 'paid'); ?>><?php _e('Paid', 'primer'); ?></option>
+ <option value="partially_refunded" <?php selected($refund, 'partially_refunded'); ?>><?php _e('Partially Refunded', 'primer'); ?></option>
+ <option value="refunded" <?php selected($refund, 'refunded'); ?>><?php _e('Refunded', 'primer'); ?></option>
+ </select>
+
+ <label for="status_filter" class="payment-filers-labels"><?php _e('', 'primer') ?></label>
+ <select name="status_filter" id="status_filter">
+ <option value=""><?php _e('All order statuses', 'primer') ?></option>
+ <?php
+ foreach ($order_statuses as $key_with_prefix => $label) :$key = str_replace('wc-', '', $key_with_prefix); ?>
+ <option value="<?php echo esc_attr($key); ?>" <?php selected($status, $key); ?>><?php echo esc_html($label); ?></option>
+ <?php endforeach; ?>
+ </select>
+
+ <div class="payments-button-filters">
+ <?php submit_button(__('Filter', 'primer'), 'button', 'filter_action', false); ?>
+ </div>
+ </div>
+ </form>
+ <?php
+ }
+
+ protected function apply_filters($orders_data) {
+ $date_from = isset($_GET['date_from']) ? sanitize_text_field($_GET['date_from']) : null;
+ $date_to = isset($_GET['date_to']) ? sanitize_text_field($_GET['date_to']) : null;
+ $receipt = isset($_GET['receipt_filter']) ? sanitize_key($_GET['receipt_filter']) : null;
+ $refund = isset($_GET['refund_filter']) ? sanitize_key($_GET['refund_filter']) : null;
+ $status = isset($_GET['status_filter']) ? sanitize_key($_GET['status_filter']) : null;
+
+ if (empty($date_from) && empty($date_to) && empty($receipt) && empty($refund) && empty($status)) {
+ return $orders_data;
+ }
+
+ $filtered_data = array_filter($orders_data, function($order) use ($date_from, $date_to, $receipt, $refund, $status) {
+ $pass_date = $pass_receipt = $pass_refund = $pass_status = true;
+
+ $order_date_timestamp = strtotime($order['date']);
+
+ if ($date_from) {
+ $from_timestamp = strtotime($date_from);
+ if ($order_date_timestamp < $from_timestamp) {
+ $pass_date = false;
+ }
+ }
+
+ if ($pass_date && $date_to) {
+ $to_timestamp = strtotime($date_to) + (24 * 60 * 60);
+ if ($order_date_timestamp >= $to_timestamp) {
+ $pass_date = false;
+ }
+ }
+
+ if ($receipt) {
+ $is_issued = !empty($order['receipt']);
+ switch ($receipt) {
+ case 'issued':
+ $pass_receipt = $is_issued;
+ break;
+ case 'not_issued':
+ $pass_receipt = !$is_issued;
+ break;
+ }
+ }
+
+ if ($refund) {
+ $order_refund_message = strtolower(str_replace(' ', '_', $order['refund_message']));
+ switch ($refund) {
+ case 'paid':
+ $pass_refund = ($order_refund_message === 'paid');
+ break;
+ case 'partially_refunded':
+ $pass_refund = ($order_refund_message === 'partially_refunded');
+ break;
+ case 'refunded':
+ $pass_refund = ($order_refund_message === 'refunded');
+ break;
+ }
+ }
+
+ if ($status) {
+ $order_status_slug = str_replace('wc-', '', $order['status']);
+ $pass_status = $order_status_slug === $status;
+ }
+
+ return $pass_date && $pass_receipt && $pass_refund && $pass_status;
+ });
+
+ return $filtered_data;
+ }
+
+ public function render_refund_modal() {
+ $currency_symbol = get_woocommerce_currency_symbol();
+ ob_start();
+ ?>
+ <div id="refund-modal-overlay">
+ <div id="refund-modal">
+ <h3><?php _e('Process Refund', 'primer'); ?></h3>
+ <p><?php _e('Order:', 'primer'); ?> <strong id="modal-order-number">N/A</strong></p>
+ <p><?php _e('Max Refund:', 'primer'); ?> <strong id="modal-max-refund">N/A</strong></p>
+ <hr>
+ <p class="payments-enter-amount"><?php _e('Enter Amount:', 'primer'); ?></p>
+ <div class="refund-amount-input-div">
+ <span style="font-size: 1.2em;"><?php echo esc_html($currency_symbol); ?></span>
+ <input type="number" id="refund-amount-input" step="0.01" min="0.01">
+ </div>
+ <p id="refund-error-message"></p>
+ <div class="refund-actions">
+ <button type="button" class="button button-secondary cancel-refund"><?php _e('Cancel', 'primer'); ?></button>
+ <button type="button" class="button button-primary confirm-refund"><?php _e('Confirm Refund', 'primer'); ?></button>
+ </div>
+ </div>
+ </div>
+ <?php
+ return ob_get_clean();
+ }
+
+}
+
+new PrimerPaymentsPage();
+
+function get_piraeusbank_transactions() {
+ global $wpdb;
+ $table_name = $wpdb->prefix . 'piraeusbank_transactions';
+
+ if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") !== $table_name) {
+ return array();
+ }
+
+ $query = "SELECT * FROM $table_name ORDER BY timestamp DESC";
+
+ return $wpdb->get_results($query, ARRAY_A);
+}
--- a/primer-mydata/admin/includes/primer-admin-table.php
+++ b/primer-mydata/admin/includes/primer-admin-table.php
@@ -616,6 +616,9 @@
$invoiceType = '';
$receipt_log_value = '';
$total = '';
+ $series = '';
+ $serie = '';
+ $number = '';
$response = null;
$response_message = null;
$response_code = null;
@@ -624,11 +627,33 @@
$Vat_exemption_categories = $create_json_instance->getVatExemptionCategories();
$Vat_exemption_categories_en = $create_json_instance->getVatExemptionCategoriesEn();
$i = 1;
+
while ($i <= 1) {
$mydata_options = get_option('primer_mydata');
- $serie = get_post_meta($order_id, '_primer_receipt_series', true) != null ? get_post_meta($order_id, '_primer_receipt_series', true) != null : '';
$series = '';
- $number = get_post_meta($order_id, '_primer_receipt_number', true) != null ? get_post_meta($order_id, '_primer_receipt_number', true) : '';
+
+ $transmission_failure = $order->get_meta('transmission_failure_check');
+ $post_id_failed = $order->get_meta('order_id_from_receipt');
+ $already_issued = get_post_meta($post_id_failed, 'response_invoice_mark', true);
+
+ if (($transmission_failure == 1 || $transmission_failure == 3) && empty($already_issued)) {
+ $serie = get_post_meta($post_id_failed, '_primer_receipt_series', true);
+ $number = get_post_meta($post_id_failed, '_primer_receipt_number', true);
+
+ $issue_date = new DateTime("now", new DateTimeZone("Europe/Athens"));
+ $order_datetime_co = $order->get_meta('order_datetime_failed');
+
+ if ($order_datetime_co != '') {
+ $issue_date = new DateTime($order_datetime_co, new DateTimeZone("Europe/Athens"));
+ }
+
+ $gr_time = $issue_date->format('Y-m-d');
+ $invoice_time = $issue_date->format('H:i');
+ } else {
+ $serie = get_post_meta($order_id, '_primer_receipt_series', true) != null ? get_post_meta($order_id, '_primer_receipt_series', true) != null : '';
+ $number = get_post_meta($order_id, '_primer_receipt_number', true) != null ? get_post_meta($order_id, '_primer_receipt_number', true) : '';
+ }
+
$invoice_data = $create_json_instance->create_invoice($user_id, $order_id, $total_vat_number, $mydata_options, $primer_license_data,
$total, $series, $serie, $number, $currency, $currency_symbol, $user_data, $insert_taxonomy,
$classificationCategory, $classificationCategory_en, $response_data, $receipt_log_value, $receipt_log_value_array,
--- a/primer-mydata/includes/class-primer-cron.php
+++ b/primer-mydata/includes/class-primer-cron.php
@@ -8,21 +8,23 @@
use PrimerDompdfDompdf;
use PhpOfficePhpSpreadsheetSpreadsheet;
use PhpOfficePhpSpreadsheetWriterXlsx;
+use PhpOfficePhpSpreadsheetStyleNumberFormat;
+use PhpOfficePhpSpreadsheetCellDataType;
class PrimerCron {
- public function __construct() {
- add_action('primer_cron_save_settings', array($this, 'primer_save_automation_data'));
+ public function __construct() {
+ add_action('primer_cron_save_settings', array($this, 'primer_save_automation_data'));
add_action('primer_cron_process', array($this, 'convert_order_to_invoice'), 1);
add_action('primer_cron_process_failed', array($this, 'convert_order_to_invoice_failed'), 1);
add_action('primer_cron_process_credit_failed', array($this, 'primer_cancel_invoice_cron'), 1);
- add_action('wp_ajax_primer_fire_cron', array($this, 'ajax_fire_cron' ));
- add_action('primer_cron_save_settings', array($this, 'primer_save_export_data'));
- add_action('primer_cron_export_process', array($this, 'export_invoice_to_report'));
- add_action('wp_ajax_export_invoice_to_report', array($this, 'export_invoice_to_report'));
+ add_action('wp_ajax_primer_fire_cron', array($this, 'ajax_fire_cron'));
+ add_action('primer_cron_save_settings', array($this, 'primer_save_export_data'));
+ add_action('primer_cron_export_process', array($this, 'export_invoice_to_report'));
+ add_action('wp_ajax_export_invoice_to_report', array($this, 'export_invoice_to_report'));
add_action('wp_ajax_primer_get_woocommerce_tax_rates', array($this, 'primer_get_woocommerce_tax_rates'));
add_action('primer_cron_primer_license_remaining', array(&$this, 'primer_cron_license_remaining'), 1);
- }
+ }
public function primer_save_automation_data() {
$next_timestamp = wp_next_scheduled('primer_cron_process');
@@ -212,6 +214,7 @@
'return' => 'ids',
'limit' => $limit_automation_orders,
'order' => 'DESC',
+// 'min_total' => 0.01,
'meta_query' => array(
array(
'key' => 'receipt_status',
@@ -292,9 +295,7 @@
$insert_taxonomy = 'receipt_status';
$receipt_log_value_array = array();
- $invoice_data = $order_country = $order_invoice_type = $order_vatNumber = $user_order_email = $currency = $currency_symbol = $user_id
- = $order_total_price = $user_full_name = $user_data = $serie = $series = $number = $invoice_time = $invoice_term = $response_data = $invoiceType
- = $receipt_log_value = $total = '';
+ $invoice_data = $order_country = $order_invoice_type = $order_vatNumber = $user_order_email = $currency = $currency_symbol = $user_id = $order_total_price = $user_full_name = $user_data = $serie = $series = $number = $invoice_time = $invoice_term = $response_data = $invoiceType = $receipt_log_value = $total = '';
$response_to_array = $response_code = $response_message = $response = null;
$create_json_instance = new Create_json();
@@ -308,10 +309,7 @@
$serie = get_post_meta($order_id, '_primer_receipt_series', true) != null ? get_post_meta($order_id, '_primer_receipt_series', true) != null : '';
$series = '';
$number = get_post_meta($order_id, '_primer_receipt_number', true) != null ? get_post_meta($order_id, '_primer_receipt_number', true) : '';
- $invoice_data = $create_json_instance->create_invoice($user_id, $order_id, $total_vat_number, $mydata_options, $primer_license_data, $total, $series, $serie,
- $number, $currency, $currency_symbol, $user_data, $insert_taxonomy, $classificationCategory, $classificationCategory_en, $response_data, $receipt_log_value,
- $receipt_log_value_array, $receipt_log_id, $invoice_term, $gr_time, $invoice_time, $order_total_price, $order_invoice_type, $order_vatNumber, $user_order_email,
- $order_country, $user_full_name, $primer_smtp, $log_ids, $callingFunction, $invoiceType, $classificationType);
+ $invoice_data = $create_json_instance->create_invoice($user_id, $order_id, $total_vat_number, $mydata_options, $primer_license_data, $total, $series, $serie, $number, $currency, $currency_symbol, $user_data, $insert_taxonomy, $classificationCategory, $classificationCategory_en, $response_data, $receipt_log_value, $receipt_log_value_array, $receipt_log_id, $invoice_term, $gr_time, $invoice_time, $order_total_price, $order_invoice_type, $order_vatNumber, $user_order_email, $order_country, $user_full_name, $primer_smtp, $log_ids, $callingFunction, $invoiceType, $classificationType);
$curl_args['body'] = json_encode($invoice_data);
$response = wp_remote_post($url, $curl_args);
$response_message = wp_remote_retrieve_body($response);
@@ -489,6 +487,15 @@
update_post_meta($order_log_id, 'receipt_log_error', $receipt_log_value);
}
}
+ $post_issued = 'issued';
+ update_post_meta($post_id, 'receipt_status', $post_issued);
+ $order->update_meta_data('receipt_status', $post_issued);
+ add_post_meta($post_id, 'receipt_client', $user_data);
+ add_post_meta($post_id, 'receipt_client_id', $user_id);
+ add_post_meta($post_id, 'receipt_price', $order_total_price . ' ' . $currency_symbol);
+ $order->update_meta_data('transmission_failure_check', 2);
+ $order->update_meta_data('failed_48', 'no');
+ $order->save();
primer_generate_qr($post_id, $generated_uid);
@@ -624,13 +631,6 @@
$output = $dompdf->output();
file_put_contents($upload_dir . '/email-invoices/' . $post_name . '.pdf', $output);
$attachments = $upload_dir . '/email-invoices/' . $post_name . '.pdf';
- $post_issued = 'issued';
- update_post_meta($post_id, 'receipt_status', $post_issued);
- $order->update_meta_data('receipt_status', $post_issued);
- $order->save();
- add_post_meta($post_id, 'receipt_client', $user_data);
- add_post_meta($post_id, 'receipt_client_id', $user_id);
- add_post_meta($post_id, 'receipt_price', $order_total_price . ' ' . $currency_symbol);
$primer_smtp_options = get_option('primer_emails');
if (!empty($primer_smtp_options['email_subject'])) {
@@ -644,7 +644,6 @@
$client_first_name = $order->get_meta('_billing_first_name');
$client_last_name = $order->get_meta('_billing_last_name');
$client_email = $order->get_meta('_billing_email');
- $country = $order->get_meta('_billing_country');
$streetAdress = $order->get_meta('_billing_address_1');
$townCity = $order->get_meta('_billing_city');
$phone = $order->get_meta('_billing_phone');
@@ -716,22 +715,18 @@
update_post_meta($order_log_id, 'receipt_log_automation_email_error', $email_logs);
update_post_meta($order_log_id, 'receipt_log_automation_total_status', 'only_issued');
}
-
- $order->update_meta_data('transmission_failure_check', 2);
- $order->update_meta_data('failed_48', 'no');
- $order->save();
$mydata_options['timeout_check_48'] = 0;
if (($response_code > 500 || $is_timeout) && $general_settings['primer_cron_transmission_failure'] == 'on') {
if ($response_code == 512) {
$receipt_log_value .= $error_messages['unable_connect_provider_aade'];
- $receipt_log_value_array[] = $error_messages['unable_connect_provider_aade'];
+ $receipt_log_value_array[] = $error_messages['unable_connect_provider_aade'];
$order->update_meta_data('transmission_failure_check', 3);
$order->save();
update_post_meta($receipt_log_id, 'receipt_log_error', $receipt_log_value_array);
} else {
$receipt_log_value .= $error_messages['unable_connect_entity_provider'];
- $receipt_log_value_array[] = $error_messages['unable_connect_entity_provider'];
+ $receipt_log_value_array[] = $error_messages['unable_connect_entity_provider'];
$order->update_meta_data('transmission_failure_check', 1);
$order->save();
update_post_meta($receipt_log_id, 'receipt_log_error', $receipt_log_value_array);
@@ -934,24 +929,19 @@
break;
}
- $order_country = $order_invoice_type = $order_vatNumber = $user_order_email = $currency = $currency_symbol = $user_id
- = $order_total_price = $user_full_name = $user_data = $invoice_term = $response_data = $invoiceType
- = $receipt_log_value = $total = $series = '';
+ $order_country = $order_invoice_type = $order_vatNumber = $user_order_email = $currency = $currency_symbol = $user_id = $order_total_price = $user_full_name = $user_data = $invoice_term = $response_data = $invoiceType = $receipt_log_value = $total = $series = '';
$receipt_log_value_array = array();
- $insert_taxonomy = 'receipt_status';
- $serie = get_post_meta($post_id_failed, '_primer_receipt_series', true);
- $number = get_post_meta($post_id_failed, '_primer_receipt_number', true);
- $connectionFailedMessage = get_post_meta($post_id_failed, 'connection_fail_message', true);
+ $insert_taxonomy = 'receipt_status';
+ $serie = get_post_meta($post_id_failed, '_primer_receipt_series', true);
+ $number = get_post_meta($post_id_failed, '_primer_receipt_number', true);
+ $connectionFailedMessage = get_post_meta($post_id_failed, 'connection_fail_message', true);
$create_json_instance = new Create_json();
$Vat_exemption_categories = $create_json_instance->getVatExemptionCategories();
$Vat_exemption_categories_en = $create_json_instance->getVatExemptionCategoriesEn();
- $invoice_data = $create_json_instance->create_invoice($us