Merge branch 'version-13-hotfix' of https://github.com/frappe/erpnext into e-commerce-refactor
This commit is contained in:
7
.github/helper/install.sh
vendored
7
.github/helper/install.sh
vendored
@@ -4,11 +4,7 @@ set -e
|
||||
|
||||
cd ~ || exit
|
||||
|
||||
sudo apt-get install redis-server
|
||||
|
||||
sudo apt install nodejs
|
||||
|
||||
sudo apt install npm
|
||||
sudo apt-get install redis-server libcups2-dev
|
||||
|
||||
pip install frappe-bench
|
||||
|
||||
@@ -32,7 +28,6 @@ wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/w
|
||||
tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
|
||||
sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf
|
||||
sudo chmod o+x /usr/local/bin/wkhtmltopdf
|
||||
sudo apt-get install libcups2-dev
|
||||
|
||||
cd ~/frappe-bench || exit
|
||||
|
||||
|
||||
6
.github/workflows/patch.yml
vendored
6
.github/workflows/patch.yml
vendored
@@ -32,6 +32,12 @@ jobs:
|
||||
with:
|
||||
python-version: 3.6
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 12
|
||||
check-latest: true
|
||||
|
||||
- name: Add to Hosts
|
||||
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
||||
|
||||
|
||||
6
.github/workflows/server-tests.yml
vendored
6
.github/workflows/server-tests.yml
vendored
@@ -42,6 +42,12 @@ jobs:
|
||||
with:
|
||||
python-version: 3.7
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 12
|
||||
check-latest: true
|
||||
|
||||
- name: Add to Hosts
|
||||
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
||||
|
||||
|
||||
2
.github/workflows/ui-tests.yml
vendored
2
.github/workflows/ui-tests.yml
vendored
@@ -94,7 +94,7 @@ jobs:
|
||||
run: cd ~/frappe-bench/ && bench --site test_site execute erpnext.setup.utils.before_tests
|
||||
|
||||
- name: cypress pre-requisites
|
||||
run: cd ~/frappe-bench/apps/frappe && yarn add cypress-file-upload@^5 --no-lockfile
|
||||
run: cd ~/frappe-bench/apps/frappe && yarn add cypress-file-upload@^5 @testing-library/cypress@^8 --no-lockfile
|
||||
|
||||
|
||||
- name: Build Assets
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.contacts.doctype.address.address import Address
|
||||
from frappe.contacts.doctype.address.address import get_address_templates
|
||||
from frappe.contacts.doctype.address.address import get_address_templates, get_address_display
|
||||
|
||||
class ERPNextAddress(Address):
|
||||
def validate(self):
|
||||
@@ -22,6 +22,16 @@ class ERPNextAddress(Address):
|
||||
frappe.throw(_("Address needs to be linked to a Company. Please add a row for Company in the Links table."),
|
||||
title=_("Company Not Linked"))
|
||||
|
||||
def on_update(self):
|
||||
"""
|
||||
After Address is updated, update the related 'Primary Address' on Customer.
|
||||
"""
|
||||
address_display = get_address_display(self.as_dict())
|
||||
filters = { "customer_primary_address": self.name }
|
||||
customers = frappe.db.get_all("Customer", filters=filters, as_list=True)
|
||||
for customer_name in customers:
|
||||
frappe.db.set_value("Customer", customer_name[0], "primary_address", address_display)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_shipping_address(company, address = None):
|
||||
filters = [
|
||||
|
||||
@@ -74,7 +74,7 @@ frappe.ui.form.on('Account', {
|
||||
});
|
||||
} else if (cint(frm.doc.is_group) == 0
|
||||
&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
|
||||
cur_frm.add_custom_button(__('Ledger'), function () {
|
||||
frm.add_custom_button(__('Ledger'), function () {
|
||||
frappe.route_options = {
|
||||
"account": frm.doc.name,
|
||||
"from_date": frappe.sys_defaults.year_start_date,
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Accounting Period", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Accounting Period
|
||||
() => frappe.tests.make('Accounting Period', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Bank", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Bank
|
||||
() => frappe.tests.make('Bank', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Bank Account", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Bank Account
|
||||
() => frappe.tests.make('Bank Account', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Bank Account Subtype", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Bank Account Subtype
|
||||
() => frappe.tests.make('Bank Account Subtype', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Bank Guarantee", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Bank Guarantee
|
||||
() => frappe.tests.make('Bank Guarantee', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -55,6 +55,11 @@ class BankTransaction(StatusUpdater):
|
||||
self.clear_sales_invoice(payment_entry, for_cancel=for_cancel)
|
||||
|
||||
def clear_simple_entry(self, payment_entry, for_cancel=False):
|
||||
if payment_entry.payment_document == "Payment Entry":
|
||||
if frappe.db.get_value("Payment Entry", payment_entry.payment_entry, "payment_type") == "Internal Transfer":
|
||||
if len(get_reconciled_bank_transactions(payment_entry)) < 2:
|
||||
return
|
||||
|
||||
clearance_date = self.date if not for_cancel else None
|
||||
frappe.db.set_value(
|
||||
payment_entry.payment_document, payment_entry.payment_entry,
|
||||
@@ -70,6 +75,17 @@ class BankTransaction(StatusUpdater):
|
||||
),
|
||||
"clearance_date", clearance_date)
|
||||
|
||||
def get_reconciled_bank_transactions(payment_entry):
|
||||
reconciled_bank_transactions = frappe.get_all(
|
||||
'Bank Transaction Payments',
|
||||
filters = {
|
||||
'payment_entry': payment_entry.payment_entry
|
||||
},
|
||||
fields = ['parent']
|
||||
)
|
||||
|
||||
return reconciled_bank_transactions
|
||||
|
||||
def get_total_allocated_amount(payment_entry):
|
||||
return frappe.db.sql("""
|
||||
SELECT
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Bank Transaction", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Bank Transaction
|
||||
() => frappe.tests.make('Bank Transaction', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Cash Flow Mapper", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Cash Flow Mapper
|
||||
() => frappe.tests.make('Cash Flow Mapper', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Cash Flow Mapping", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Cash Flow Mapping
|
||||
() => frappe.tests.make('Cash Flow Mapping', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Cash Flow Mapping Template", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Cash Flow Mapping Template
|
||||
() => frappe.tests.make('Cash Flow Mapping Template', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Cash Flow Mapping Template Details", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Cash Flow Mapping Template Details
|
||||
() => frappe.tests.make('Cash Flow Mapping Template Details', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Cashier Closing", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Cashier Closing
|
||||
() => frappe.tests.make('Cashier Closing', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Chart of Accounts Importer", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Chart of Accounts Importer
|
||||
() => frappe.tests.make('Chart of Accounts Importer', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Coupon Code", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Coupon Code
|
||||
() => frappe.tests.make('Coupon Code', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Exchange Rate Revaluation", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Exchange Rate Revaluation
|
||||
() => frappe.tests.make('Exchange Rate Revaluation', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Finance Book", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Finance Book
|
||||
() => frappe.tests.make('Finance Book', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: GL Entry", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially('GL Entry', [
|
||||
// insert a new GL Entry
|
||||
() => frappe.tests.make([
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Item Tax Template", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Item Tax Template
|
||||
() => frappe.tests.make('Item Tax Template', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -643,7 +643,10 @@ class JournalEntry(AccountsController):
|
||||
for d in self.accounts:
|
||||
if d.reference_type=="Expense Claim" and d.reference_name:
|
||||
doc = frappe.get_doc("Expense Claim", d.reference_name)
|
||||
update_reimbursed_amount(doc, jv=self.name)
|
||||
if self.docstatus == 2:
|
||||
update_reimbursed_amount(doc, -1 * d.debit)
|
||||
else:
|
||||
update_reimbursed_amount(doc, d.debit)
|
||||
|
||||
|
||||
def validate_expense_claim(self):
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Loyalty Point Entry", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Loyalty Point Entry
|
||||
() => frappe.tests.make('Loyalty Point Entry', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Loyalty Program", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Loyalty Program
|
||||
() => frappe.tests.make('Loyalty Program', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Opening Invoice Creation Tool", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Opening Invoice Creation Tool
|
||||
() => frappe.tests.make('Opening Invoice Creation Tool', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -75,9 +75,9 @@ class PaymentEntry(AccountsController):
|
||||
if self.difference_amount:
|
||||
frappe.throw(_("Difference Amount must be zero"))
|
||||
self.make_gl_entries()
|
||||
self.update_expense_claim()
|
||||
self.update_outstanding_amounts()
|
||||
self.update_advance_paid()
|
||||
self.update_expense_claim()
|
||||
self.update_donation()
|
||||
self.update_payment_schedule()
|
||||
self.set_status()
|
||||
@@ -85,9 +85,9 @@ class PaymentEntry(AccountsController):
|
||||
def on_cancel(self):
|
||||
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
|
||||
self.make_gl_entries(cancel=1)
|
||||
self.update_expense_claim()
|
||||
self.update_outstanding_amounts()
|
||||
self.update_advance_paid()
|
||||
self.update_expense_claim()
|
||||
self.update_donation(cancel=1)
|
||||
self.delink_advance_entry_references()
|
||||
self.update_payment_schedule(cancel=1)
|
||||
@@ -755,9 +755,11 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
if self.payment_type in ('Pay', 'Internal Transfer'):
|
||||
dr_or_cr = "debit" if d.add_deduct_tax == "Add" else "credit"
|
||||
rev_dr_or_cr = "credit" if dr_or_cr == "debit" else "debit"
|
||||
against = self.party or self.paid_from
|
||||
elif self.payment_type == 'Receive':
|
||||
dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
|
||||
rev_dr_or_cr = "credit" if dr_or_cr == "debit" else "debit"
|
||||
against = self.party or self.paid_to
|
||||
|
||||
payment_or_advance_account = self.get_party_account_for_taxes()
|
||||
@@ -779,14 +781,13 @@ class PaymentEntry(AccountsController):
|
||||
"cost_center": d.cost_center
|
||||
}, account_currency, item=d))
|
||||
|
||||
#Intentionally use -1 to get net values in party account
|
||||
if not d.included_in_paid_amount or self.advance_tax_account:
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": payment_or_advance_account,
|
||||
"against": against,
|
||||
dr_or_cr: -1 * tax_amount,
|
||||
dr_or_cr + "_in_account_currency": -1 * base_tax_amount
|
||||
rev_dr_or_cr: tax_amount,
|
||||
rev_dr_or_cr + "_in_account_currency": base_tax_amount
|
||||
if account_currency==self.company_currency
|
||||
else d.tax_amount,
|
||||
"cost_center": self.cost_center,
|
||||
@@ -830,7 +831,10 @@ class PaymentEntry(AccountsController):
|
||||
for d in self.get("references"):
|
||||
if d.reference_doctype=="Expense Claim" and d.reference_name:
|
||||
doc = frappe.get_doc("Expense Claim", d.reference_name)
|
||||
update_reimbursed_amount(doc, self.name)
|
||||
if self.docstatus == 2:
|
||||
update_reimbursed_amount(doc, -1 * d.allocated_amount)
|
||||
else:
|
||||
update_reimbursed_amount(doc, d.allocated_amount)
|
||||
|
||||
def update_donation(self, cancel=0):
|
||||
if self.payment_type == "Receive" and self.party_type == "Donor" and self.party:
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Payment Order", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Payment Order
|
||||
() => frappe.tests.make('Payment Order', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Payment Request", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Payment Request
|
||||
() => frappe.tests.make('Payment Request', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Payment Term", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Payment Term
|
||||
() => frappe.tests.make('Payment Term', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Payment Terms Template", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Payment Terms Template
|
||||
() => frappe.tests.make('Payment Terms Template', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -13,59 +13,49 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal
|
||||
|
||||
class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
def test_closing_entry(self):
|
||||
year_start_date = get_fiscal_year(today(), company="_Test Company")[1]
|
||||
frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'")
|
||||
|
||||
make_journal_entry("_Test Bank - _TC", "Sales - _TC", 400,
|
||||
"_Test Cost Center - _TC", posting_date=now(), submit=True)
|
||||
company = create_company()
|
||||
cost_center = create_cost_center('Test Cost Center 1')
|
||||
|
||||
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Bank - _TC", 600, "_Test Cost Center - _TC", posting_date=now(), submit=True)
|
||||
jv1 = make_journal_entry(
|
||||
amount=400,
|
||||
account1="Cash - TPC",
|
||||
account2="Sales - TPC",
|
||||
cost_center=cost_center,
|
||||
posting_date=now(),
|
||||
save=False
|
||||
)
|
||||
jv1.company = company
|
||||
jv1.save()
|
||||
jv1.submit()
|
||||
|
||||
random_expense_account = frappe.db.sql("""
|
||||
select t1.account,
|
||||
sum(t1.debit) - sum(t1.credit) as balance,
|
||||
sum(t1.debit_in_account_currency) - sum(t1.credit_in_account_currency) \
|
||||
as balance_in_account_currency
|
||||
from `tabGL Entry` t1, `tabAccount` t2
|
||||
where t1.account = t2.name and t2.root_type = 'Expense'
|
||||
and t2.docstatus < 2 and t2.company = '_Test Company'
|
||||
and t1.posting_date between %s and %s
|
||||
group by t1.account
|
||||
having sum(t1.debit) > sum(t1.credit)
|
||||
limit 1""", (year_start_date, today()), as_dict=True)
|
||||
|
||||
profit_or_loss = frappe.db.sql("""select sum(t1.debit) - sum(t1.credit) as balance
|
||||
from `tabGL Entry` t1, `tabAccount` t2
|
||||
where t1.account = t2.name and t2.report_type = 'Profit and Loss'
|
||||
and t2.docstatus < 2 and t2.company = '_Test Company'
|
||||
and t1.posting_date between %s and %s""", (year_start_date, today()))
|
||||
|
||||
profit_or_loss = flt(profit_or_loss[0][0]) if profit_or_loss else 0
|
||||
jv2 = make_journal_entry(
|
||||
amount=600,
|
||||
account1="Cost of Goods Sold - TPC",
|
||||
account2="Cash - TPC",
|
||||
cost_center=cost_center,
|
||||
posting_date=now(),
|
||||
save=False
|
||||
)
|
||||
jv2.company = company
|
||||
jv2.save()
|
||||
jv2.submit()
|
||||
|
||||
pcv = self.make_period_closing_voucher()
|
||||
surplus_account = pcv.closing_account_head
|
||||
|
||||
# Check value for closing account
|
||||
gle_amount_for_closing_account = frappe.db.sql("""select debit - credit
|
||||
from `tabGL Entry` where voucher_type='Period Closing Voucher' and voucher_no=%s
|
||||
and account = '_Test Account Reserves and Surplus - _TC'""", pcv.name)
|
||||
expected_gle = (
|
||||
('Cost of Goods Sold - TPC', 0.0, 600.0),
|
||||
(surplus_account, 600.0, 400.0),
|
||||
('Sales - TPC', 400.0, 0.0)
|
||||
)
|
||||
|
||||
gle_amount_for_closing_account = flt(gle_amount_for_closing_account[0][0]) \
|
||||
if gle_amount_for_closing_account else 0
|
||||
pcv_gle = frappe.db.sql("""
|
||||
select account, debit, credit from `tabGL Entry` where voucher_no=%s order by account
|
||||
""", (pcv.name))
|
||||
|
||||
self.assertEqual(gle_amount_for_closing_account, profit_or_loss)
|
||||
|
||||
if random_expense_account:
|
||||
# Check posted value for teh above random_expense_account
|
||||
gle_for_random_expense_account = frappe.db.sql("""
|
||||
select sum(debit - credit) as amount,
|
||||
sum(debit_in_account_currency - credit_in_account_currency) as amount_in_account_currency
|
||||
from `tabGL Entry`
|
||||
where voucher_type='Period Closing Voucher' and voucher_no=%s and account =%s""",
|
||||
(pcv.name, random_expense_account[0].account), as_dict=True)
|
||||
|
||||
self.assertEqual(gle_for_random_expense_account[0].amount, -1*random_expense_account[0].balance)
|
||||
self.assertEqual(gle_for_random_expense_account[0].amount_in_account_currency,
|
||||
-1*random_expense_account[0].balance_in_account_currency)
|
||||
self.assertEqual(pcv_gle, expected_gle)
|
||||
|
||||
def test_cost_center_wise_posting(self):
|
||||
frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'")
|
||||
@@ -93,31 +83,23 @@ class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
debit_to="Debtors - TPC"
|
||||
)
|
||||
|
||||
pcv = frappe.get_doc({
|
||||
"transaction_date": today(),
|
||||
"posting_date": today(),
|
||||
"fiscal_year": get_fiscal_year(today())[0],
|
||||
"company": "Test PCV Company",
|
||||
"cost_center_wise_pnl": 1,
|
||||
"closing_account_head": surplus_account,
|
||||
"remarks": "Test",
|
||||
"doctype": "Period Closing Voucher"
|
||||
})
|
||||
pcv.insert()
|
||||
pcv.submit()
|
||||
pcv = self.make_period_closing_voucher()
|
||||
surplus_account = pcv.closing_account_head
|
||||
|
||||
expected_gle = (
|
||||
('Sales - TPC', 200.0, 0.0, cost_center2),
|
||||
(surplus_account, 0.0, 400.0, cost_center1),
|
||||
(surplus_account, 0.0, 200.0, cost_center2),
|
||||
('Sales - TPC', 400.0, 0.0, cost_center1),
|
||||
(surplus_account, 0.0, 400.0, cost_center1)
|
||||
('Sales - TPC', 200.0, 0.0, cost_center2),
|
||||
)
|
||||
|
||||
pcv_gle = frappe.db.sql("""
|
||||
select account, debit, credit, cost_center from `tabGL Entry` where voucher_no=%s
|
||||
select account, debit, credit, cost_center
|
||||
from `tabGL Entry` where voucher_no=%s
|
||||
order by account, cost_center
|
||||
""", (pcv.name))
|
||||
|
||||
self.assertTrue(pcv_gle, expected_gle)
|
||||
self.assertEqual(pcv_gle, expected_gle)
|
||||
|
||||
def test_period_closing_with_finance_book_entries(self):
|
||||
frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'")
|
||||
@@ -146,39 +128,35 @@ class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
jv.save()
|
||||
jv.submit()
|
||||
|
||||
pcv = frappe.get_doc({
|
||||
"transaction_date": today(),
|
||||
"posting_date": today(),
|
||||
"fiscal_year": get_fiscal_year(today())[0],
|
||||
"company": company,
|
||||
"closing_account_head": surplus_account,
|
||||
"remarks": "Test",
|
||||
"doctype": "Period Closing Voucher"
|
||||
})
|
||||
pcv.insert()
|
||||
pcv.submit()
|
||||
pcv = self.make_period_closing_voucher()
|
||||
surplus_account = pcv.closing_account_head
|
||||
|
||||
expected_gle = (
|
||||
(surplus_account, 0.0, 400.0, ''),
|
||||
(surplus_account, 0.0, 400.0, None),
|
||||
(surplus_account, 0.0, 400.0, jv.finance_book),
|
||||
('Sales - TPC', 400.0, 0.0, ''),
|
||||
('Sales - TPC', 400.0, 0.0, None),
|
||||
('Sales - TPC', 400.0, 0.0, jv.finance_book)
|
||||
)
|
||||
|
||||
pcv_gle = frappe.db.sql("""
|
||||
select account, debit, credit, finance_book from `tabGL Entry` where voucher_no=%s
|
||||
select account, debit, credit, finance_book
|
||||
from `tabGL Entry` where voucher_no=%s
|
||||
order by account, finance_book
|
||||
""", (pcv.name))
|
||||
|
||||
self.assertTrue(pcv_gle, expected_gle)
|
||||
self.assertEqual(pcv_gle, expected_gle)
|
||||
|
||||
def make_period_closing_voucher(self):
|
||||
surplus_account = create_account()
|
||||
cost_center = create_cost_center("Test Cost Center 1")
|
||||
pcv = frappe.get_doc({
|
||||
"doctype": "Period Closing Voucher",
|
||||
"closing_account_head": "_Test Account Reserves and Surplus - _TC",
|
||||
"company": "_Test Company",
|
||||
"fiscal_year": get_fiscal_year(today(), company="_Test Company")[0],
|
||||
"transaction_date": today(),
|
||||
"posting_date": today(),
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"company": "Test PCV Company",
|
||||
"fiscal_year": get_fiscal_year(today(), company="Test PCV Company")[0],
|
||||
"cost_center": cost_center,
|
||||
"closing_account_head": surplus_account,
|
||||
"remarks": "test"
|
||||
})
|
||||
pcv.insert()
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: POS Closing Entry", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new POS Closing Entry
|
||||
() => frappe.tests.make('POS Closing Entry', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: POS Profile", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially('POS Profile', [
|
||||
// insert a new POS Profile
|
||||
() => frappe.tests.make([
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: POS Profile User", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new POS Profile User
|
||||
() => frappe.tests.make('POS Profile User', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: POS Settings", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new POS Settings
|
||||
() => frappe.tests.make('POS Settings', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -475,7 +475,20 @@ def apply_pricing_rule_on_transaction(doc):
|
||||
frappe.msgprint(_("User has not applied rule on the invoice {0}")
|
||||
.format(doc.name))
|
||||
else:
|
||||
doc.set(field, d.get(pr_field))
|
||||
if not d.coupon_code_based:
|
||||
doc.set(field, d.get(pr_field))
|
||||
elif doc.get('coupon_code'):
|
||||
# coupon code based pricing rule
|
||||
coupon_code_pricing_rule = frappe.db.get_value('Coupon Code', doc.get('coupon_code'), 'pricing_rule')
|
||||
if coupon_code_pricing_rule == d.name:
|
||||
# if selected coupon code is linked with pricing rule
|
||||
doc.set(field, d.get(pr_field))
|
||||
else:
|
||||
# reset discount if not linked
|
||||
doc.set(field, 0)
|
||||
else:
|
||||
# if coupon code based but no coupon code selected
|
||||
doc.set(field, 0)
|
||||
|
||||
doc.calculate_taxes_and_totals()
|
||||
elif d.price_or_product_discount == 'Product':
|
||||
|
||||
@@ -719,19 +719,6 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
}
|
||||
},
|
||||
|
||||
project: function(frm){
|
||||
if (!frm.doc.is_return) {
|
||||
frm.call({
|
||||
method: "add_timesheet_data",
|
||||
doc: frm.doc,
|
||||
callback: function(r, rt) {
|
||||
refresh_field(['timesheets'])
|
||||
}
|
||||
})
|
||||
frm.refresh();
|
||||
}
|
||||
},
|
||||
|
||||
onload: function(frm) {
|
||||
frm.redemption_conversion_factor = null;
|
||||
},
|
||||
@@ -842,25 +829,92 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
}
|
||||
},
|
||||
|
||||
add_timesheet_row: function(frm, row, exchange_rate) {
|
||||
frm.add_child('timesheets', {
|
||||
'activity_type': row.activity_type,
|
||||
'description': row.description,
|
||||
'time_sheet': row.parent,
|
||||
'billing_hours': row.billing_hours,
|
||||
'billing_amount': flt(row.billing_amount) * flt(exchange_rate),
|
||||
'timesheet_detail': row.name,
|
||||
'project_name': row.project_name
|
||||
project: function(frm) {
|
||||
if (frm.doc.project) {
|
||||
frm.events.add_timesheet_data(frm, {
|
||||
project: frm.doc.project
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async add_timesheet_data(frm, kwargs) {
|
||||
if (kwargs === "Sales Invoice") {
|
||||
// called via frm.trigger()
|
||||
kwargs = Object();
|
||||
}
|
||||
|
||||
if (!kwargs.hasOwnProperty("project") && frm.doc.project) {
|
||||
kwargs.project = frm.doc.project;
|
||||
}
|
||||
|
||||
const timesheets = await frm.events.get_timesheet_data(frm, kwargs);
|
||||
return frm.events.set_timesheet_data(frm, timesheets);
|
||||
},
|
||||
|
||||
async get_timesheet_data(frm, kwargs) {
|
||||
return frappe.call({
|
||||
method: "erpnext.projects.doctype.timesheet.timesheet.get_projectwise_timesheet_data",
|
||||
args: kwargs
|
||||
}).then(r => {
|
||||
if (!r.exc && r.message.length > 0) {
|
||||
return r.message
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
});
|
||||
frm.refresh_field('timesheets');
|
||||
calculate_total_billing_amount(frm);
|
||||
},
|
||||
|
||||
set_timesheet_data: function(frm, timesheets) {
|
||||
frm.clear_table("timesheets")
|
||||
timesheets.forEach(timesheet => {
|
||||
if (frm.doc.currency != timesheet.currency) {
|
||||
frappe.call({
|
||||
method: "erpnext.setup.utils.get_exchange_rate",
|
||||
args: {
|
||||
from_currency: timesheet.currency,
|
||||
to_currency: frm.doc.currency
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
exchange_rate = r.message;
|
||||
frm.events.append_time_log(frm, timesheet, exchange_rate);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
frm.events.append_time_log(frm, timesheet, 1.0);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
append_time_log: function(frm, time_log, exchange_rate) {
|
||||
const row = frm.add_child("timesheets");
|
||||
row.activity_type = time_log.activity_type;
|
||||
row.description = time_log.description;
|
||||
row.time_sheet = time_log.time_sheet;
|
||||
row.from_time = time_log.from_time;
|
||||
row.to_time = time_log.to_time;
|
||||
row.billing_hours = time_log.billing_hours;
|
||||
row.billing_amount = flt(time_log.billing_amount) * flt(exchange_rate);
|
||||
row.timesheet_detail = time_log.name;
|
||||
row.project_name = time_log.project_name;
|
||||
|
||||
frm.refresh_field("timesheets");
|
||||
frm.trigger("calculate_timesheet_totals");
|
||||
},
|
||||
|
||||
calculate_timesheet_totals: function(frm) {
|
||||
frm.set_value("total_billing_amount",
|
||||
frm.doc.timesheets.reduce((a, b) => a + (b["billing_amount"] || 0.0), 0.0));
|
||||
frm.set_value("total_billing_hours",
|
||||
frm.doc.timesheets.reduce((a, b) => a + (b["billing_hours"] || 0.0), 0.0));
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
if (frm.doc.docstatus===0 && !frm.doc.is_return) {
|
||||
frm.add_custom_button(__('Fetch Timesheet'), function() {
|
||||
frm.add_custom_button(__("Fetch Timesheet"), function() {
|
||||
let d = new frappe.ui.Dialog({
|
||||
title: __('Fetch Timesheet'),
|
||||
title: __("Fetch Timesheet"),
|
||||
fields: [
|
||||
{
|
||||
"label" : __("From"),
|
||||
@@ -869,8 +923,8 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
"reqd": 1,
|
||||
},
|
||||
{
|
||||
fieldtype: 'Column Break',
|
||||
fieldname: 'col_break_1',
|
||||
fieldtype: "Column Break",
|
||||
fieldname: "col_break_1",
|
||||
},
|
||||
{
|
||||
"label" : __("To"),
|
||||
@@ -887,48 +941,18 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
},
|
||||
],
|
||||
primary_action: function() {
|
||||
let data = d.get_values();
|
||||
frappe.call({
|
||||
method: "erpnext.projects.doctype.timesheet.timesheet.get_projectwise_timesheet_data",
|
||||
args: {
|
||||
from_time: data.from_time,
|
||||
to_time: data.to_time,
|
||||
project: data.project
|
||||
},
|
||||
callback: function(r) {
|
||||
if (!r.exc && r.message.length > 0) {
|
||||
frm.clear_table('timesheets')
|
||||
r.message.forEach((d) => {
|
||||
let exchange_rate = 1.0;
|
||||
if (frm.doc.currency != d.currency) {
|
||||
frappe.call({
|
||||
method: 'erpnext.setup.utils.get_exchange_rate',
|
||||
args: {
|
||||
from_currency: d.currency,
|
||||
to_currency: frm.doc.currency
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
exchange_rate = r.message;
|
||||
frm.events.add_timesheet_row(frm, d, exchange_rate);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
frm.events.add_timesheet_row(frm, d, exchange_rate);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
frappe.msgprint(__('No Timesheets found with the selected filters.'))
|
||||
}
|
||||
d.hide();
|
||||
}
|
||||
const data = d.get_values();
|
||||
frm.events.add_timesheet_data(frm, {
|
||||
from_time: data.from_time,
|
||||
to_time: data.to_time,
|
||||
project: data.project
|
||||
});
|
||||
d.hide();
|
||||
},
|
||||
primary_action_label: __('Get Timesheets')
|
||||
primary_action_label: __("Get Timesheets")
|
||||
});
|
||||
d.show();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (frm.doc.is_debit_note) {
|
||||
@@ -961,26 +985,22 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
frm: frm
|
||||
});
|
||||
},
|
||||
|
||||
create_dunning: function(frm) {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.create_dunning",
|
||||
frm: frm
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
var calculate_total_billing_amount = function(frm) {
|
||||
var doc = frm.doc;
|
||||
|
||||
doc.total_billing_amount = 0.0
|
||||
if (doc.timesheets) {
|
||||
$.each(doc.timesheets, function(index, data){
|
||||
doc.total_billing_amount += flt(data.billing_amount)
|
||||
})
|
||||
frappe.ui.form.on("Sales Invoice Timesheet", {
|
||||
timesheets_remove(frm, cdt, cdn) {
|
||||
frm.trigger("calculate_timesheet_totals");
|
||||
}
|
||||
});
|
||||
|
||||
refresh_field('total_billing_amount')
|
||||
}
|
||||
|
||||
var set_timesheet_detail_rate = function(cdt, cdn, currency, timelog) {
|
||||
frappe.call({
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
"time_sheet_list",
|
||||
"timesheets",
|
||||
"total_billing_amount",
|
||||
"total_billing_hours",
|
||||
"section_break_30",
|
||||
"total_qty",
|
||||
"base_total",
|
||||
@@ -2011,6 +2012,13 @@
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Dispatch Address",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "total_billing_hours",
|
||||
"fieldtype": "Float",
|
||||
"label": "Total Billing Hours",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-file-text",
|
||||
@@ -2023,7 +2031,7 @@
|
||||
"link_fieldname": "consolidated_invoice"
|
||||
}
|
||||
],
|
||||
"modified": "2021-08-25 14:46:05.279588",
|
||||
"modified": "2021-08-25 15:46:05.279588",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
@@ -2077,4 +2085,4 @@
|
||||
"title_field": "title",
|
||||
"track_changes": 1,
|
||||
"track_seen": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
import frappe.defaults
|
||||
from frappe.utils import cint, flt, getdate, add_days, cstr, nowdate, get_link_to_form, formatdate
|
||||
from frappe.utils import cint, flt, getdate, add_days, add_months, cstr, nowdate, get_link_to_form, formatdate
|
||||
from frappe import _, msgprint, throw
|
||||
from erpnext.accounts.party import get_party_account, get_due_date, get_party_details
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
@@ -13,7 +13,7 @@ from erpnext.accounts.utils import get_account_currency
|
||||
from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so
|
||||
from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timesheet_data
|
||||
from erpnext.assets.doctype.asset.depreciation \
|
||||
import get_disposal_account_and_cost_center, get_gl_entries_on_asset_disposal
|
||||
import get_disposal_account_and_cost_center, get_gl_entries_on_asset_disposal, get_gl_entries_on_asset_regain, post_depreciation_entries
|
||||
from erpnext.stock.doctype.batch.batch import set_batch_nos
|
||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos, get_delivery_note_serial_no
|
||||
from erpnext.setup.doctype.company.company import update_company_current_month_sales
|
||||
@@ -149,7 +149,7 @@ class SalesInvoice(SellingController):
|
||||
if self.update_stock:
|
||||
frappe.throw(_("'Update Stock' cannot be checked for fixed asset sale"))
|
||||
|
||||
elif asset.status in ("Scrapped", "Cancelled", "Sold"):
|
||||
elif asset.status in ("Scrapped", "Cancelled") or (asset.status == "Sold" and not self.is_return):
|
||||
frappe.throw(_("Row #{0}: Asset {1} cannot be submitted, it is already {2}").format(d.idx, d.asset, asset.status))
|
||||
|
||||
def validate_item_cost_centers(self):
|
||||
@@ -757,7 +757,7 @@ class SalesInvoice(SellingController):
|
||||
if self.project:
|
||||
for data in get_projectwise_timesheet_data(self.project):
|
||||
self.append('timesheets', {
|
||||
'time_sheet': data.parent,
|
||||
'time_sheet': data.time_sheet,
|
||||
'billing_hours': data.billing_hours,
|
||||
'billing_amount': data.billing_amount,
|
||||
'timesheet_detail': data.name,
|
||||
@@ -768,12 +768,11 @@ class SalesInvoice(SellingController):
|
||||
self.calculate_billing_amount_for_timesheet()
|
||||
|
||||
def calculate_billing_amount_for_timesheet(self):
|
||||
total_billing_amount = 0.0
|
||||
for data in self.timesheets:
|
||||
if data.billing_amount:
|
||||
total_billing_amount += data.billing_amount
|
||||
def timesheet_sum(field):
|
||||
return sum((ts.get(field) or 0.0) for ts in self.timesheets)
|
||||
|
||||
self.total_billing_amount = total_billing_amount
|
||||
self.total_billing_amount = timesheet_sum("billing_amount")
|
||||
self.total_billing_hours = timesheet_sum("billing_hours")
|
||||
|
||||
def get_warehouse(self):
|
||||
user_pos_profile = frappe.db.sql("""select name, warehouse from `tabPOS Profile`
|
||||
@@ -925,22 +924,30 @@ class SalesInvoice(SellingController):
|
||||
for item in self.get("items"):
|
||||
if flt(item.base_net_amount, item.precision("base_net_amount")):
|
||||
if item.is_fixed_asset:
|
||||
asset = frappe.get_doc("Asset", item.asset)
|
||||
asset = self.get_asset(item)
|
||||
|
||||
if (len(asset.finance_books) > 1 and not item.finance_book
|
||||
and asset.finance_books[0].finance_book):
|
||||
frappe.throw(_("Select finance book for the item {0} at row {1}")
|
||||
.format(item.item_code, item.idx))
|
||||
if self.is_return:
|
||||
fixed_asset_gl_entries = get_gl_entries_on_asset_regain(asset,
|
||||
item.base_net_amount, item.finance_book)
|
||||
asset.db_set("disposal_date", None)
|
||||
|
||||
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset,
|
||||
item.base_net_amount, item.finance_book)
|
||||
if asset.calculate_depreciation:
|
||||
self.reset_depreciation_schedule(asset)
|
||||
|
||||
else:
|
||||
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset,
|
||||
item.base_net_amount, item.finance_book)
|
||||
asset.db_set("disposal_date", self.posting_date)
|
||||
|
||||
if asset.calculate_depreciation:
|
||||
self.depreciate_asset(asset)
|
||||
|
||||
for gle in fixed_asset_gl_entries:
|
||||
gle["against"] = self.customer
|
||||
gl_entries.append(self.get_gl_dict(gle, item=item))
|
||||
|
||||
asset.db_set("disposal_date", self.posting_date)
|
||||
asset.set_status("Sold" if self.docstatus==1 else None)
|
||||
self.set_asset_status(asset)
|
||||
|
||||
else:
|
||||
# Do not book income for transfer within same company
|
||||
if not self.is_internal_transfer():
|
||||
@@ -968,6 +975,89 @@ class SalesInvoice(SellingController):
|
||||
erpnext.is_perpetual_inventory_enabled(self.company):
|
||||
gl_entries += super(SalesInvoice, self).get_gl_entries()
|
||||
|
||||
def get_asset(self, item):
|
||||
if item.get('asset'):
|
||||
asset = frappe.get_doc("Asset", item.asset)
|
||||
else:
|
||||
frappe.throw(_(
|
||||
"Row #{0}: You must select an Asset for Item {1}.").format(item.idx, item.item_name),
|
||||
title=_("Missing Asset")
|
||||
)
|
||||
|
||||
self.check_finance_books(item, asset)
|
||||
return asset
|
||||
|
||||
def check_finance_books(self, item, asset):
|
||||
if (len(asset.finance_books) > 1 and not item.finance_book
|
||||
and asset.finance_books[0].finance_book):
|
||||
frappe.throw(_("Select finance book for the item {0} at row {1}")
|
||||
.format(item.item_code, item.idx))
|
||||
|
||||
def depreciate_asset(self, asset):
|
||||
asset.flags.ignore_validate_update_after_submit = True
|
||||
asset.prepare_depreciation_data(self.posting_date)
|
||||
asset.save()
|
||||
|
||||
post_depreciation_entries(self.posting_date)
|
||||
|
||||
def reset_depreciation_schedule(self, asset):
|
||||
asset.flags.ignore_validate_update_after_submit = True
|
||||
|
||||
# recreate original depreciation schedule of the asset
|
||||
asset.prepare_depreciation_data()
|
||||
|
||||
self.modify_depreciation_schedule_for_asset_repairs(asset)
|
||||
asset.save()
|
||||
|
||||
self.delete_depreciation_entry_made_after_sale(asset)
|
||||
|
||||
def modify_depreciation_schedule_for_asset_repairs(self, asset):
|
||||
asset_repairs = frappe.get_all(
|
||||
'Asset Repair',
|
||||
filters = {'asset': asset.name},
|
||||
fields = ['name', 'increase_in_asset_life']
|
||||
)
|
||||
|
||||
for repair in asset_repairs:
|
||||
if repair.increase_in_asset_life:
|
||||
asset_repair = frappe.get_doc('Asset Repair', repair.name)
|
||||
asset_repair.modify_depreciation_schedule()
|
||||
asset.prepare_depreciation_data()
|
||||
|
||||
def delete_depreciation_entry_made_after_sale(self, asset):
|
||||
from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry
|
||||
|
||||
posting_date_of_original_invoice = self.get_posting_date_of_sales_invoice()
|
||||
|
||||
row = -1
|
||||
finance_book = asset.get('schedules')[0].get('finance_book')
|
||||
for schedule in asset.get('schedules'):
|
||||
if schedule.finance_book != finance_book:
|
||||
row = 0
|
||||
finance_book = schedule.finance_book
|
||||
else:
|
||||
row += 1
|
||||
|
||||
if schedule.schedule_date == posting_date_of_original_invoice:
|
||||
if not self.sale_was_made_on_original_schedule_date(asset, schedule, row, posting_date_of_original_invoice):
|
||||
reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry)
|
||||
reverse_journal_entry.posting_date = nowdate()
|
||||
reverse_journal_entry.submit()
|
||||
|
||||
def get_posting_date_of_sales_invoice(self):
|
||||
return frappe.db.get_value('Sales Invoice', self.return_against, 'posting_date')
|
||||
|
||||
# if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone
|
||||
def sale_was_made_on_original_schedule_date(self, asset, schedule, row, posting_date_of_original_invoice):
|
||||
for finance_book in asset.get('finance_books'):
|
||||
if schedule.finance_book == finance_book.finance_book:
|
||||
orginal_schedule_date = add_months(finance_book.depreciation_start_date,
|
||||
row * cint(finance_book.frequency_of_depreciation))
|
||||
|
||||
if orginal_schedule_date == posting_date_of_original_invoice:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def enable_discount_accounting(self):
|
||||
if not hasattr(self, "_enable_discount_accounting"):
|
||||
|
||||
@@ -10,6 +10,8 @@ from frappe.model.dynamic_links import get_dynamic_link_map
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
|
||||
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
|
||||
from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_data
|
||||
from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries
|
||||
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
|
||||
from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError
|
||||
from frappe.model.naming import make_autoname
|
||||
@@ -1106,6 +1108,45 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
self.assertFalse(si1.outstanding_amount)
|
||||
self.assertEqual(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"), 1500)
|
||||
|
||||
def test_gle_made_when_asset_is_returned(self):
|
||||
create_asset_data()
|
||||
|
||||
pi = frappe.new_doc('Purchase Invoice')
|
||||
pi.supplier = '_Test Supplier'
|
||||
pi.append('items', {
|
||||
'item_code': 'Macbook Pro',
|
||||
'qty': 1
|
||||
})
|
||||
pi.set_missing_values()
|
||||
|
||||
asset = create_asset(item_code="Macbook Pro")
|
||||
|
||||
si = create_sales_invoice(item_code="Macbook Pro", asset=asset.name, qty=1, rate=90000)
|
||||
return_si = create_sales_invoice(is_return=1, return_against=si.name, item_code="Macbook Pro", asset=asset.name, qty=-1, rate=90000)
|
||||
|
||||
disposal_account = frappe.get_cached_value("Company", "_Test Company", "disposal_account")
|
||||
|
||||
# Asset value is 100,000 but it was sold for 90,000, so there should be a loss of 10,000
|
||||
loss_for_si = frappe.get_all(
|
||||
"GL Entry",
|
||||
filters = {
|
||||
"voucher_no": si.name,
|
||||
"account": disposal_account
|
||||
},
|
||||
fields = ["credit", "debit"]
|
||||
)[0]
|
||||
|
||||
loss_for_return_si = frappe.get_all(
|
||||
"GL Entry",
|
||||
filters = {
|
||||
"voucher_no": return_si.name,
|
||||
"account": disposal_account
|
||||
},
|
||||
fields = ["credit", "debit"]
|
||||
)[0]
|
||||
|
||||
self.assertEqual(loss_for_si['credit'], loss_for_return_si['debit'])
|
||||
self.assertEqual(loss_for_si['debit'], loss_for_return_si['credit'])
|
||||
|
||||
def test_incoming_rate_for_stand_alone_credit_note(self):
|
||||
return_si = create_sales_invoice(is_return=1, update_stock=1, qty=-1, rate=90000, incoming_rate=10,
|
||||
@@ -2108,6 +2149,30 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
check_gl_entries(self, si.name, expected_gle, add_days(nowdate(), -1))
|
||||
enable_discount_accounting(enable=0)
|
||||
|
||||
def test_asset_depreciation_on_sale(self):
|
||||
"""
|
||||
Tests if an Asset set to depreciate yearly on June 30, that gets sold on Sept 30, creates an additional depreciation entry on Sept 30.
|
||||
"""
|
||||
|
||||
create_asset_data()
|
||||
asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, submit=1)
|
||||
post_depreciation_entries(getdate("2021-09-30"))
|
||||
|
||||
create_sales_invoice(item_code="Macbook Pro", asset=asset.name, qty=1, rate=90000, posting_date=getdate("2021-09-30"))
|
||||
asset.load_from_db()
|
||||
|
||||
expected_values = [
|
||||
["2020-06-30", 1311.48, 1311.48],
|
||||
["2021-06-30", 20000.0, 21311.48],
|
||||
["2021-09-30", 3966.76, 25278.24]
|
||||
]
|
||||
|
||||
for i, schedule in enumerate(asset.schedules):
|
||||
self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date)
|
||||
self.assertEqual(expected_values[i][1], schedule.depreciation_amount)
|
||||
self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount)
|
||||
self.assertTrue(schedule.journal_entry)
|
||||
|
||||
def test_sales_invoice_against_supplier(self):
|
||||
from erpnext.accounts.doctype.opening_invoice_creation_tool.test_opening_invoice_creation_tool import make_customer
|
||||
from erpnext.buying.doctype.supplier.test_supplier import create_supplier
|
||||
@@ -2360,6 +2425,7 @@ def create_sales_invoice(**args):
|
||||
"price_list_rate": args.price_list_rate if args.get("price_list_rate") is not None else 100,
|
||||
"income_account": args.income_account or "Sales - _TC",
|
||||
"expense_account": args.expense_account or "Cost of Goods Sold - _TC",
|
||||
"asset": args.asset or None,
|
||||
"discount_account": args.discount_account or None,
|
||||
"discount_amount": args.discount_amount or 0,
|
||||
"cost_center": args.cost_center or "_Test Cost Center - _TC",
|
||||
|
||||
@@ -7,12 +7,19 @@
|
||||
"field_order": [
|
||||
"activity_type",
|
||||
"description",
|
||||
"section_break_3",
|
||||
"from_time",
|
||||
"column_break_5",
|
||||
"to_time",
|
||||
"section_break_7",
|
||||
"billing_hours",
|
||||
"column_break_9",
|
||||
"billing_amount",
|
||||
"section_break_11",
|
||||
"timesheet_detail",
|
||||
"column_break_5",
|
||||
"time_sheet",
|
||||
"project_name",
|
||||
"timesheet_detail"
|
||||
"project_name"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -64,10 +71,40 @@
|
||||
"label": "Description",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "from_time",
|
||||
"fieldtype": "Datetime",
|
||||
"label": "From Time"
|
||||
},
|
||||
{
|
||||
"fieldname": "to_time",
|
||||
"fieldtype": "Datetime",
|
||||
"label": "To Time"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_3",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Time"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_5",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
|
||||
"fieldname": "section_break_7",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Totals"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_11",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Reference"
|
||||
},
|
||||
{
|
||||
"fieldname": "project_name",
|
||||
"fieldtype": "Data",
|
||||
@@ -77,7 +114,7 @@
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-06-08 14:43:02.748981",
|
||||
"modified": "2021-08-15 18:37:08.084930",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Timesheet",
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Share Transfer", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Share Transfer
|
||||
() => frappe.tests.make('Share Transfer', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Share Type", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Share Type
|
||||
() => frappe.tests.make('Share Type', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Shareholder", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Shareholder
|
||||
() => frappe.tests.make('Shareholder', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Subscription Invoice", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Subscription Invoice
|
||||
() => frappe.tests.make('Subscription Invoice', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -21,7 +21,7 @@
|
||||
"column_break_13",
|
||||
"billing_interval_count",
|
||||
"payment_plan_section",
|
||||
"payment_plan_id",
|
||||
"product_price_id",
|
||||
"column_break_16",
|
||||
"payment_gateway",
|
||||
"accounting_dimensions_section",
|
||||
@@ -114,11 +114,6 @@
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Payment Plan"
|
||||
},
|
||||
{
|
||||
"fieldname": "payment_plan_id",
|
||||
"fieldtype": "Data",
|
||||
"label": "Payment Plan"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_16",
|
||||
"fieldtype": "Column Break"
|
||||
@@ -144,10 +139,15 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Cost Center",
|
||||
"options": "Cost Center"
|
||||
},
|
||||
{
|
||||
"fieldname": "product_price_id",
|
||||
"fieldtype": "Data",
|
||||
"label": "Product Price ID"
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2021-08-09 10:53:44.205774",
|
||||
"modified": "2021-08-13 10:53:44.205774",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Subscription Plan",
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Subscription Plan", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Subscription Plan
|
||||
() => frappe.tests.make('Subscription Plan', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Subscription Settings", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Subscription Settings
|
||||
() => frappe.tests.make('Subscription Settings', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Tax Category", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Tax Category
|
||||
() => frappe.tests.make('Tax Category', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Tax Rule", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Tax Rule
|
||||
() => frappe.tests.make('Tax Rule', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Tax Withholding Category", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Tax Withholding Category
|
||||
() => frappe.tests.make('Tax Withholding Category', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1086,3 +1086,14 @@ def get_journal_entry(account, stock_adjustment_account, amount):
|
||||
db_or_cr_stock_adjustment_account : abs(amount)
|
||||
}]
|
||||
}
|
||||
|
||||
def check_and_delete_linked_reports(report):
|
||||
""" Check if reports are referenced in Desktop Icon """
|
||||
icons = frappe.get_all("Desktop Icon",
|
||||
fields = ['name'],
|
||||
filters = {
|
||||
"_report": report
|
||||
})
|
||||
if icons:
|
||||
for icon in icons:
|
||||
frappe.delete_doc("Desktop Icon", icon)
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Agriculture Analysis Criteria", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Agriculture Analysis Criteria
|
||||
() => frappe.tests.make('Agriculture Analysis Criteria', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Agriculture Task", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Agriculture Task
|
||||
() => frappe.tests.make('Agriculture Task', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Plant Analysis", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Plant Analysis
|
||||
() => frappe.tests.make('Plant Analysis', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Soil Analysis", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Soil Analysis
|
||||
() => frappe.tests.make('Soil Analysis', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Weather", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Weather
|
||||
() => frappe.tests.make('Weather', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -56,12 +56,12 @@ class Asset(AccountsController):
|
||||
if self.is_existing_asset and self.purchase_invoice:
|
||||
frappe.throw(_("Purchase Invoice cannot be made against an existing asset {0}").format(self.name))
|
||||
|
||||
def prepare_depreciation_data(self):
|
||||
def prepare_depreciation_data(self, date_of_sale=None):
|
||||
if self.calculate_depreciation:
|
||||
self.value_after_depreciation = 0
|
||||
self.set_depreciation_rate()
|
||||
self.make_depreciation_schedule()
|
||||
self.set_accumulated_depreciation()
|
||||
self.make_depreciation_schedule(date_of_sale)
|
||||
self.set_accumulated_depreciation(date_of_sale)
|
||||
else:
|
||||
self.finance_books = []
|
||||
self.value_after_depreciation = (flt(self.gross_purchase_amount) -
|
||||
@@ -167,7 +167,7 @@ class Asset(AccountsController):
|
||||
d.rate_of_depreciation = flt(self.get_depreciation_rate(d, on_validate=True),
|
||||
d.precision("rate_of_depreciation"))
|
||||
|
||||
def make_depreciation_schedule(self):
|
||||
def make_depreciation_schedule(self, date_of_sale):
|
||||
if 'Manual' not in [d.depreciation_method for d in self.finance_books] and not self.schedules:
|
||||
self.schedules = []
|
||||
|
||||
@@ -212,6 +212,21 @@ class Asset(AccountsController):
|
||||
# so monthly schedule date is calculated by removing 11 months from it
|
||||
monthly_schedule_date = add_months(schedule_date, - d.frequency_of_depreciation + 1)
|
||||
|
||||
# if asset is being sold
|
||||
if date_of_sale:
|
||||
from_date = self.get_from_date(d.finance_book)
|
||||
depreciation_amount, days, months = self.get_pro_rata_amt(d, depreciation_amount,
|
||||
from_date, date_of_sale)
|
||||
|
||||
self.append("schedules", {
|
||||
"schedule_date": date_of_sale,
|
||||
"depreciation_amount": depreciation_amount,
|
||||
"depreciation_method": d.depreciation_method,
|
||||
"finance_book": d.finance_book,
|
||||
"finance_book_id": d.idx
|
||||
})
|
||||
break
|
||||
|
||||
# For first row
|
||||
if has_pro_rata and n==0:
|
||||
depreciation_amount, days, months = self.get_pro_rata_amt(d, depreciation_amount,
|
||||
@@ -303,6 +318,21 @@ class Asset(AccountsController):
|
||||
break
|
||||
return start
|
||||
|
||||
def get_from_date(self, finance_book):
|
||||
if not self.get('schedules'):
|
||||
return self.available_for_use_date
|
||||
|
||||
if len(self.finance_books) == 1:
|
||||
return self.schedules[-1].schedule_date
|
||||
|
||||
from_date = ""
|
||||
for schedule in self.get('schedules'):
|
||||
if schedule.finance_book == finance_book:
|
||||
from_date = schedule.schedule_date
|
||||
|
||||
if from_date:
|
||||
return from_date
|
||||
return self.available_for_use_date
|
||||
|
||||
# if it returns True, depreciation_amount will not be equal for the first and last rows
|
||||
def check_is_pro_rata(self, row):
|
||||
@@ -357,7 +387,7 @@ class Asset(AccountsController):
|
||||
frappe.throw(_("Depreciation Row {0}: Next Depreciation Date cannot be before Available-for-use Date")
|
||||
.format(row.idx))
|
||||
|
||||
def set_accumulated_depreciation(self, ignore_booked_entry = False):
|
||||
def set_accumulated_depreciation(self, date_of_sale=None, ignore_booked_entry = False):
|
||||
straight_line_idx = [d.idx for d in self.get("schedules") if d.depreciation_method == 'Straight Line']
|
||||
finance_books = []
|
||||
|
||||
@@ -365,7 +395,7 @@ class Asset(AccountsController):
|
||||
if ignore_booked_entry and d.journal_entry:
|
||||
continue
|
||||
|
||||
if d.finance_book_id not in finance_books:
|
||||
if int(d.finance_book_id) not in finance_books:
|
||||
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
|
||||
value_after_depreciation = flt(self.get_value_after_depreciation(d.finance_book_id))
|
||||
finance_books.append(int(d.finance_book_id))
|
||||
@@ -374,7 +404,7 @@ class Asset(AccountsController):
|
||||
value_after_depreciation -= flt(depreciation_amount)
|
||||
|
||||
# for the last row, if depreciation method = Straight Line
|
||||
if straight_line_idx and i == max(straight_line_idx) - 1:
|
||||
if straight_line_idx and i == max(straight_line_idx) - 1 and not date_of_sale:
|
||||
book = self.get('finance_books')[cint(d.finance_book_id) - 1]
|
||||
depreciation_amount += flt(value_after_depreciation -
|
||||
flt(book.expected_value_after_useful_life), d.precision("depreciation_amount"))
|
||||
|
||||
@@ -176,22 +176,34 @@ def restore_asset(asset_name):
|
||||
|
||||
asset.set_status()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_gl_entries_on_asset_regain(asset, selling_amount=0, finance_book=None):
|
||||
fixed_asset_account, asset, depreciation_cost_center, accumulated_depr_account, accumulated_depr_amount, disposal_account, value_after_depreciation = \
|
||||
get_asset_details(asset, finance_book)
|
||||
|
||||
gl_entries = [
|
||||
{
|
||||
"account": fixed_asset_account,
|
||||
"debit_in_account_currency": asset.gross_purchase_amount,
|
||||
"debit": asset.gross_purchase_amount,
|
||||
"cost_center": depreciation_cost_center
|
||||
},
|
||||
{
|
||||
"account": accumulated_depr_account,
|
||||
"credit_in_account_currency": accumulated_depr_amount,
|
||||
"credit": accumulated_depr_amount,
|
||||
"cost_center": depreciation_cost_center
|
||||
}
|
||||
]
|
||||
|
||||
profit_amount = abs(flt(value_after_depreciation)) - abs(flt(selling_amount))
|
||||
if profit_amount:
|
||||
get_profit_gl_entries(profit_amount, gl_entries, disposal_account, depreciation_cost_center)
|
||||
|
||||
return gl_entries
|
||||
|
||||
def get_gl_entries_on_asset_disposal(asset, selling_amount=0, finance_book=None):
|
||||
fixed_asset_account, accumulated_depr_account, depr_expense_account = get_depreciation_accounts(asset)
|
||||
disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(asset.company)
|
||||
depreciation_cost_center = asset.cost_center or depreciation_cost_center
|
||||
|
||||
idx = 1
|
||||
if finance_book:
|
||||
for d in asset.finance_books:
|
||||
if d.finance_book == finance_book:
|
||||
idx = d.idx
|
||||
break
|
||||
|
||||
value_after_depreciation = (asset.finance_books[idx - 1].value_after_depreciation
|
||||
if asset.calculate_depreciation else asset.value_after_depreciation)
|
||||
accumulated_depr_amount = flt(asset.gross_purchase_amount) - flt(value_after_depreciation)
|
||||
fixed_asset_account, asset, depreciation_cost_center, accumulated_depr_account, accumulated_depr_amount, disposal_account, value_after_depreciation = \
|
||||
get_asset_details(asset, finance_book)
|
||||
|
||||
gl_entries = [
|
||||
{
|
||||
@@ -210,16 +222,37 @@ def get_gl_entries_on_asset_disposal(asset, selling_amount=0, finance_book=None)
|
||||
|
||||
profit_amount = flt(selling_amount) - flt(value_after_depreciation)
|
||||
if profit_amount:
|
||||
debit_or_credit = "debit" if profit_amount < 0 else "credit"
|
||||
gl_entries.append({
|
||||
"account": disposal_account,
|
||||
"cost_center": depreciation_cost_center,
|
||||
debit_or_credit: abs(profit_amount),
|
||||
debit_or_credit + "_in_account_currency": abs(profit_amount)
|
||||
})
|
||||
get_profit_gl_entries(profit_amount, gl_entries, disposal_account, depreciation_cost_center)
|
||||
|
||||
return gl_entries
|
||||
|
||||
def get_asset_details(asset, finance_book=None):
|
||||
fixed_asset_account, accumulated_depr_account, depr_expense_account = get_depreciation_accounts(asset)
|
||||
disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(asset.company)
|
||||
depreciation_cost_center = asset.cost_center or depreciation_cost_center
|
||||
|
||||
idx = 1
|
||||
if finance_book:
|
||||
for d in asset.finance_books:
|
||||
if d.finance_book == finance_book:
|
||||
idx = d.idx
|
||||
break
|
||||
|
||||
value_after_depreciation = (asset.finance_books[idx - 1].value_after_depreciation
|
||||
if asset.calculate_depreciation else asset.value_after_depreciation)
|
||||
accumulated_depr_amount = flt(asset.gross_purchase_amount) - flt(value_after_depreciation)
|
||||
|
||||
return fixed_asset_account, asset, depreciation_cost_center, accumulated_depr_account, accumulated_depr_amount, disposal_account, value_after_depreciation
|
||||
|
||||
def get_profit_gl_entries(profit_amount, gl_entries, disposal_account, depreciation_cost_center):
|
||||
debit_or_credit = "debit" if profit_amount < 0 else "credit"
|
||||
gl_entries.append({
|
||||
"account": disposal_account,
|
||||
"cost_center": depreciation_cost_center,
|
||||
debit_or_credit: abs(profit_amount),
|
||||
debit_or_credit + "_in_account_currency": abs(profit_amount)
|
||||
})
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_disposal_account_and_cost_center(company):
|
||||
disposal_account, depreciation_cost_center = frappe.get_cached_value('Company', company,
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Asset", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Asset
|
||||
() => frappe.tests.make('Asset', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Asset Category", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Asset Category
|
||||
() => frappe.tests.make('Asset Category', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Asset Maintenance", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Asset Maintenance
|
||||
() => frappe.tests.make('Asset Maintenance', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Asset Maintenance Log", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Asset Maintenance Log
|
||||
() => frappe.tests.make('Asset Maintenance Log', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Asset Maintenance Team", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Asset Maintenance Team
|
||||
() => frappe.tests.make('Asset Maintenance Team', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Asset Movement", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Asset Movement
|
||||
() => frappe.tests.make('Asset Movement', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Asset Repair", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Asset Repair
|
||||
() => frappe.tests.make('Asset Repair', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Asset Value Adjustment", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Asset Value Adjustment
|
||||
() => frappe.tests.make('Asset Value Adjustment', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Location", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Location
|
||||
() => frappe.tests.make('Location', [
|
||||
// values to be set
|
||||
{ location_name: 'Basil Farm' }
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.name, 'Basil Farm');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Maintenance Team Member", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Maintenance Team Member
|
||||
() => frappe.tests.make('Maintenance Team Member', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -24,7 +24,26 @@ frappe.ui.form.on("Supplier", {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query("supplier_primary_contact", function(doc) {
|
||||
return {
|
||||
query: "erpnext.buying.doctype.supplier.supplier.get_supplier_primary_contact",
|
||||
filters: {
|
||||
"supplier": doc.name
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("supplier_primary_address", function(doc) {
|
||||
return {
|
||||
filters: {
|
||||
"link_doctype": "Supplier",
|
||||
"link_name": doc.name
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function (frm) {
|
||||
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Supplier' }
|
||||
|
||||
@@ -78,6 +97,30 @@ frappe.ui.form.on("Supplier", {
|
||||
});
|
||||
},
|
||||
|
||||
supplier_primary_address: function(frm) {
|
||||
if (frm.doc.supplier_primary_address) {
|
||||
frappe.call({
|
||||
method: 'frappe.contacts.doctype.address.address.get_address_display',
|
||||
args: {
|
||||
"address_dict": frm.doc.supplier_primary_address
|
||||
},
|
||||
callback: function(r) {
|
||||
frm.set_value("primary_address", r.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!frm.doc.supplier_primary_address) {
|
||||
frm.set_value("primary_address", "");
|
||||
}
|
||||
},
|
||||
|
||||
supplier_primary_contact: function(frm) {
|
||||
if (!frm.doc.supplier_primary_contact) {
|
||||
frm.set_value("mobile_no", "");
|
||||
frm.set_value("email_id", "");
|
||||
}
|
||||
},
|
||||
|
||||
is_internal_supplier: function(frm) {
|
||||
if (frm.doc.is_internal_supplier == 1) {
|
||||
frm.toggle_reqd("represents_company", true);
|
||||
|
||||
@@ -49,6 +49,13 @@
|
||||
"address_html",
|
||||
"column_break1",
|
||||
"contact_html",
|
||||
"primary_address_and_contact_detail_section",
|
||||
"supplier_primary_contact",
|
||||
"mobile_no",
|
||||
"email_id",
|
||||
"column_break_44",
|
||||
"supplier_primary_address",
|
||||
"primary_address",
|
||||
"default_payable_accounts",
|
||||
"accounts",
|
||||
"default_tax_withholding_config",
|
||||
@@ -378,6 +385,47 @@
|
||||
"fieldname": "allow_purchase_invoice_creation_without_purchase_receipt",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow Purchase Invoice Creation Without Purchase Receipt"
|
||||
},
|
||||
{
|
||||
"fieldname": "primary_address_and_contact_detail_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Primary Address and Contact Detail"
|
||||
},
|
||||
{
|
||||
"description": "Reselect, if the chosen contact is edited after save",
|
||||
"fieldname": "supplier_primary_contact",
|
||||
"fieldtype": "Link",
|
||||
"label": "Supplier Primary Contact",
|
||||
"options": "Contact"
|
||||
},
|
||||
{
|
||||
"fetch_from": "supplier_primary_contact.mobile_no",
|
||||
"fieldname": "mobile_no",
|
||||
"fieldtype": "Read Only",
|
||||
"label": "Mobile No"
|
||||
},
|
||||
{
|
||||
"fetch_from": "supplier_primary_contact.email_id",
|
||||
"fieldname": "email_id",
|
||||
"fieldtype": "Read Only",
|
||||
"label": "Email Id"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_44",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "primary_address",
|
||||
"fieldtype": "Text",
|
||||
"label": "Primary Address",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"description": "Reselect, if the chosen address is edited after save",
|
||||
"fieldname": "supplier_primary_address",
|
||||
"fieldtype": "Link",
|
||||
"label": "Supplier Primary Address",
|
||||
"options": "Address"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-user",
|
||||
@@ -390,7 +438,7 @@
|
||||
"link_fieldname": "supplier"
|
||||
}
|
||||
],
|
||||
"modified": "2021-05-18 15:10:11.087191",
|
||||
"modified": "2021-08-27 18:02:44.314077",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier",
|
||||
|
||||
@@ -42,7 +42,12 @@ class Supplier(TransactionBase):
|
||||
if not self.naming_series:
|
||||
self.naming_series = ''
|
||||
|
||||
self.create_primary_contact()
|
||||
self.create_primary_address()
|
||||
|
||||
def validate(self):
|
||||
self.flags.is_new_doc = self.is_new()
|
||||
|
||||
# validation for Naming Series mandatory field...
|
||||
if frappe.defaults.get_global_default('supp_master_name') == 'Naming Series':
|
||||
if not self.naming_series:
|
||||
@@ -76,7 +81,39 @@ class Supplier(TransactionBase):
|
||||
frappe.throw(_("Internal Supplier for company {0} already exists").format(
|
||||
frappe.bold(self.represents_company)))
|
||||
|
||||
def create_primary_contact(self):
|
||||
from erpnext.selling.doctype.customer.customer import make_contact
|
||||
|
||||
if not self.supplier_primary_contact:
|
||||
if self.mobile_no or self.email_id:
|
||||
contact = make_contact(self)
|
||||
self.db_set('supplier_primary_contact', contact.name)
|
||||
self.db_set('mobile_no', self.mobile_no)
|
||||
self.db_set('email_id', self.email_id)
|
||||
|
||||
def create_primary_address(self):
|
||||
from erpnext.selling.doctype.customer.customer import make_address
|
||||
from frappe.contacts.doctype.address.address import get_address_display
|
||||
|
||||
if self.flags.is_new_doc and self.get('address_line1'):
|
||||
address = make_address(self)
|
||||
address_display = get_address_display(address.name)
|
||||
|
||||
self.db_set("supplier_primary_address", address.name)
|
||||
self.db_set("primary_address", address_display)
|
||||
|
||||
def on_trash(self):
|
||||
if self.supplier_primary_contact:
|
||||
frappe.db.sql("""
|
||||
UPDATE `tabSupplier`
|
||||
SET
|
||||
supplier_primary_contact=null,
|
||||
supplier_primary_address=null,
|
||||
mobile_no=null,
|
||||
email_id=null,
|
||||
primary_address=null
|
||||
WHERE name=%(name)s""", {"name": self.name})
|
||||
|
||||
delete_contact_and_address('Supplier', self.name)
|
||||
|
||||
def after_rename(self, olddn, newdn, merge=False):
|
||||
@@ -104,3 +141,21 @@ class Supplier(TransactionBase):
|
||||
doc.name, args.get('supplier_email_' + str(i)))
|
||||
except frappe.NameError:
|
||||
pass
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_supplier_primary_contact(doctype, txt, searchfield, start, page_len, filters):
|
||||
supplier = filters.get("supplier")
|
||||
return frappe.db.sql("""
|
||||
SELECT
|
||||
`tabContact`.name from `tabContact`,
|
||||
`tabDynamic Link`
|
||||
WHERE
|
||||
`tabContact`.name = `tabDynamic Link`.parent
|
||||
and `tabDynamic Link`.link_name = %(supplier)s
|
||||
and `tabDynamic Link`.link_doctype = 'Supplier'
|
||||
and `tabContact`.name like %(txt)s
|
||||
""", {
|
||||
'supplier': supplier,
|
||||
'txt': '%%%s%%' % txt
|
||||
})
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Contract", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Contract
|
||||
() => frappe.tests.make('Contract', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Contract Fulfilment Checklist", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Contract Fulfilment Checklist
|
||||
() => frappe.tests.make('Contract Fulfilment Checklist', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Contract Template", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Contract Template
|
||||
() => frappe.tests.make('Contract Template', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Market Segment", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Market Segment
|
||||
() => frappe.tests.make('Market Segment', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Opportunity Type", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Opportunity Type
|
||||
() => frappe.tests.make('Opportunity Type', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Sales Stage", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Sales Stage
|
||||
() => frappe.tests.make('Sales Stage', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
// Testing Setup Module in Education
|
||||
QUnit.module('education');
|
||||
|
||||
QUnit.test('Test: Academic Year', function(assert){
|
||||
assert.expect(3);
|
||||
let done = assert.async();
|
||||
frappe.run_serially([
|
||||
() => {
|
||||
return frappe.tests.make('Academic Year', [
|
||||
{academic_year_name: '2016-17'},
|
||||
{year_start_date: '2016-07-20'},
|
||||
{year_end_date:'2017-06-20'},
|
||||
]);
|
||||
},
|
||||
|
||||
() => {
|
||||
assert.ok(cur_frm.doc.academic_year_name=='2016-17');
|
||||
assert.ok(cur_frm.doc.year_start_date=='2016-07-20');
|
||||
assert.ok(cur_frm.doc.year_end_date=='2017-06-20');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Article", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Article
|
||||
() => frappe.tests.make('Article', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Content Question", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Content Question
|
||||
() => frappe.tests.make('Content Question', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Course Activity", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Course Activity
|
||||
() => frappe.tests.make('Course Activity', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Course Content", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Course Content
|
||||
() => frappe.tests.make('Course Content', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Course Enrollment", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Course Enrollment
|
||||
() => frappe.tests.make('Course Enrollment', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Course Schedule", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Course Schedule
|
||||
() => frappe.tests.make('Course Schedule', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Course Scheduling Tool", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Course Scheduling Tool
|
||||
() => frappe.tests.make('Course Scheduling Tool', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Course Topic", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Course Topic
|
||||
() => frappe.tests.make('Course Topic', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Fee Category", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Fee Category
|
||||
() => frappe.tests.make('Fee Category', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Fee Schedule", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially('Fee Schedule', [
|
||||
// insert a new Fee Schedule
|
||||
() => frappe.tests.make([
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Fee Structure", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Fee Structure
|
||||
() => frappe.tests.make('Fee Structure', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Program Enrollment", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Program Enrollment
|
||||
() => frappe.tests.make('Program Enrollment', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Program Enrollment Tool", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Program Enrollment Tool
|
||||
() => frappe.tests.make('Program Enrollment Tool', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Question", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Question
|
||||
() => frappe.tests.make('Question', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Quiz", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Quiz
|
||||
() => frappe.tests.make('Quiz', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Quiz Activity", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Quiz Activity
|
||||
() => frappe.tests.make('Quiz Activity', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Quiz Result", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Quiz Result
|
||||
() => frappe.tests.make('Quiz Result', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: School House", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new School House
|
||||
() => frappe.tests.make('School House', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user