Skip to content

Commit 4a4328f

Browse files
committed
Add payment mapping configuration and validation for WooCommerce gateways
- Introduced a new section for payment mapping configuration in settings. - Mapped WooCommerce payment methods to Alegra bank accounts. - Implemented strict validation to ensure complete mapping for active gateways. - Updated invoice generation to utilize mapped payment methods and bank accounts. - Added support for editing mappings of inactive gateways with previous configurations. - Included automated tests for payment mapping resolution and settings validation. - Bumped version to 0.1.0 and updated compatibility details in readme.
1 parent eca6632 commit 4a4328f

9 files changed

Lines changed: 773 additions & 23 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
/wordpress/
33
/node_modules
44
.env
5+
phpunit.xml
56
.phpunit.result.cache

includes/admin/other_settings.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@
1818
return $new_tax;
1919
});
2020

21+
$bank_accounts = $this->get_data_options('Integration_Alegra_WC::get_bank_accounts', function($new_account, $account){
22+
if(($account["status"] ?? '') !== 'active') return $new_account;
23+
$account_id = (string) ($account["id"] ?? '');
24+
if(!$account_id) return $new_account;
25+
26+
$account_name = $account["name"] ?? $account_id;
27+
$account_number = !empty($account["number"]) ? " ({$account["number"]})" : '';
28+
$new_account[$account_id] = "{$account_name}{$account_number}";
29+
30+
return $new_account;
31+
});
32+
33+
$active_gateways = Integration_Alegra_WC::get_wc_payment_gateways(true);
34+
$all_gateways = Integration_Alegra_WC::get_wc_payment_gateways();
35+
2136
return [
2237
'invoice' => array(
2338
'title' => __( 'Facturas de ventas' ),
@@ -58,6 +73,21 @@
5873
'description' => __( 'Centro de costo asociado a la factura' ),
5974
'desc_tip' => false
6075
),
76+
'payment_methods' => array(
77+
'title' => __( 'Métodos de pago' ),
78+
'type' => 'title',
79+
'description' => __( 'Relacione cada método de pago activo de WooCommerce con el método de pago y la cuenta bancaria de Alegra.' )
80+
),
81+
'payment_gateways_mapping' => array(
82+
'title' => __( 'Mapeo de métodos de pago' ),
83+
'type' => 'payment_mappings_table',
84+
'payment_methods' => Integration_Alegra_WC::PAYMENTS_METHODS,
85+
'bank_accounts' => $bank_accounts,
86+
'active_gateways' => $active_gateways,
87+
'all_gateways' => $all_gateways,
88+
'description' => __( 'Debe configurar método de pago y cuenta bancaria para cada gateway activo. Los gateways inactivos con mapeo guardado también se muestran para edición.' ),
89+
'desc_tip' => false
90+
),
6191
'client' => array(
6292
'title' => __( 'Clientes' ),
6393
'type' => 'title'

includes/class-alegra-integration-wc.php

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,253 @@ public function get_data_options(string $method, callable $callback)
113113
$data = isset($_GET['section']) && $_GET['section'] === $this->id ? $method() : [];
114114
return array_reduce($data, $callback, []);
115115
}
116+
117+
public function generate_payment_mappings_table_html($key, $data): string
118+
{
119+
$defaults = [
120+
'title' => '',
121+
'description' => '',
122+
'payment_methods' => [],
123+
'bank_accounts' => [],
124+
'active_gateways' => [],
125+
'all_gateways' => [],
126+
];
127+
128+
$data = wp_parse_args($data, $defaults);
129+
$field_key = $this->get_field_key($key);
130+
$saved_mappings = $this->sanitize_payment_gateways_mapping_input($this->get_option($key, []));
131+
$rows = $this->get_payment_mapping_rows($data['active_gateways'], $data['all_gateways'], $saved_mappings);
132+
133+
ob_start();
134+
?>
135+
<tr valign="top">
136+
<th scope="row" class="titledesc">
137+
<label><?php echo esc_html($data['title']); ?></label>
138+
</th>
139+
<td class="forminp">
140+
<?php if ( empty($rows) ): ?>
141+
<p><?php echo esc_html__('No hay métodos de pago activos disponibles en WooCommerce para mapear.', 'integration-alegra-woo'); ?></p>
142+
<?php else: ?>
143+
<table class="widefat striped">
144+
<thead>
145+
<tr>
146+
<th><?php echo esc_html__('Gateway WooCommerce', 'integration-alegra-woo'); ?></th>
147+
<th><?php echo esc_html__('Método de pago en Alegra', 'integration-alegra-woo'); ?></th>
148+
<th><?php echo esc_html__('Cuenta bancaria en Alegra', 'integration-alegra-woo'); ?></th>
149+
</tr>
150+
</thead>
151+
<tbody>
152+
<?php foreach ($rows as $gateway_id => $gateway_data): ?>
153+
<?php
154+
$saved_method = $saved_mappings[$gateway_id]['payment_method'] ?? '';
155+
$saved_account = $saved_mappings[$gateway_id]['account_id'] ?? '';
156+
$gateway_label = $gateway_data['label'];
157+
if (!$gateway_data['active']) {
158+
$gateway_label .= ' (' . __('inactivo', 'integration-alegra-woo') . ')';
159+
}
160+
?>
161+
<tr>
162+
<td>
163+
<strong><?php echo esc_html($gateway_label); ?></strong>
164+
<br/>
165+
<small><?php echo esc_html($gateway_id); ?></small>
166+
</td>
167+
<td>
168+
<select name="<?php echo esc_attr(sprintf('%s[%s][payment_method]', $field_key, $gateway_id)); ?>">
169+
<option value=""><?php echo esc_html__('Seleccionar método...', 'integration-alegra-woo'); ?></option>
170+
<?php foreach ($data['payment_methods'] as $method_key => $method_label): ?>
171+
<option value="<?php echo esc_attr($method_key); ?>" <?php selected($saved_method, $method_key); ?>>
172+
<?php echo esc_html($method_label); ?>
173+
</option>
174+
<?php endforeach; ?>
175+
</select>
176+
</td>
177+
<td>
178+
<select name="<?php echo esc_attr(sprintf('%s[%s][account_id]', $field_key, $gateway_id)); ?>">
179+
<option value=""><?php echo esc_html__('Seleccionar cuenta...', 'integration-alegra-woo'); ?></option>
180+
<?php foreach ($data['bank_accounts'] as $account_id => $account_label): ?>
181+
<option value="<?php echo esc_attr($account_id); ?>" <?php selected($saved_account, (string) $account_id); ?>>
182+
<?php echo esc_html($account_label); ?>
183+
</option>
184+
<?php endforeach; ?>
185+
</select>
186+
</td>
187+
</tr>
188+
<?php endforeach; ?>
189+
</tbody>
190+
</table>
191+
<?php endif; ?>
192+
193+
<?php if (!empty($data['description'])): ?>
194+
<p class="description"><?php echo wp_kses_post($data['description']); ?></p>
195+
<?php endif; ?>
196+
</td>
197+
</tr>
198+
<?php
199+
200+
return ob_get_clean();
201+
}
202+
203+
public function validate_payment_mappings_table_field($key, $value): array
204+
{
205+
$existing_value = $this->get_option($key, []);
206+
207+
if (!is_array($existing_value)) {
208+
$existing_value = [];
209+
}
210+
211+
$sanitized_mapping = $this->sanitize_payment_gateways_mapping_input($value);
212+
$active_gateways = Integration_Alegra_WC::get_wc_payment_gateways(true);
213+
$bank_accounts = Integration_Alegra_WC::get_bank_accounts();
214+
$available_bank_accounts = [];
215+
216+
foreach ($bank_accounts as $bank_account) {
217+
if (($bank_account['status'] ?? '') !== 'active') {
218+
continue;
219+
}
220+
221+
$account_id = (string) ($bank_account['id'] ?? '');
222+
223+
if (!$account_id) {
224+
continue;
225+
}
226+
227+
$available_bank_accounts[$account_id] = true;
228+
}
229+
230+
if (empty($available_bank_accounts)) {
231+
WC_Admin_Settings::add_error(
232+
__('Integration Alegra Woocommerce: No se encontraron cuentas bancarias activas en Alegra para guardar el mapeo de pagos.', 'integration-alegra-woo')
233+
);
234+
return $existing_value;
235+
}
236+
237+
$has_errors = false;
238+
$validated_mapping = [];
239+
240+
foreach ($active_gateways as $gateway_id => $gateway_title) {
241+
$gateway_map = $sanitized_mapping[$gateway_id] ?? [
242+
'payment_method' => '',
243+
'account_id' => '',
244+
];
245+
246+
if (!$gateway_map['payment_method'] || !$gateway_map['account_id']) {
247+
WC_Admin_Settings::add_error(
248+
sprintf(
249+
__('Integration Alegra Woocommerce: Debe configurar método de pago y cuenta bancaria para el gateway activo "%s".', 'integration-alegra-woo'),
250+
$gateway_title
251+
)
252+
);
253+
$has_errors = true;
254+
}
255+
}
256+
257+
foreach ($sanitized_mapping as $gateway_id => $gateway_map) {
258+
$payment_method = $gateway_map['payment_method'];
259+
$account_id = $gateway_map['account_id'];
260+
261+
if (($payment_method && !$account_id) || (!$payment_method && $account_id)) {
262+
WC_Admin_Settings::add_error(
263+
sprintf(
264+
__('Integration Alegra Woocommerce: El gateway "%s" tiene configuración incompleta. Debe seleccionar método y cuenta.', 'integration-alegra-woo'),
265+
$gateway_id
266+
)
267+
);
268+
$has_errors = true;
269+
continue;
270+
}
271+
272+
if (!$payment_method && !$account_id) {
273+
continue;
274+
}
275+
276+
if (!isset(Integration_Alegra_WC::PAYMENTS_METHODS[$payment_method])) {
277+
WC_Admin_Settings::add_error(
278+
sprintf(
279+
__('Integration Alegra Woocommerce: El método de pago "%s" no es válido para el gateway "%s".', 'integration-alegra-woo'),
280+
$payment_method,
281+
$gateway_id
282+
)
283+
);
284+
$has_errors = true;
285+
continue;
286+
}
287+
288+
if (!isset($available_bank_accounts[$account_id])) {
289+
WC_Admin_Settings::add_error(
290+
sprintf(
291+
__('Integration Alegra Woocommerce: La cuenta bancaria "%s" no es válida para el gateway "%s".', 'integration-alegra-woo'),
292+
$account_id,
293+
$gateway_id
294+
)
295+
);
296+
$has_errors = true;
297+
continue;
298+
}
299+
300+
$validated_mapping[$gateway_id] = [
301+
'payment_method' => $payment_method,
302+
'account_id' => $account_id,
303+
];
304+
}
305+
306+
if ($has_errors) {
307+
return $existing_value;
308+
}
309+
310+
return $validated_mapping;
311+
}
312+
313+
private function sanitize_payment_gateways_mapping_input($value): array
314+
{
315+
$sanitized = [];
316+
317+
if (!is_array($value)) {
318+
return $sanitized;
319+
}
320+
321+
foreach ($value as $gateway_id => $gateway_map) {
322+
if (!is_array($gateway_map)) {
323+
continue;
324+
}
325+
326+
$sanitized_gateway_id = sanitize_text_field((string) $gateway_id);
327+
328+
if (!$sanitized_gateway_id) {
329+
continue;
330+
}
331+
332+
$sanitized[$sanitized_gateway_id] = [
333+
'payment_method' => sanitize_text_field((string) ($gateway_map['payment_method'] ?? '')),
334+
'account_id' => sanitize_text_field((string) ($gateway_map['account_id'] ?? '')),
335+
];
336+
}
337+
338+
return $sanitized;
339+
}
340+
341+
private function get_payment_mapping_rows(array $active_gateways, array $all_gateways, array $saved_mappings): array
342+
{
343+
$rows = [];
344+
345+
foreach ($active_gateways as $gateway_id => $gateway_title) {
346+
$rows[$gateway_id] = [
347+
'label' => $gateway_title,
348+
'active' => true,
349+
];
350+
}
351+
352+
foreach ($saved_mappings as $gateway_id => $mapping) {
353+
if (isset($rows[$gateway_id])) {
354+
continue;
355+
}
356+
357+
$rows[$gateway_id] = [
358+
'label' => $all_gateways[$gateway_id] ?? $gateway_id,
359+
'active' => false,
360+
];
361+
}
362+
363+
return $rows;
364+
}
116365
}

0 commit comments

Comments
 (0)