Skip to content
Open
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
68 changes: 68 additions & 0 deletions .github/helper/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/bin/bash

set -e

# Check for merge conflicts before proceeding
python -m compileall -f "${GITHUB_WORKSPACE}"
if grep -lr --exclude-dir=node_modules "^<<<<<<< " "${GITHUB_WORKSPACE}"
then echo "Found merge conflicts"
exit 1
fi

cd ~ || exit

echo "Setting Up System Dependencies..."

sudo apt update

sudo apt remove mysql-server mysql-client
sudo apt install libcups2-dev redis-server mariadb-client

install_whktml() {
wget -O /tmp/wkhtmltox.deb https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.jammy_amd64.deb
sudo apt install /tmp/wkhtmltox.deb
}
install_whktml &
wkpid=$!

pip install frappe-bench

git clone "https://github.com/frappe/frappe" --branch "$BRANCH_TO_CLONE" --depth 1
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench

mkdir ~/frappe-bench/sites/test_site

cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config.json" ~/frappe-bench/sites/test_site/


mariadb --host 127.0.0.1 --port 3306 -u root -ptravis -e "
SET GLOBAL character_set_server = 'utf8mb4';
SET GLOBAL collation_server = 'utf8mb4_unicode_ci';

CREATE USER 'test_resilient'@'localhost' IDENTIFIED BY 'test_resilient';
CREATE DATABASE test_resilient;
GRANT ALL PRIVILEGES ON \`test_resilient\`.* TO 'test_resilient'@'localhost';

FLUSH PRIVILEGES;
"

cd ~/frappe-bench || exit

sed -i 's/watch:/# watch:/g' Procfile
sed -i 's/schedule:/# schedule:/g' Procfile
sed -i 's/socketio:/# socketio:/g' Procfile
sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile

bench get-app erpnext --branch "$BRANCH_TO_CLONE" --resolve-deps
bench get-app payments_processor "${GITHUB_WORKSPACE}"
bench setup requirements --dev

wait $wkpid

bench use test_site
bench start &
bench reinstall --yes

bench --verbose install-app payments_processor
bench --site test_site add-to-hosts

17 changes: 17 additions & 0 deletions .github/helper/site_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"db_host": "127.0.0.1",
"db_port": 3306,
"db_name": "test_frappe",
"db_password": "test_frappe",
"db_type": "mariadb",
"auto_email_id": "test@example.com",
"mail_server": "smtp.example.com",
"mail_login": "test@example.com",
"mail_password": "test",
"admin_password": "admin",
"root_login": "root",
"root_password": "travis",
"host_name": "http://test_site:8000",
"install_apps": ["erpnext"],
"throttle_user_limit": 100
}
122 changes: 122 additions & 0 deletions .github/workflows/server-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Server Tests

on:
workflow_call:
inputs:
base_ref:
type: string

app_name:
type: string


pull_request:
paths-ignore:
- "**.css"
- "**.js"
- "**.md"
- "**.html"
- "**.csv"

push:
branches: [version-15]
paths-ignore:
- "**.css"
- "**.js"
- "**.md"
- "**.html"
- "**.csv"
env:
BRANCH: ${{ inputs.base_ref || github.base_ref || github.ref_name }}
APP_NAME: ${{ inputs.app_name || 'payments_processor' }}

jobs:
tests:
runs-on: ubuntu-latest
timeout-minutes: 20

strategy:
fail-fast: false

name: Python Unit Tests

services:
mariadb:
image: mariadb:10.6
env:
MARIADB_ROOT_PASSWORD: "travis"
ports:
- 3306:3306
options: --health-cmd="mariadb-admin ping" --health-interval=5s --health-timeout=2s --health-retries=3

steps:
- name: Clone
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
check-latest: true

- name: Add to Hosts
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts

- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-

- name: Cache node modules
uses: actions/cache@v4
env:
cache-name: cache-node-modules
with:
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-

- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT

- uses: actions/cache@v4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-

- name: Install
run: |
bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
env:
BRANCH_TO_CLONE: ${{ env.BRANCH }}

- name: Run Tests
run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app ${{ env.APP_NAME }} --with-coverage
env:
TYPE: server

- name: Show bench output
if: ${{ always() }}
run: cat ~/frappe-bench/bench_start.log || true

- name: Upload coverage data
uses: actions/upload-artifact@v4
with:
name: coverage
path: /home/runner/frappe-bench/sites/coverage.xml
50 changes: 29 additions & 21 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
exclude: "node_modules|.git"
exclude: 'node_modules|.git'
default_stages: [commit]
fail_fast: false


repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v4.3.0
hooks:
- id: trailing-whitespace
files: "payments_processor/.*"
exclude: ".*txt$|.*csv|.*md"
files: "payments_processor.*"
exclude: ".*json$|.*txt$|.*csv|.*md"
- id: check-yaml
- id: no-commit-to-branch
args: ["--branch", "version-15"]
args: ['--branch', 'version-15']
- id: check-merge-conflict
- id: check-ast
- id: check-json
- id: check-toml
- id: check-yaml
- id: debug-statements

- repo: https://github.com/pre-commit/mirrors-prettier
Expand All @@ -25,27 +27,33 @@ repos:
types_or: [javascript, vue, scss]
# Ignore any files that might contain jinja / bundles
exclude: |
(?x)^(
payments_processor/public/dist/.*|
cypress/.*|
.*node_modules.*|
.*boilerplate.*
)$
(?x)^(
payments_processor/public/dist/.*|
cypress/.*|
.*node_modules.*|
.*boilerplate.*|
payments_processor/public/js/controllers/.*|
payments_processor/templates/pages/order.js|
payments_processor/templates/includes/.*
)$

- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.44.0
hooks:
- id: eslint
types_or: [javascript]
args: ["--quiet"]
args: ['--quiet']
# Ignore any files that might contain jinja / bundles
exclude: |
(?x)^(
payments_processor/public/dist/.*|
cypress/.*|
.*node_modules.*|
.*boilerplate.*
)$
(?x)^(
payments_processor/public/dist/.*|
cypress/.*|
.*node_modules.*|
.*boilerplate.*|
payments_processor/public/js/controllers/.*|
payments_processor/templates/pages/order.js|
payments_processor/templates/includes/.*
)$

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.2.0
Expand All @@ -61,6 +69,6 @@ repos:
name: "Run ruff formatter"

ci:
autoupdate_schedule: weekly
skip: []
submodules: false
autoupdate_schedule: weekly
skip: []
submodules: false
3 changes: 2 additions & 1 deletion payments_processor/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
after_install = "payments_processor.install.after_install"
before_uninstall = "payments_processor.uninstall.before_uninstall"

# TODO: Make this comfigurable
before_tests = "payments_processor.tests.before_tests"

scheduler_events = {
"all": [
"payments_processor.payments_processor.utils.automation.autocreate_payment_entry"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# TODO: only share the sections available.
# TODO: error with Fmt Money in dev
EMAIL_TEMPLATES = [
{
"name": "Auto Payment Email",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,13 +270,15 @@
"fieldtype": "Column Break"
},
{
"depends_on": "eval: doc.auto_generate_entries",
"description": "Email notification will be sent to all users with this role",
"fieldname": "email_to",
"fieldtype": "Link",
"label": "Email To",
"options": "Role"
},
{
"depends_on": "eval: doc.auto_generate_entries",
"description": "Time during the day when processing should be done",
"fieldname": "processing_time",
"fieldtype": "Time",
Expand All @@ -291,6 +293,7 @@
"fieldtype": "Column Break"
},
{
"depends_on": "eval: doc.auto_generate_entries",
"fieldname": "last_execution",
"fieldtype": "Datetime",
"label": "Last Execution",
Expand All @@ -299,7 +302,7 @@
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-03-01 10:44:27.963980",
"modified": "2025-03-02 08:40:59.207141",
"modified_by": "Administrator",
"module": "Payments Processor",
"name": "Payments Processor Configuration",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
# For license information, please see license.txt

import frappe
from erpnext import get_default_cost_center
from frappe import _
from frappe.model.document import Document
from frappe.utils import get_link_to_form

# Auto Payment Setting
# Payouts not required
Expand Down Expand Up @@ -49,6 +51,7 @@ def validate(self):
return

self.validate_default_discount_account()
self.validate_default_cost_center()
self.validate_automation_days()

def set_defaults(self):
Expand All @@ -65,14 +68,25 @@ def validate_default_discount_account(self):
default_discount_account = frappe.get_cached_value(
"Company", self.company, "default_discount_account"
)

if not default_discount_account:
if not default_discount_account and not frappe.flags.in_test:
frappe.throw(
_(
"Please set a default payment discount account in the company settings."
)
)

def validate_default_cost_center(self):
if not self.claim_early_payment_discount:
return

if not get_default_cost_center(self.company):
frappe.throw(
title=_("Default Cost Center Required"),
msg=_(
"Please set a default Cost Center in the Company {0} settings to claim early payment discounts."
).format(frappe.bold(get_link_to_form("Company", self.company))),
)

def validate_automation_days(self):
automation_days = [
self.automate_on_monday,
Expand Down
Loading