trabajando en la tabla de transferencias

This commit is contained in:
2025-11-05 21:46:54 +01:00
parent a4443763d8
commit c11c34011e
14 changed files with 800 additions and 433 deletions

View File

@ -1,403 +1,418 @@
databaseChangeLog:
- changeSet:
id: 0007-payments-core
author: jjo
changes:
# 2) payments
- createTable:
tableName: payments
columns:
- column:
name: id
type: BIGINT AUTO_INCREMENT
constraints:
primaryKey: true
nullable: false
- column:
name: order_id
type: BIGINT
- column:
name: user_id
type: BIGINT
- column:
name: currency
type: CHAR(3)
constraints:
nullable: false
- column:
name: amount_total_cents
type: BIGINT
constraints:
nullable: false
- column:
name: amount_captured_cents
type: BIGINT
defaultValueNumeric: 0
constraints:
nullable: false
- column:
name: amount_refunded_cents
type: BIGINT
defaultValueNumeric: 0
constraints:
nullable: false
- column:
name: status
type: "ENUM('requires_payment_method','requires_action','authorized','captured','partially_refunded','refunded','canceled','failed')"
defaultValue: "requires_payment_method"
constraints:
nullable: false
- column:
name: capture_method
type: "ENUM('automatic','manual')"
defaultValue: "automatic"
constraints:
nullable: false
- column:
name: gateway
type: VARCHAR(32)
constraints:
nullable: false
- column:
name: gateway_payment_id
type: VARCHAR(128)
- column:
name: gateway_order_id
type: VARCHAR(12)
- column:
name: authorization_code
type: VARCHAR(32)
- column:
name: three_ds_status
type: "ENUM('not_applicable','attempted','challenge','succeeded','failed')"
defaultValue: "not_applicable"
constraints:
nullable: false
- column:
name: descriptor
type: VARCHAR(22)
- column:
name: client_ip
type: VARBINARY(16)
- column:
name: authorized_at
type: DATETIME
- column:
name: captured_at
type: DATETIME
- column:
name: canceled_at
type: DATETIME
- column:
name: failed_at
type: DATETIME
- column:
name: metadata
type: JSON
- column:
name: created_at
type: DATETIME
defaultValueComputed: CURRENT_TIMESTAMP
constraints:
nullable: false
- column:
name: updated_at
type: DATETIME
defaultValueComputed: "CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
constraints:
nullable: false
id: 0007-payments-core
author: jjo
changes:
# 2) payments
- createTable:
tableName: payments
columns:
- column:
name: id
type: BIGINT AUTO_INCREMENT
constraints:
primaryKey: true
nullable: false
- column:
name: order_id
type: BIGINT
- column:
name: user_id
type: BIGINT
- column:
name: currency
type: CHAR(3)
constraints:
nullable: false
- column:
name: amount_total_cents
type: BIGINT
constraints:
nullable: false
- column:
name: amount_captured_cents
type: BIGINT
defaultValueNumeric: 0
constraints:
nullable: false
- column:
name: amount_refunded_cents
type: BIGINT
defaultValueNumeric: 0
constraints:
nullable: false
- column:
name: status
type: "ENUM('requires_payment_method','requires_action','authorized','captured','partially_refunded','refunded','canceled','failed')"
defaultValue: "requires_payment_method"
constraints:
nullable: false
- column:
name: capture_method
type: "ENUM('automatic','manual')"
defaultValue: "automatic"
constraints:
nullable: false
- column:
name: gateway
type: VARCHAR(32)
constraints:
nullable: false
- column:
name: gateway_payment_id
type: VARCHAR(128)
- column:
name: gateway_order_id
type: VARCHAR(12)
- column:
name: authorization_code
type: VARCHAR(32)
- column:
name: three_ds_status
type: "ENUM('not_applicable','attempted','challenge','succeeded','failed')"
defaultValue: "not_applicable"
constraints:
nullable: false
- column:
name: descriptor
type: VARCHAR(22)
- column:
name: client_ip
type: VARBINARY(16)
- column:
name: authorized_at
type: DATETIME
- column:
name: captured_at
type: DATETIME
- column:
name: canceled_at
type: DATETIME
- column:
name: failed_at
type: DATETIME
- column:
name: metadata
type: JSON
- column:
name: created_at
type: DATETIME
defaultValueComputed: CURRENT_TIMESTAMP
constraints:
nullable: false
- column:
name: updated_at
type: DATETIME
defaultValueComputed: "CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
constraints:
nullable: false
- createIndex:
tableName: payments
indexName: idx_payments_order
columns:
- column:
name: order_id
- createIndex:
tableName: payments
indexName: idx_payments_order
columns:
- column:
name: order_id
- createIndex:
tableName: payments
indexName: idx_payments_gateway
columns:
- column:
name: gateway
- column:
name: gateway_payment_id
- createIndex:
tableName: payments
indexName: idx_payments_gateway
columns:
- column:
name: gateway
- column:
name: gateway_payment_id
- createIndex:
tableName: payments
indexName: idx_payments_status
columns:
- column:
name: status
- createIndex:
tableName: payments
indexName: idx_payments_status
columns:
- column:
name: status
- addUniqueConstraint:
tableName: payments
columnNames: gateway, gateway_order_id
constraintName: uq_payments_gateway_order
- addUniqueConstraint:
tableName: payments
columnNames: gateway, gateway_order_id
constraintName: uq_payments_gateway_order
# 3) payment_transactions
- createTable:
tableName: payment_transactions
columns:
- column:
name: id
type: BIGINT AUTO_INCREMENT
constraints:
primaryKey: true
nullable: false
- column:
name: payment_id
type: BIGINT
constraints:
nullable: false
- column:
name: type
type: "ENUM('AUTH','CAPTURE','REFUND','VOID')"
constraints:
nullable: false
- column:
name: status
type: "ENUM('pending','succeeded','failed')"
constraints:
nullable: false
- column:
name: amount_cents
type: BIGINT
constraints:
nullable: false
- column:
name: currency
type: CHAR(3)
constraints:
nullable: false
- column:
name: gateway_transaction_id
type: VARCHAR(128)
- column:
name: gateway_response_code
type: VARCHAR(64)
- column:
name: avs_result
type: VARCHAR(8)
- column:
name: cvv_result
type: VARCHAR(8)
- column:
name: three_ds_version
type: VARCHAR(16)
- column:
name: idempotency_key
type: VARCHAR(128)
- column:
name: request_payload
type: JSON
- column:
name: response_payload
type: JSON
- column:
name: processed_at
type: DATETIME
- column:
name: created_at
type: DATETIME
defaultValueComputed: CURRENT_TIMESTAMP
constraints:
nullable: false
# 3) payment_transactions
- createTable:
tableName: payment_transactions
columns:
- column:
name: id
type: BIGINT AUTO_INCREMENT
constraints:
primaryKey: true
nullable: false
- column:
name: payment_id
type: BIGINT
constraints:
nullable: false
- column:
name: type
type: "ENUM('AUTH','CAPTURE','REFUND','VOID')"
constraints:
nullable: false
- column:
name: status
type: "ENUM('pending','succeeded','failed')"
constraints:
nullable: false
- column:
name: amount_cents
type: BIGINT
constraints:
nullable: false
- column:
name: currency
type: CHAR(3)
constraints:
nullable: false
- column:
name: gateway_transaction_id
type: VARCHAR(128)
- column:
name: gateway_response_code
type: VARCHAR(64)
- column:
name: avs_result
type: VARCHAR(8)
- column:
name: cvv_result
type: VARCHAR(8)
- column:
name: three_ds_version
type: VARCHAR(16)
- column:
name: idempotency_key
type: VARCHAR(128)
- column:
name: request_payload
type: JSON
- column:
name: response_payload
type: JSON
- column:
name: processed_at
type: DATETIME
- column:
name: created_at
type: DATETIME
defaultValueComputed: CURRENT_TIMESTAMP
constraints:
nullable: false
- addForeignKeyConstraint:
baseTableName: payment_transactions
baseColumnNames: payment_id
referencedTableName: payments
referencedColumnNames: id
constraintName: fk_tx_payment
onDelete: CASCADE
- addForeignKeyConstraint:
baseTableName: payment_transactions
baseColumnNames: payment_id
referencedTableName: payments
referencedColumnNames: id
constraintName: fk_tx_payment
onDelete: CASCADE
- addUniqueConstraint:
tableName: payment_transactions
columnNames: gateway_transaction_id
constraintName: uq_tx_gateway_txid
- addUniqueConstraint:
tableName: payment_transactions
columnNames: gateway_transaction_id
constraintName: uq_tx_gateway_txid
- createIndex:
tableName: payment_transactions
indexName: idx_tx_pay
columns:
- column:
name: payment_id
- createIndex:
tableName: payment_transactions
indexName: idx_tx_pay
columns:
- column:
name: payment_id
- createIndex:
tableName: payment_transactions
indexName: idx_tx_type_status
columns:
- column:
name: type
- column:
name: status
- createIndex:
tableName: payment_transactions
indexName: idx_tx_type_status
columns:
- column:
name: type
- column:
name: status
- createIndex:
tableName: payment_transactions
indexName: idx_tx_idem
columns:
- column:
name: idempotency_key
- createIndex:
tableName: payment_transactions
indexName: idx_tx_idem
columns:
- column:
name: idempotency_key
# 4) refunds
- createTable:
tableName: refunds
columns:
- column:
name: id
type: BIGINT AUTO_INCREMENT
constraints:
primaryKey: true
nullable: false
- column:
name: payment_id
type: BIGINT
constraints:
nullable: false
- column:
name: transaction_id
type: BIGINT
- column:
name: amount_cents
type: BIGINT
constraints:
nullable: false
- column:
name: reason
type: "ENUM('customer_request','partial_return','pricing_adjustment','duplicate','fraud','other')"
defaultValue: "customer_request"
constraints:
nullable: false
- column:
name: status
type: "ENUM('pending','succeeded','failed','canceled')"
defaultValue: "pending"
constraints:
nullable: false
- column:
name: requested_by_user_id
type: BIGINT
- column:
name: requested_at
type: DATETIME
defaultValueComputed: CURRENT_TIMESTAMP
constraints:
nullable: false
- column:
name: processed_at
type: DATETIME
- column:
name: gateway_refund_id
type: VARCHAR(128)
- column:
name: notes
type: VARCHAR(500)
- column:
name: metadata
type: JSON
# 4) refunds
- createTable:
tableName: refunds
columns:
- column:
name: id
type: BIGINT AUTO_INCREMENT
constraints:
primaryKey: true
nullable: false
- column:
name: payment_id
type: BIGINT
constraints:
nullable: false
- column:
name: transaction_id
type: BIGINT
- column:
name: amount_cents
type: BIGINT
constraints:
nullable: false
- column:
name: reason
type: "ENUM('customer_request','partial_return','pricing_adjustment','duplicate','fraud','other')"
defaultValue: "customer_request"
constraints:
nullable: false
- column:
name: status
type: "ENUM('pending','succeeded','failed','canceled')"
defaultValue: "pending"
constraints:
nullable: false
- column:
name: requested_by_user_id
type: BIGINT
- column:
name: requested_at
type: DATETIME
defaultValueComputed: CURRENT_TIMESTAMP
constraints:
nullable: false
- column:
name: processed_at
type: DATETIME
- column:
name: gateway_refund_id
type: VARCHAR(128)
- column:
name: notes
type: VARCHAR(500)
- column:
name: metadata
type: JSON
- addForeignKeyConstraint:
baseTableName: refunds
baseColumnNames: payment_id
referencedTableName: payments
referencedColumnNames: id
constraintName: fk_ref_payment
onDelete: CASCADE
- addForeignKeyConstraint:
baseTableName: refunds
baseColumnNames: payment_id
referencedTableName: payments
referencedColumnNames: id
constraintName: fk_ref_payment
onDelete: CASCADE
- addForeignKeyConstraint:
baseTableName: refunds
baseColumnNames: transaction_id
referencedTableName: payment_transactions
referencedColumnNames: id
constraintName: fk_ref_tx
onDelete: SET NULL
- addForeignKeyConstraint:
baseTableName: refunds
baseColumnNames: transaction_id
referencedTableName: payment_transactions
referencedColumnNames: id
constraintName: fk_ref_tx
onDelete: SET NULL
- addUniqueConstraint:
tableName: refunds
columnNames: gateway_refund_id
constraintName: uq_refund_gateway_id
- addUniqueConstraint:
tableName: refunds
columnNames: gateway_refund_id
constraintName: uq_refund_gateway_id
- createIndex:
tableName: refunds
indexName: idx_ref_pay
columns:
- column:
name: payment_id
- createIndex:
tableName: refunds
indexName: idx_ref_pay
columns:
- column:
name: payment_id
- createIndex:
tableName: refunds
indexName: idx_ref_status
columns:
- column:
name: status
- createIndex:
tableName: refunds
indexName: idx_ref_status
columns:
- column:
name: status
# 5) webhook_events
- createTable:
tableName: webhook_events
columns:
- column:
name: id
type: BIGINT AUTO_INCREMENT
constraints:
primaryKey: true
nullable: false
- column:
name: provider
type: VARCHAR(32)
constraints:
nullable: false
- column:
name: event_type
type: VARCHAR(64)
constraints:
nullable: false
- column:
name: event_id
type: VARCHAR(128)
- column:
name: signature
type: VARCHAR(512)
- column:
name: payload
type: JSON
constraints:
nullable: false
- column:
name: processed
type: TINYINT(1)
defaultValueNumeric: 0
constraints:
nullable: false
- column:
name: processed_at
type: DATETIME
- column:
name: attempts
type: INT
defaultValueNumeric: 0
constraints:
nullable: false
- column:
name: last_error
type: VARCHAR(500)
- column:
name: created_at
type: DATETIME
defaultValueComputed: CURRENT_TIMESTAMP
constraints:
nullable: false
# 5) webhook_events
- createTable:
tableName: webhook_events
columns:
- column:
name: id
type: BIGINT AUTO_INCREMENT
constraints:
primaryKey: true
nullable: false
- column:
name: provider
type: VARCHAR(32)
constraints:
nullable: false
- column:
name: event_type
type: VARCHAR(64)
constraints:
nullable: false
- column:
name: event_id
type: VARCHAR(128)
- column:
name: signature
type: VARCHAR(512)
- column:
name: payload
type: JSON
constraints:
nullable: false
- column:
name: processed
type: TINYINT(1)
defaultValueNumeric: 0
constraints:
nullable: false
- column:
name: processed_at
type: DATETIME
- column:
name: attempts
type: INT
defaultValueNumeric: 0
constraints:
nullable: false
- column:
name: last_error
type: VARCHAR(500)
- column:
name: created_at
type: DATETIME
defaultValueComputed: CURRENT_TIMESTAMP
constraints:
nullable: false
- addUniqueConstraint:
tableName: webhook_events
columnNames: provider, event_id
constraintName: uq_webhook_provider_event
- addUniqueConstraint:
tableName: webhook_events
columnNames: provider, event_id
constraintName: uq_webhook_provider_event
- createIndex:
tableName: webhook_events
indexName: idx_webhook_processed
columns:
- column:
name: processed
- createIndex:
tableName: webhook_events
indexName: idx_webhook_processed
columns:
- column:
name: processed
rollback:
# Se borran las tablas en orden inverso de dependencias
- dropTable:
tableName: webhook_events
- dropTable:
tableName: refunds
- dropTable:
tableName: payment_transactions
- dropTable:
tableName: payments

View File

@ -26,3 +26,22 @@ databaseChangeLog:
sql: |
CREATE UNIQUE INDEX uq_carts_user_active
ON carts (user_id, active_flag);
rollback:
# 🔙 1) Eliminar el índice nuevo basado en active_flag
- sql:
sql: |
ALTER TABLE carts
DROP INDEX uq_carts_user_active;
# 🔙 2) Eliminar la columna generada active_flag
- sql:
sql: |
ALTER TABLE carts
DROP COLUMN active_flag;
# 🔙 3) Restaurar el índice único original (user_id, status)
- sql:
sql: |
CREATE UNIQUE INDEX uq_carts_user_active
ON carts (user_id, status);

View File

@ -1,15 +0,0 @@
databaseChangeLog:
- changeSet:
id: 0009-add-composite-unique-txid-type
author: JJO
changes:
# 1⃣ Eliminar el índice único anterior
- dropUniqueConstraint:
constraintName: uq_tx_gateway_txid
tableName: payment_transactions
# 2⃣ Crear índice único compuesto por gateway_transaction_id + type
- addUniqueConstraint:
tableName: payment_transactions
columnNames: gateway_transaction_id, type
constraintName: uq_tx_gateway_txid_type

View File

@ -0,0 +1,29 @@
databaseChangeLog:
- changeSet:
id: 0009-drop-unique-refund-gateway-id
author: JJO
changes:
# 1⃣ Eliminar la UNIQUE constraint sobre gateway_refund_id
- dropUniqueConstraint:
constraintName: uq_refund_gateway_id
tableName: refunds
# 2⃣ Crear un índice normal (no único) para acelerar búsquedas por gateway_refund_id
- createIndex:
tableName: refunds
indexName: idx_refunds_gateway_refund_id
columns:
- column:
name: gateway_refund_id
rollback:
# 🔙 1) Eliminar el índice normal creado en este changeSet
- dropIndex:
indexName: idx_refunds_gateway_refund_id
tableName: refunds
# 🔙 2) Restaurar la UNIQUE constraint original
- addUniqueConstraint:
tableName: refunds
columnNames: gateway_refund_id
constraintName: uq_refund_gateway_id

View File

@ -0,0 +1,30 @@
databaseChangeLog:
- changeSet:
id: 0010-drop-unique-tx-gateway
author: JJO
changes:
# 1⃣ Eliminar la UNIQUE constraint sobre (gateway_transaction_id, type)
- dropUniqueConstraint:
constraintName: uq_tx_gateway_txid_type
tableName: payment_transactions
# 2⃣ Crear un índice normal (no único) sobre gateway_transaction_id
# para poder seguir buscando rápido por este campo
- createIndex:
tableName: payment_transactions
indexName: idx_payment_tx_gateway_txid
columns:
- column:
name: gateway_transaction_id
rollback:
# 🔙 1) Eliminar el índice normal creado en este changeSet
- dropIndex:
indexName: idx_payment_tx_gateway_txid
tableName: payment_transactions
# 🔙 2) Restaurar la UNIQUE constraint original
- addUniqueConstraint:
tableName: payment_transactions
columnNames: gateway_transaction_id, type
constraintName: uq_tx_gateway_txid_type

View File

@ -16,4 +16,6 @@ databaseChangeLog:
- include:
file: db/changelog/changesets/0008-update-cart-status-constraint.yml
- include:
file: db/changelog/changesets/0009-add-composite-unique-txid-type.yml
file: db/changelog/changesets/0009-add-composite-unique-txid-type.yml
- include:
file: db/changelog/changesets/0010-drop-unique-tx-gateway.yml

View File

@ -11,3 +11,21 @@ pagos.table.devuelto=Devolución
pagos.table.fecha=Fecha
pagos.table.estado=Estado
pagos.table.acciones=Acciones
pagos.table.concepto-transferencia=Concepto
pagos.table.estado-transferencia=Estado
pagos.table.fecha-created=Fecha creación
pagos.table.fecha-procesed=Fecha procesada
pagos.table.estado.pending=Pendiente
pagos.table.estado.succeeded=Completada
pagos.table.estado.failed=Fallido
pagos.table.finalizar=Finalizar
pagos.transferencia.no-pedido=No disponible
pagos.refund.title=Devolución de Pago Redsys
pagos.refund.text=Introduce la cantidad a devolver (en euros):
pagos.refund.success=Devolución solicitada con éxito. Si no se refleja inmediatamente, espere unos minutos y actualiza la página.
pagos.refund.error.general=Error al procesar la devolución
pagos.refund.error.invalid-number=Cantidad inválida para la devolución

View File

@ -76,11 +76,20 @@ $(() => {
$(document).on('click', '.btn-refund-payment', function () {
const dsOrderId = $(this).data('dsorderid');
const transactionId = $(this).data('transactionid');
const maxAmountCents = $(this).data('amount');
// show swal confirmation with input for amount to refund
Swal.fire({
title: '¿Estás seguro de que deseas devolver este pago?',
text: 'Introduce la cantidad a devolver (en euros):',
showCancelButton: true,
buttonsStyling: false,
title: window.languageBundle['pagos.refund.title'],
text: window.languageBundle['pagos.refund.text'],
input: 'number',
confirmButtonText: window.languageBundle['app.aceptar'] || 'Seleccionar',
cancelButtonText: window.languageBundle['app.cancelar'] || 'Cancelar',
customClass: {
confirmButton: 'btn btn-secondary me-2',
cancelButton: 'btn btn-light',
},
inputAttributes: {
min: 0,
}
@ -88,7 +97,15 @@ $(() => {
if (result.isConfirmed) {
const amountToRefund = parseFloat(result.value);
if (isNaN(amountToRefund) || amountToRefund <= 0) {
Swal.fire('Error', 'Cantidad inválida para la devolución.', 'error');
showSwal('Error', window.languageBundle['pagos.refund.error.invalid-number'], 'error');
return;
}
if (amountToRefund*100 > maxAmountCents) {
showSwal('Error', window.languageBundle['pagos.refund.error.invalid-number'], 'error');
return;
}
if (amountToRefund*100 > maxAmountCents) {
showSwal('Error', window.languageBundle['pagos.refund.error.invalid-number'], 'error');
return;
}
$.ajax({
@ -98,14 +115,91 @@ $(() => {
amountCents: amountToRefund*100
}
}).then((response) => {
response = typeof response === 'string' ? JSON.parse(response) : response;
if (response.success) {
Swal.fire('Éxito', 'Pago devuelto con éxito.', 'success');
table.draw();
showSwal('Éxito', window.languageBundle['pagos.refund.success'], 'success');
$('#pagos-redsys-datatable').DataTable().draw();
} else {
Swal.fire('Error', 'No se pudo procesar la devolución.', 'error');
showSwal('Error', window.languageBundle['pagos.refund.error.general'], 'error');
$('#pagos-redsys-datatable').DataTable().draw();
}
});
}).fail(() => {
showSwal('Error', window.languageBundle['pagos.refund.error.general'], 'error');
});
}
});
});
const tableT = new DataTable('#pagos-transferencias-datatable', {
processing: true,
serverSide: true,
orderCellsTop: true,
pageLength: 50,
lengthMenu: [10, 25, 50, 100, 500],
language: { url: '/assets/libs/datatables/i18n/' + language + '.json' },
responsive: true,
dom: 'lBrtip',
buttons: {
dom: {
button: {
className: 'btn btn-sm btn-outline-primary me-1'
},
buttons: [
{ extend: 'copy' },
{ extend: 'csv' },
{ extend: 'excel' },
{ extend: 'pdf' },
{ extend: 'print' },
{ extend: 'colvis' }
],
}
},
ajax: {
url: '/pagos/datatable/transferencias',
method: 'GET',
},
order: [[7, 'desc']], // Ordena por fecha por defecto
columns: [
{ data: 'client', name: 'client', orderable: true },
{ data: 'transfer_id', name: 'transfer_id', orderable: true },
{ data: 'status', name: 'status', orderable: true },
{ data: 'order_id', name: 'payment.orderId', orderable: true },
{ data: 'amount_cents', name: 'amountCents', orderable: true },
{ data: 'amount_cents_refund', name: 'amountCentsRefund', orderable: true },
{ data: 'created_at', name: 'createdAt', orderable: true },
{ data: 'processed_at', name: 'processedAt', orderable: true },
{ data: 'actions', name: 'actions', orderable: false, searchable: false }
],
columnDefs: [{ targets: -1, orderable: false, searchable: false }]
});
// Fila de filtros = segunda fila del thead (index 1)
$('#pagos-redsys-datatable thead tr:eq(1) th').each(function (colIdx) {
const input = $(this).find('input');
if (input.length === 0) return; // columnas sin filtro
input.on('keyup change', function () {
const value = this.value;
if (table.column(colIdx).search() !== value) {
table.column(colIdx).search(value).draw();
}
});
});
function showSwal(title, text, icon) {
Swal.fire({
title: title,
text: text,
icon: icon,
buttonsStyling: false,
confirmButtonText: window.languageBundle['app.aceptar'] || 'Aceptar',
customClass: {
confirmButton: 'btn btn-secondary',
}
});
}
});

View File

@ -67,11 +67,11 @@
</div>
<div class="tab-pane" id="arrow-transferencias" role="tabpanel">
<div></div>
<!---
<div
th:insert="~{imprimelibros/presupuestos/presupuesto-list-items/tabla-anonimos :: tabla-anonimos}">
th:insert="~{imprimelibros/pagos/tabla-transferencias :: tabla-transferencias}">
</div>
-->
</div>
</div>

View File

@ -0,0 +1,30 @@
<div th:fragment="tabla-transferencias">
<table id="pagos-transferencias-datatable" class="table table-striped table-nowrap responsive w-100">
<thead>
<tr>
<th scope="col" th:text="#{pagos.table.cliente.nombre}"></th>
<th scope="col" th:text="#{pagos.table.concepto-transferencia}"></th>
<th scope="col" th:text="#{pagos.table.estado-transferencia}"></th>
<th scope="col" th:text="#{pagos.table.pedido.id}"></th>
<th scope="col" th:text="#{pagos.table.cantidad}"></th>
<th scope="col" th:text="#{pagos.table.devuelto}"></th>
<th scope="col" th:text="#{pagos.table.fecha-created}"></th>
<th scope="col" th:text="#{pagos.table.fecha-procesed}"></th>
<th scope="col" th:text="#{pagos.table.acciones}">Acciones</th>
</tr>
<tr>
<th><input type="text" class="form-control form-control-sm redsys-filter" /></th>
<th><input type="text" class="form-control form-control-sm redsys-filter" /></th>
<th><input type="text" class="form-control form-control-sm redsys-filter" /></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th> <!-- Acciones (sin filtro) -->
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>