Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 81 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
<p>
<img src="docs/assets/SUMUP_INTEGRATION_APP_LOGO.png" alt="ERPNext SumUp Integration Logo" width="164"/>
</p>
<h1>SumUp ERPNext Integration <br> (WORK IN PROGRESS)</h1>
<h1>SumUp ERPNext Integration</h1>
</div>

This app integrates SumUp card terminals into ERPNext and allows card payments directly in the POS.
This app integrates [SumUp](https://www.sumup.com) card terminals into ERPNext and allows card payments directly in the POS.

When a card payment is selected, the amount is sent to a SumUp terminal. After a successful payment, the result is sent back to ERPNext.
When a card payment is selected, the amount is sent to a SumUp terminal. After successful payment, the result is sent back to ERPNext and the POS sale is completed.
In the event of a refund or return, the amount will also be automatically refunded for any previous SumUp payments.

> **Trademark notice:**
> SumUp is a registered trademark of SumUp Payments Limited.
Expand All @@ -17,42 +18,8 @@ When a card payment is selected, the amount is sent to a SumUp terminal. After a

| ERPNext | Frappe | Support Status |
|---------|--------|----------------|
| v16 Beta | v16 Beta | Coming soon |
| v15 | v15 | Coming soon |

## Quick Setup (POS)

1. Install the app (see installation sections below).
2. Open **SumUp Settings**:
- Enable SumUp.
- Enter **API Key** and **Merchant Code**.
- Click **Test Connection** to fetch the merchant currency.
3. Pair a terminal:
- Go to **SumUp Terminal** list.
- Click **Pair Terminal**.
- Enter the pairing code shown on the terminal and a name.
4. Mark a payment method for SumUp:
- Open **POS Payment Method**.
- Enable **Use SumUp Terminal**.
5. Assign the terminal in the POS Profile:
- Open **POS Profile**.
- Set **SumUp Terminal**.
- Ensure the SumUp payment method is listed in the profile.
6. Use in POS:
- Select the SumUp payment method.
- Submit the POS invoice to start the payment on the terminal.

Notes:
- SumUp payments must cover the full invoice total.
- The POS invoice currency must match the SumUp merchant currency.

## Recovery Mode (Optional)

If readers already exist in your SumUp account but are missing in ERPNext:

1. Open **SumUp Settings** and enable **Recovery Mode**.
2. Go to **SumUp Terminal** list view.
3. Click **Recovery Sync** to fetch and sync terminals.
| v16 Beta | v16 Beta | Testing... |
| v15 | v15 | ✅ Supported |

## Installation (Frappe Cloud)

Expand Down Expand Up @@ -91,6 +58,80 @@ Run migrations:
bench --site yoursite.com migrate
```

## Configuration

1. After installation, open the **SumUp Integration**
<p>
<img src="docs/assets/Settings/Settings_Overview.png" alt="Settings Overview for SumUp Integration"/>
</p>
2. Open **SumUp Settings**:
- Enable SumUp
- Enter **API Key**, **Merchant Code** and **Affiliate Key**
- Click **Test Connection** to fetch the merchant currency
- (Optional) Click Validate Merchant Code to verify correct keys and merchant
<p>
<img src="docs/assets/Settings/Settings.png" alt="Set API Key Merchant Code and Affiliate Key in SumUp Integrations App"/>
</p>
3. Pair a terminal:
- Go to **SumUp Terminal** list
- Click **Pair Terminal**
<p>
<img src="docs/assets/Terminals/Pair_New_Terminal.png" alt="Pairing a new SumUp terminal"/>
</p>
- Start the SumUp Solo device and select **Cloud API** as the connection
<p>
<img src="docs/assets/Terminals/SumUp_Solo_Pair_API_1.png" alt="Pair Solo with CLoud API" width="256"/>
</p>
- Generate a pairing code
<p>
<img src="docs/assets/Terminals/SumUp_Solo_Pair_API_2.png" alt="SumUp Solo Pairing Code" width="256"/>
</p>
- Enter the pairing code shown on the terminal and a name for the terminal to be used for administration purposes
<p>
<img src="docs/assets/Terminals/Pair_New_Terminal_Filled.png" alt="SumUp Solo Pairing Code"/>
</p>
- After successful connection, the terminal is listed. If necessary, the status can be updated manually using the Refresh Status button. The status is automatically updated at regular intervals.
<p>
<img src="docs/assets/Terminals/Terminal_List_View.png" alt="List View Paired SumUp Solo Terminals"/>
</p>
4. Mark a payment method for SumUp and assign the terminal:
- Open **POS Profile**
- Select the payment method you want to use with SumUp (Checkbox)
- Set the **SumUp Terminal** to be used for the POS profile
<p>
<img src="docs/assets/POS_Profile/POS_Profile_Settings.png" alt="Link POS Profile to SumUp Terminal"/>
</p>
5. Use in POS:
- As soon as a payment for SumUp has been selected, the workflows are triggered and the payment is forwarded to the terminal. If the payment is successful, the POS invoice is submitted directly.
<p>
<img src="docs/assets/Terminals/Terminal_Payment.png" alt="Link POS Profile to SumUp Terminal" width="256"/>
</p>

Notes:
- [SumUp Solo Cloud API](https://www.youtube.com/watch?v=AhI6R0RLtDw) How-to video on YouTube
- SumUp payments must cover the full invoice total.
- The POS invoice currency must match the SumUp merchant currency.

## More Instructions

More detailed instructions can be found here:
- [Payment Process](/docs/guides/payment-process.md)
- [Recovery Mode](/docs/guides/recovery-mode.md)
- [Refund Flow](/docs/guides/refund-flow.md)

## Community Support

Please create a ticket via [Issues](https://github.com/Rocket-Quack/erpnext_sumup/issues) for:

- **Bug Reports & Feature Requests**
- **Questions about general use**

## Sponsors ❤️

Development and maintenance are made possible by sponsors and voluntary support.

If you would like to support the project, you are welcome to do so via [Ko-fi](https://ko-fi.com/rocketquack).

## Trademark Notice

**SumUp** is a registered trademark of **SumUp Payments Limited**.
Expand All @@ -106,7 +147,7 @@ This app uses the Python package `sumup` v0.0.20 (tag v0.0.20). See `THIRD_PARTY

## License

Copyright (C) 2025 RocketQuackIT
Copyright (C) 2026 RocketQuackIT

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Expand Down
Binary file added docs/assets/POS_Profile/POS_Profile_Settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/Settings/Settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/Settings/Settings_Overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/Terminals/Pair_New_Terminal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/Terminals/SumUp_Solo_Pair_API_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/Terminals/Terminal_List_View.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/Terminals/Terminal_Payment.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion erpnext_sumup/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "15.0.0"
__version__ = "15.0.1"
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,26 @@ const show_recovery_message = (result) => {
});
};

const ensure_sumup_enabled = (listview) => {
if (listview && typeof listview.sumup_enabled === "boolean") {
if (!listview.sumup_enabled) {
frappe.msgprint(__("SumUp is disabled in settings."));
}
return Promise.resolve(listview.sumup_enabled);
}

return frappe.db.get_value("SumUp Settings", "SumUp Settings", "enabled").then((response) => {
const enabled = !!cint(response.message && response.message.enabled);
if (listview) {
listview.sumup_enabled = enabled;
}
if (!enabled) {
frappe.msgprint(__("SumUp is disabled in settings."));
}
return enabled;
});
};

const run_recovery_sync = (listview) => {
frappe.confirm(__("Fetch readers from SumUp and sync local terminals?"), () => {
frappe.call({
Expand All @@ -297,24 +317,30 @@ const remove_selected_terminals = (listview) => {
return;
}

frappe.confirm(
__("Remove {0} terminal(s) from SumUp and delete locally?", [terminal_names.length]),
() => {
frappe.call({
method: "erpnext_sumup.erpnext_sumup.doctype.sumup_terminal.sumup_terminal.remove_terminals",
args: {
terminal_names,
},
freeze: true,
freeze_message: __("Removing terminals..."),
callback: (response) => {
const result = response.message || {};
listview.refresh();
show_status_message(result);
},
});
ensure_sumup_enabled(listview).then((enabled) => {
if (!enabled) {
return;
}
);

frappe.confirm(
__("Remove {0} terminal(s) from SumUp and delete locally?", [terminal_names.length]),
() => {
frappe.call({
method: "erpnext_sumup.erpnext_sumup.doctype.sumup_terminal.sumup_terminal.remove_terminals",
args: {
terminal_names,
},
freeze: true,
freeze_message: __("Removing terminals..."),
callback: (response) => {
const result = response.message || {};
listview.refresh();
show_status_message(result);
},
});
}
);
});
};

const force_remove_selected_terminals = (listview) => {
Expand Down Expand Up @@ -350,6 +376,7 @@ frappe.listview_settings["SumUp Terminal"] = {
add_fields: ["connection_status", "online_status", "activity_status"],
onload(listview) {
listview.sumup_debug_enabled = false;
listview.sumup_enabled = undefined;
const refresh_action = () => {
const terminal_names = get_selected_terminal_names(listview);
refresh_terminal_statuses(listview, terminal_names.length ? terminal_names : null);
Expand All @@ -376,6 +403,9 @@ frappe.listview_settings["SumUp Terminal"] = {
listview.page.add_actions_menu_item(__("Remove from SumUp"), () => {
remove_selected_terminals(listview);
});
listview.page.add_inner_button(__("Remove from SumUp"), () => {
remove_selected_terminals(listview);
});

frappe.db
.get_value("SumUp Settings", "SumUp Settings", "enable_debug_logging")
Expand Down
22 changes: 22 additions & 0 deletions erpnext_sumup/erpnext_sumup/fixtures/number_card.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[
{
"creation": "2025-12-29 00:00:00.000000",
"docstatus": 0,
"doctype": "Number Card",
"document_type": "SumUp Terminal",
"filters_json": "[[\"SumUp Terminal\",\"enabled\",\"=\",\"1\"]]",
"function": "Count",
"idx": 0,
"is_public": 1,
"is_standard": 1,
"label": "SumUp Terminals",
"modified": "2025-12-29 00:00:00.000000",
"modified_by": "Administrator",
"module": "ERPNext SumUp",
"name": "SumUp Terminals",
"owner": "Administrator",
"show_percentage_stats": 1,
"stats_time_interval": "Monthly",
"type": "Document Type"
}
]
1 change: 1 addition & 0 deletions erpnext_sumup/public/js/pos_invoice_sumup.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@
const sumup_show_dialog = async (frm, pos, original_submit) => {
const dialog = new frappe.ui.Dialog({
title: __("SumUp Payment"),
static: true,
fields: [
{
fieldname: "sumup_status_html",
Expand Down