Merge branch 'develop' into prospect
This commit is contained in:
commit
212921aace
2
.github/workflows/ui-tests.yml
vendored
2
.github/workflows/ui-tests.yml
vendored
@ -95,7 +95,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 = [
|
||||
|
@ -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()
|
||||
]);
|
||||
|
||||
});
|
@ -6,46 +6,3 @@ frappe.ui.form.on('Accounts Settings', {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
frappe.tour['Accounts Settings'] = [
|
||||
{
|
||||
fieldname: "acc_frozen_upto",
|
||||
title: "Accounts Frozen Upto",
|
||||
description: __("Freeze accounting transactions up to specified date, nobody can make/modify entry except the specified Role."),
|
||||
},
|
||||
{
|
||||
fieldname: "frozen_accounts_modifier",
|
||||
title: "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
|
||||
description: __("Users with this Role are allowed to set frozen accounts and create/modify accounting entries against frozen accounts.")
|
||||
},
|
||||
{
|
||||
fieldname: "determine_address_tax_category_from",
|
||||
title: "Determine Address Tax Category From",
|
||||
description: __("Tax category can be set on Addresses. An address can be Shipping or Billing address. Set which addres to select when applying Tax Category.")
|
||||
},
|
||||
{
|
||||
fieldname: "over_billing_allowance",
|
||||
title: "Over Billing Allowance Percentage",
|
||||
description: __("The percentage by which you can overbill transactions. For example, if the order value is $100 for an Item and percentage here is set as 10% then you are allowed to bill for $110.")
|
||||
},
|
||||
{
|
||||
fieldname: "credit_controller",
|
||||
title: "Credit Controller",
|
||||
description: __("Select the role that is allowed to submit transactions that exceed credit limits set. The credit limit can be set in the Customer form.")
|
||||
},
|
||||
{
|
||||
fieldname: "make_payment_via_journal_entry",
|
||||
title: "Make Payment via Journal Entry",
|
||||
description: __("When checked, if user proceeds to make payment from an invoice, the system will open a Journal Entry instead of a Payment Entry.")
|
||||
},
|
||||
{
|
||||
fieldname: "unlink_payment_on_cancellation_of_invoice",
|
||||
title: "Unlink Payment on Cancellation of Invoice",
|
||||
description: __("If checked, system will unlink the payment against the respective invoice.")
|
||||
},
|
||||
{
|
||||
fieldname: "unlink_advance_payment_on_cancelation_of_order",
|
||||
title: "Unlink Advance Payment on Cancellation of Order",
|
||||
description: __("Similar to the previous option, this unlinks any advance payments made against Purchase/Sales Orders.")
|
||||
}
|
||||
];
|
||||
|
@ -19,6 +19,7 @@
|
||||
"delete_linked_ledger_entries",
|
||||
"book_asset_depreciation_entry_automatically",
|
||||
"unlink_advance_payment_on_cancelation_of_order",
|
||||
"enable_common_party_accounting",
|
||||
"post_change_gl_entries",
|
||||
"enable_discount_accounting",
|
||||
"tax_settings_section",
|
||||
@ -268,6 +269,12 @@
|
||||
"fieldname": "enable_discount_accounting",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enable Discount Accounting"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "enable_common_party_accounting",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enable Common Party Accounting"
|
||||
}
|
||||
],
|
||||
"icon": "icon-cog",
|
||||
@ -275,7 +282,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2021-08-09 13:08:04.335416",
|
||||
"modified": "2021-08-19 11:17:38.788054",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
|
@ -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()
|
||||
]);
|
||||
|
||||
});
|
@ -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()
|
||||
]);
|
||||
|
||||
});
|
@ -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()
|
||||
]);
|
||||
|
||||
});
|
33
erpnext/accounts/doctype/party_link/party_link.js
Normal file
33
erpnext/accounts/doctype/party_link/party_link.js
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Party Link', {
|
||||
refresh: function(frm) {
|
||||
frm.set_query('primary_role', () => {
|
||||
return {
|
||||
filters: {
|
||||
name: ['in', ['Customer', 'Supplier']]
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query('secondary_role', () => {
|
||||
let party_types = Object.keys(frappe.boot.party_account_types)
|
||||
.filter(p => p != frm.doc.primary_role);
|
||||
return {
|
||||
filters: {
|
||||
name: ['in', party_types]
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
primary_role(frm) {
|
||||
frm.set_value('primary_party', '');
|
||||
frm.set_value('secondary_role', '');
|
||||
},
|
||||
|
||||
secondary_role(frm) {
|
||||
frm.set_value('secondary_party', '');
|
||||
}
|
||||
});
|
102
erpnext/accounts/doctype/party_link/party_link.json
Normal file
102
erpnext/accounts/doctype/party_link/party_link.json
Normal file
@ -0,0 +1,102 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "ACC-PT-LNK-.###.",
|
||||
"creation": "2021-08-18 21:06:53.027695",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"primary_role",
|
||||
"secondary_role",
|
||||
"column_break_2",
|
||||
"primary_party",
|
||||
"secondary_party"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "primary_role",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Primary Role",
|
||||
"options": "DocType",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"depends_on": "primary_role",
|
||||
"fieldname": "secondary_role",
|
||||
"fieldtype": "Link",
|
||||
"label": "Secondary Role",
|
||||
"mandatory_depends_on": "primary_role",
|
||||
"options": "DocType"
|
||||
},
|
||||
{
|
||||
"depends_on": "primary_role",
|
||||
"fieldname": "primary_party",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"label": "Primary Party",
|
||||
"mandatory_depends_on": "primary_role",
|
||||
"options": "primary_role"
|
||||
},
|
||||
{
|
||||
"depends_on": "secondary_role",
|
||||
"fieldname": "secondary_party",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"label": "Secondary Party",
|
||||
"mandatory_depends_on": "secondary_role",
|
||||
"options": "secondary_role"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2021-08-25 20:08:56.761150",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Party Link",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "primary_party",
|
||||
"track_changes": 1
|
||||
}
|
26
erpnext/accounts/doctype/party_link/party_link.py
Normal file
26
erpnext/accounts/doctype/party_link/party_link.py
Normal file
@ -0,0 +1,26 @@
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
|
||||
class PartyLink(Document):
|
||||
def validate(self):
|
||||
if self.primary_role not in ['Customer', 'Supplier']:
|
||||
frappe.throw(_("Allowed primary roles are 'Customer' and 'Supplier'. Please select one of these roles only."),
|
||||
title=_("Invalid Primary Role"))
|
||||
|
||||
existing_party_link = frappe.get_all('Party Link', {
|
||||
'primary_party': self.secondary_party
|
||||
}, pluck="primary_role")
|
||||
if existing_party_link:
|
||||
frappe.throw(_('{} {} is already linked with another {}')
|
||||
.format(self.secondary_role, self.secondary_party, existing_party_link[0]))
|
||||
|
||||
existing_party_link = frappe.get_all('Party Link', {
|
||||
'secondary_party': self.primary_party
|
||||
}, pluck="primary_role")
|
||||
if existing_party_link:
|
||||
frappe.throw(_('{} {} is already linked with another {}')
|
||||
.format(self.primary_role, self.primary_party, existing_party_link[0]))
|
8
erpnext/accounts/doctype/party_link/test_party_link.py
Normal file
8
erpnext/accounts/doctype/party_link/test_party_link.py
Normal file
@ -0,0 +1,8 @@
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestPartyLink(unittest.TestCase):
|
||||
pass
|
@ -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,
|
||||
|
@ -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:
|
||||
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':
|
||||
|
@ -415,6 +415,8 @@ class PurchaseInvoice(BuyingController):
|
||||
self.update_project()
|
||||
update_linked_doc(self.doctype, self.name, self.inter_company_invoice_reference)
|
||||
|
||||
self.process_common_party_accounting()
|
||||
|
||||
def make_gl_entries(self, gl_entries=None, from_repost=False):
|
||||
if not gl_entries:
|
||||
gl_entries = self.get_gl_entries()
|
||||
|
@ -253,6 +253,8 @@ class SalesInvoice(SellingController):
|
||||
if "Healthcare" in active_domains:
|
||||
manage_invoice_submit_cancel(self, "on_submit")
|
||||
|
||||
self.process_common_party_accounting()
|
||||
|
||||
def validate_pos_return(self):
|
||||
|
||||
if self.is_pos and self.is_return:
|
||||
|
@ -1140,6 +1140,18 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
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,
|
||||
company='_Test Company with perpetual inventory', warehouse='Stores - TCP1', debit_to='Debtors - TCP1',
|
||||
income_account='Sales - TCP1', expense_account='Cost of Goods Sold - TCP1', cost_center='Main - TCP1')
|
||||
|
||||
incoming_rate = frappe.db.get_value('Stock Ledger Entry', {'voucher_no': return_si.name}, 'incoming_rate')
|
||||
debit_amount = frappe.db.get_value('GL Entry',
|
||||
{'voucher_no': return_si.name, 'account': 'Stock In Hand - TCP1'}, 'debit')
|
||||
|
||||
self.assertEqual(debit_amount, 10.0)
|
||||
self.assertEqual(incoming_rate, 10.0)
|
||||
|
||||
def test_discount_on_net_total(self):
|
||||
si = frappe.copy_doc(test_records[2])
|
||||
si.apply_discount_on = "Net Total"
|
||||
@ -1816,23 +1828,13 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
acc_settings.save()
|
||||
|
||||
def test_inter_company_transaction(self):
|
||||
from erpnext.selling.doctype.customer.test_customer import create_internal_customer
|
||||
|
||||
if not frappe.db.exists("Customer", "_Test Internal Customer"):
|
||||
customer = frappe.get_doc({
|
||||
"customer_group": "_Test Customer Group",
|
||||
"customer_name": "_Test Internal Customer",
|
||||
"customer_type": "Individual",
|
||||
"doctype": "Customer",
|
||||
"territory": "_Test Territory",
|
||||
"is_internal_customer": 1,
|
||||
"represents_company": "_Test Company 1"
|
||||
})
|
||||
|
||||
customer.append("companies", {
|
||||
"company": "Wind Power LLC"
|
||||
})
|
||||
|
||||
customer.insert()
|
||||
create_internal_customer(
|
||||
customer_name="_Test Internal Customer",
|
||||
represents_company="_Test Company 1",
|
||||
allowed_to_interact_with="Wind Power LLC"
|
||||
)
|
||||
|
||||
if not frappe.db.exists("Supplier", "_Test Internal Supplier"):
|
||||
supplier = frappe.get_doc({
|
||||
@ -1958,8 +1960,43 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
frappe.local.enable_perpetual_inventory['_Test Company 1'] = old_perpetual_inventory
|
||||
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", old_negative_stock)
|
||||
|
||||
def test_sle_if_target_warehouse_exists_accidentally(self):
|
||||
"""
|
||||
Check if inward entry exists if Target Warehouse accidentally exists
|
||||
but Customer is not an internal customer.
|
||||
"""
|
||||
se = make_stock_entry(
|
||||
item_code="138-CMS Shoe",
|
||||
target="Finished Goods - _TC",
|
||||
company = "_Test Company",
|
||||
qty=1,
|
||||
basic_rate=500
|
||||
)
|
||||
|
||||
si = frappe.copy_doc(test_records[0])
|
||||
si.update_stock = 1
|
||||
si.set_warehouse = "Finished Goods - _TC"
|
||||
si.set_target_warehouse = "Stores - _TC"
|
||||
si.get("items")[0].warehouse = "Finished Goods - _TC"
|
||||
si.get("items")[0].target_warehouse = "Stores - _TC"
|
||||
si.insert()
|
||||
si.submit()
|
||||
|
||||
sles = frappe.get_all("Stock Ledger Entry", filters={"voucher_no": si.name},
|
||||
fields=["name", "actual_qty"])
|
||||
|
||||
# check if only one SLE for outward entry is created
|
||||
self.assertEqual(len(sles), 1)
|
||||
self.assertEqual(sles[0].actual_qty, -1)
|
||||
|
||||
# tear down
|
||||
si.cancel()
|
||||
se.cancel()
|
||||
|
||||
def test_internal_transfer_gl_entry(self):
|
||||
## Create internal transfer account
|
||||
from erpnext.selling.doctype.customer.test_customer import create_internal_customer
|
||||
|
||||
account = create_account(account_name="Unrealized Profit",
|
||||
parent_account="Current Liabilities - TCP1", company="_Test Company with perpetual inventory")
|
||||
|
||||
@ -2163,6 +2200,50 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
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
|
||||
|
||||
# create a customer
|
||||
customer = make_customer(customer="_Test Common Supplier")
|
||||
# create a supplier
|
||||
supplier = create_supplier(supplier_name="_Test Common Supplier").name
|
||||
|
||||
# create a party link between customer & supplier
|
||||
# set primary role as supplier
|
||||
party_link = frappe.new_doc("Party Link")
|
||||
party_link.primary_role = "Supplier"
|
||||
party_link.primary_party = supplier
|
||||
party_link.secondary_role = "Customer"
|
||||
party_link.secondary_party = customer
|
||||
party_link.save()
|
||||
|
||||
# enable common party accounting
|
||||
frappe.db.set_value('Accounts Settings', None, 'enable_common_party_accounting', 1)
|
||||
|
||||
# create a sales invoice
|
||||
si = create_sales_invoice(customer=customer, parent_cost_center="_Test Cost Center - _TC")
|
||||
|
||||
# check outstanding of sales invoice
|
||||
si.reload()
|
||||
self.assertEqual(si.status, 'Paid')
|
||||
self.assertEqual(flt(si.outstanding_amount), 0.0)
|
||||
|
||||
# check creation of journal entry
|
||||
jv = frappe.get_all('Journal Entry Account', {
|
||||
'account': si.debit_to,
|
||||
'party_type': 'Customer',
|
||||
'party': si.customer,
|
||||
'reference_type': si.doctype,
|
||||
'reference_name': si.name
|
||||
}, pluck='credit_in_account_currency')
|
||||
|
||||
self.assertTrue(jv)
|
||||
self.assertEqual(jv[0], si.grand_total)
|
||||
|
||||
party_link.delete()
|
||||
frappe.db.set_value('Accounts Settings', None, 'enable_common_party_accounting', 0)
|
||||
|
||||
def get_sales_invoice_for_e_invoice():
|
||||
si = make_sales_invoice_for_ewaybill()
|
||||
si.naming_series = 'INV-2020-.#####'
|
||||
@ -2375,7 +2456,8 @@ def create_sales_invoice(**args):
|
||||
"asset": args.asset or None,
|
||||
"cost_center": args.cost_center or "_Test Cost Center - _TC",
|
||||
"serial_no": args.serial_no,
|
||||
"conversion_factor": 1
|
||||
"conversion_factor": 1,
|
||||
"incoming_rate": args.incoming_rate or 0
|
||||
})
|
||||
|
||||
if not args.do_not_save:
|
||||
@ -2472,29 +2554,6 @@ def get_taxes_and_charges():
|
||||
"row_id": 1
|
||||
}]
|
||||
|
||||
def create_internal_customer(customer_name, represents_company, allowed_to_interact_with):
|
||||
if not frappe.db.exists("Customer", customer_name):
|
||||
customer = frappe.get_doc({
|
||||
"customer_group": "_Test Customer Group",
|
||||
"customer_name": customer_name,
|
||||
"customer_type": "Individual",
|
||||
"doctype": "Customer",
|
||||
"territory": "_Test Territory",
|
||||
"is_internal_customer": 1,
|
||||
"represents_company": represents_company
|
||||
})
|
||||
|
||||
customer.append("companies", {
|
||||
"company": allowed_to_interact_with
|
||||
})
|
||||
|
||||
customer.insert()
|
||||
customer_name = customer.name
|
||||
else:
|
||||
customer_name = frappe.db.get_value("Customer", customer_name)
|
||||
|
||||
return customer_name
|
||||
|
||||
def create_internal_supplier(supplier_name, represents_company, allowed_to_interact_with):
|
||||
if not frappe.db.exists("Supplier", supplier_name):
|
||||
supplier = frappe.get_doc({
|
||||
|
@ -53,7 +53,6 @@
|
||||
"column_break_24",
|
||||
"base_net_rate",
|
||||
"base_net_amount",
|
||||
"incoming_rate",
|
||||
"drop_ship",
|
||||
"delivered_by_supplier",
|
||||
"accounting",
|
||||
@ -81,6 +80,7 @@
|
||||
"target_warehouse",
|
||||
"quality_inspection",
|
||||
"batch_no",
|
||||
"incoming_rate",
|
||||
"col_break5",
|
||||
"allow_zero_valuation_rate",
|
||||
"serial_no",
|
||||
@ -807,12 +807,12 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:parent.is_return && parent.update_stock && !parent.return_against",
|
||||
"fieldname": "incoming_rate",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Incoming Rate",
|
||||
"label": "Incoming Rate (Costing)",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.uom != doc.stock_uom",
|
||||
@ -833,7 +833,7 @@
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-08-12 20:15:47.668399",
|
||||
"modified": "2021-08-19 13:41:53.435827",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Item",
|
||||
|
@ -5,25 +5,3 @@ cur_frm.cscript.tax_table = "Sales Taxes and Charges";
|
||||
|
||||
{% include "erpnext/public/js/controllers/accounts.js" %}
|
||||
|
||||
frappe.tour['Sales Taxes and Charges Template'] = [
|
||||
{
|
||||
fieldname: "title",
|
||||
title: __("Title"),
|
||||
description: __("A name by which you will identify this template. You can change this later."),
|
||||
},
|
||||
{
|
||||
fieldname: "company",
|
||||
title: __("Company"),
|
||||
description: __("Company for which this tax template will be applicable"),
|
||||
},
|
||||
{
|
||||
fieldname: "is_default",
|
||||
title: __("Is this Default?"),
|
||||
description: __("Set this template as the default for all sales transactions"),
|
||||
},
|
||||
{
|
||||
fieldname: "taxes",
|
||||
title: __("Taxes Table"),
|
||||
description: __("You can add a row for a tax rule here. These rules can be applied on the net total, or can be a flat amount."),
|
||||
}
|
||||
];
|
||||
|
@ -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()
|
||||
]);
|
||||
|
||||
});
|
@ -0,0 +1,113 @@
|
||||
{
|
||||
"creation": "2021-06-29 17:00:18.273054",
|
||||
"docstatus": 0,
|
||||
"doctype": "Form Tour",
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"modified": "2021-06-29 17:00:26.145996",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
"owner": "Administrator",
|
||||
"reference_doctype": "Accounts Settings",
|
||||
"save_on_complete": 0,
|
||||
"steps": [
|
||||
{
|
||||
"description": "The percentage by which you can overbill transactions. For example, if the order value is $100 for an Item and percentage here is set as 10% then you are allowed to bill for $110.",
|
||||
"field": "",
|
||||
"fieldname": "over_billing_allowance",
|
||||
"fieldtype": "Currency",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Over Billing Allowance (%)",
|
||||
"parent_field": "",
|
||||
"position": "Right",
|
||||
"title": "Over Billing Allowance Percentage"
|
||||
},
|
||||
{
|
||||
"description": "Select the role that is allowed to overbill a transactions.",
|
||||
"field": "",
|
||||
"fieldname": "role_allowed_to_over_bill",
|
||||
"fieldtype": "Link",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Role Allowed to Over Bill ",
|
||||
"parent_field": "",
|
||||
"position": "Right",
|
||||
"title": "Role Allowed to Over Bill"
|
||||
},
|
||||
{
|
||||
"description": "If checked, system will unlink the payment against the respective invoice.",
|
||||
"field": "",
|
||||
"fieldname": "unlink_payment_on_cancellation_of_invoice",
|
||||
"fieldtype": "Check",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Unlink Payment on Cancellation of Invoice",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Unlink Payment on Cancellation of Invoice"
|
||||
},
|
||||
{
|
||||
"description": "Similar to the previous option, this unlinks any advance payments made against Purchase/Sales Orders.",
|
||||
"field": "",
|
||||
"fieldname": "unlink_advance_payment_on_cancelation_of_order",
|
||||
"fieldtype": "Check",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Unlink Advance Payment on Cancellation of Order",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Unlink Advance Payment on Cancellation of Order"
|
||||
},
|
||||
{
|
||||
"description": "Tax category can be set on Addresses. An address can be Shipping or Billing address. Set which addres to select when applying Tax Category.",
|
||||
"field": "",
|
||||
"fieldname": "determine_address_tax_category_from",
|
||||
"fieldtype": "Select",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Determine Address Tax Category From",
|
||||
"parent_field": "",
|
||||
"position": "Right",
|
||||
"title": "Determine Address Tax Category From"
|
||||
},
|
||||
{
|
||||
"description": "Freeze accounting transactions up to specified date, nobody can make/modify entry except the specified Role.",
|
||||
"field": "",
|
||||
"fieldname": "acc_frozen_upto",
|
||||
"fieldtype": "Date",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Accounts Frozen Till Date",
|
||||
"parent_field": "",
|
||||
"position": "Right",
|
||||
"title": "Accounts Frozen Upto"
|
||||
},
|
||||
{
|
||||
"description": "Users with this Role are allowed to set frozen accounts and create/modify accounting entries against frozen accounts.",
|
||||
"field": "",
|
||||
"fieldname": "frozen_accounts_modifier",
|
||||
"fieldtype": "Link",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Role Allowed to Set Frozen Accounts and Edit Frozen Entries",
|
||||
"parent_field": "",
|
||||
"position": "Right",
|
||||
"title": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries"
|
||||
},
|
||||
{
|
||||
"description": "Select the role that is allowed to submit transactions that exceed credit limits set. The credit limit can be set in the Customer form.",
|
||||
"field": "",
|
||||
"fieldname": "credit_controller",
|
||||
"fieldtype": "Link",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Credit Controller",
|
||||
"parent_field": "",
|
||||
"position": "Left",
|
||||
"title": "Credit Controller"
|
||||
}
|
||||
],
|
||||
"title": "Accounts Settings"
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
{
|
||||
"creation": "2021-06-29 16:31:48.558826",
|
||||
"docstatus": 0,
|
||||
"doctype": "Form Tour",
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"modified": "2021-06-29 16:31:48.558826",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
"owner": "Administrator",
|
||||
"reference_doctype": "Purchase Invoice",
|
||||
"save_on_complete": 1,
|
||||
"steps": [
|
||||
{
|
||||
"description": "Select Supplier",
|
||||
"field": "",
|
||||
"fieldname": "supplier",
|
||||
"fieldtype": "Link",
|
||||
"has_next_condition": 1,
|
||||
"is_table_field": 0,
|
||||
"label": "Supplier",
|
||||
"next_step_condition": "supplier",
|
||||
"parent_field": "",
|
||||
"position": "Right",
|
||||
"title": "Select Supplier"
|
||||
},
|
||||
{
|
||||
"description": "Add items in the table",
|
||||
"field": "",
|
||||
"fieldname": "items",
|
||||
"fieldtype": "Table",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Items",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "List of Items"
|
||||
},
|
||||
{
|
||||
"child_doctype": "Purchase Invoice Item",
|
||||
"description": "Select an item",
|
||||
"field": "",
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 1,
|
||||
"label": "Item",
|
||||
"parent_field": "",
|
||||
"parent_fieldname": "items",
|
||||
"position": "Right",
|
||||
"title": "Select Item"
|
||||
},
|
||||
{
|
||||
"child_doctype": "Purchase Invoice Item",
|
||||
"description": "Enter the quantity",
|
||||
"field": "",
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 1,
|
||||
"label": "Accepted Qty",
|
||||
"parent_field": "",
|
||||
"parent_fieldname": "items",
|
||||
"position": "Right",
|
||||
"title": "Enter Quantity"
|
||||
},
|
||||
{
|
||||
"child_doctype": "Purchase Invoice Item",
|
||||
"description": "Enter rate of the item",
|
||||
"field": "",
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Currency",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 1,
|
||||
"label": "Rate",
|
||||
"parent_field": "",
|
||||
"parent_fieldname": "items",
|
||||
"position": "Right",
|
||||
"title": "Enter Rate"
|
||||
},
|
||||
{
|
||||
"description": "You can add taxes here",
|
||||
"field": "",
|
||||
"fieldname": "taxes",
|
||||
"fieldtype": "Table",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Purchase Taxes and Charges",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Select taxes"
|
||||
}
|
||||
],
|
||||
"title": "Purchase Invoice"
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
{
|
||||
"creation": "2021-08-24 12:28:18.044902",
|
||||
"docstatus": 0,
|
||||
"doctype": "Form Tour",
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"modified": "2021-08-24 12:28:18.044902",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Taxes and Charges Template",
|
||||
"owner": "Administrator",
|
||||
"reference_doctype": "Sales Taxes and Charges Template",
|
||||
"save_on_complete": 0,
|
||||
"steps": [
|
||||
{
|
||||
"description": "A name by which you will identify this template. You can change this later.",
|
||||
"field": "",
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Title",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Title"
|
||||
},
|
||||
{
|
||||
"description": "Company for which this tax template will be applicable",
|
||||
"field": "",
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Company",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Company"
|
||||
},
|
||||
{
|
||||
"description": "Set this template as the default for all sales transactions",
|
||||
"field": "",
|
||||
"fieldname": "is_default",
|
||||
"fieldtype": "Check",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Default",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Is this Default Tax Template?"
|
||||
},
|
||||
{
|
||||
"description": "You can add a row for a tax rule here. These rules can be applied on the net total, or can be a flat amount.",
|
||||
"field": "",
|
||||
"fieldname": "taxes",
|
||||
"fieldtype": "Table",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Sales Taxes and Charges",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Taxes Table"
|
||||
}
|
||||
],
|
||||
"title": "Sales Taxes and Charges Template"
|
||||
}
|
@ -13,12 +13,15 @@
|
||||
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/accounts",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"modified": "2020-10-30 15:41:15.547225",
|
||||
"modified": "2021-08-13 11:59:35.690443",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts",
|
||||
"owner": "Administrator",
|
||||
"steps": [
|
||||
{
|
||||
"step": "Company"
|
||||
},
|
||||
{
|
||||
"step": "Chart of Accounts"
|
||||
},
|
||||
@ -26,22 +29,19 @@
|
||||
"step": "Setup Taxes"
|
||||
},
|
||||
{
|
||||
"step": "Create a Product"
|
||||
"step": "Accounts Settings"
|
||||
},
|
||||
{
|
||||
"step": "Create a Supplier"
|
||||
"step": "Cost Centers for Report and Budgeting"
|
||||
},
|
||||
{
|
||||
"step": "Create Your First Purchase Invoice"
|
||||
},
|
||||
{
|
||||
"step": "Create a Customer"
|
||||
"step": "Updating Opening Balances"
|
||||
},
|
||||
{
|
||||
"step": "Create Your First Sales Invoice"
|
||||
},
|
||||
{
|
||||
"step": "Configure Account Settings"
|
||||
"step": "Financial Statements"
|
||||
}
|
||||
],
|
||||
"subtitle": "Accounts, Invoices, Taxation, and more.",
|
||||
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Show Form Tour",
|
||||
"action_label": "Take a quick walk-through of Accounts Settings",
|
||||
"creation": "2021-06-29 16:42:03.400731",
|
||||
"description": "# Account Settings\n\nIn ERPNext, Accounting features are configurable as per your business needs. Accounts Settings is the place to define some of your accounting preferences like:\n\n - Credit Limit and over billing settings\n - Taxation preferences\n - Deferred accounting preferences\n",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 1,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-08-13 11:50:06.227835",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Accounts Settings",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Accounts Settings",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Accounts Settings",
|
||||
"validate_action": 1
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"action": "Go to Page",
|
||||
"action_label": "View Chart of Accounts",
|
||||
"action": "Watch Video",
|
||||
"action_label": "Learn more about Chart of Accounts",
|
||||
"callback_message": "You can continue with the onboarding after exploring this page",
|
||||
"callback_title": "Awesome Work",
|
||||
"creation": "2020-05-13 19:58:20.928127",
|
||||
"description": "# Chart Of Accounts\n\nThe Chart of Accounts is the blueprint of the accounts in your organization.\nIt is a tree view of the names of the Accounts (Ledgers and Groups) that a Company requires to manage its books of accounts. ERPNext sets up a simple chart of accounts for each Company you create, but you can modify it according to your needs and legal requirements.\n\nFor each company, Chart of Accounts signifies the way to classify the accounting entries, mostly\nbased on statutory (tax, compliance to government regulations) requirements.\n\nThere's a brief video tutorial about chart of accounts in the next step.",
|
||||
"description": "# Chart Of Accounts\n\nERPNext sets up a simple chart of accounts for each Company you create, but you can modify it according to business and legal requirements.",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
@ -12,7 +12,7 @@
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-10-30 14:35:59.474920",
|
||||
"modified": "2021-08-13 11:46:25.878506",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Chart of Accounts",
|
||||
"owner": "Administrator",
|
||||
@ -21,5 +21,6 @@
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Review Chart of Accounts",
|
||||
"validate_action": 0
|
||||
"validate_action": 0,
|
||||
"video_url": "https://www.youtube.com/embed/AcfMCT7wLLo"
|
||||
}
|
22
erpnext/accounts/onboarding_step/company/company.json
Normal file
22
erpnext/accounts/onboarding_step/company/company.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"action": "Go to Page",
|
||||
"action_label": "Let's Review your Company",
|
||||
"creation": "2021-06-29 14:47:42.497318",
|
||||
"description": "# Company\n\nIn ERPNext, you can also create multiple companies, and establish relationships (group/subsidiary) among them.\n\nWithin the company master, you can capture various default accounts for that Company and set crucial settings related to the accounting methodology followed for a company. \n",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-08-13 11:43:35.767341",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Company",
|
||||
"owner": "Administrator",
|
||||
"path": "app/company",
|
||||
"reference_document": "Company",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Review Company",
|
||||
"validate_action": 1
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Go to Page",
|
||||
"action_label": "View Cost Center Tree",
|
||||
"creation": "2021-07-12 12:02:05.726608",
|
||||
"description": "# Cost Centers for Budgeting and Analysis\n\nWhile your Books of Accounts are framed to fulfill statutory requirements, you can set up Cost Center and Accounting Dimensions to address your companies reporting and budgeting requirements.\n\nClick here to learn more about how <b>[Cost Center](https://docs.erpnext.com/docs/v13/user/manual/en/accounts/cost-center)</b> and <b> [Dimensions](https://docs.erpnext.com/docs/v13/user/manual/en/accounts/accounting-dimensions)</b> allow you to get advanced financial analytics reports from ERPNext.",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-08-13 11:55:08.510366",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Cost Centers for Report and Budgeting",
|
||||
"owner": "Administrator",
|
||||
"path": "cost-center/view/tree",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Cost Centers for Budgeting and Analysis",
|
||||
"validate_action": 1
|
||||
}
|
@ -1,14 +1,15 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"action": "Show Form Tour",
|
||||
"action_label": "Let\u2019s create your first Purchase Invoice",
|
||||
"creation": "2020-05-14 22:10:07.049704",
|
||||
"description": "# What's a Purchase Invoice?\n\nA Purchase Invoice is a bill you receive from your Suppliers against which you need to make the payment.\nPurchase Invoice is the exact opposite of your Sales Invoice. Here you accrue expenses to your Supplier. \n\nThe following is what a typical purchase cycle looks like, however you can create a purchase invoice directly as well.\n\n![Purchase Flow](https://docs.erpnext.com/docs/assets/img/accounts/pi-flow.png)\n\n",
|
||||
"description": "# Create your first Purchase Invoice\n\nA Purchase Invoice is a bill received from a Supplier for a product(s) or service(s) delivery to your company. You can track payables through Purchase Invoice and process Payment Entries against it.\n\nPurchase Invoices can also be created against a Purchase Order or Purchase Receipt.",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-10-30 15:30:26.337773",
|
||||
"modified": "2021-08-13 11:56:11.677253",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Create Your First Purchase Invoice",
|
||||
"owner": "Administrator",
|
||||
|
@ -0,0 +1,23 @@
|
||||
{
|
||||
"action": "View Report",
|
||||
"creation": "2021-07-12 12:08:47.026115",
|
||||
"description": "# Financial Statements\n\nIn ERPNext, you can get crucial financial reports like [Balance Sheet] and [Profit and Loss] statements with a click of a button. You can run in the report for a different period and plot analytics charts premised on statement data. For more reports, check sections like Financial Statements, General Ledger, and Profitability reports.\n\n<b>[Check Accounting reports](https://docs.erpnext.com/docs/v13/user/manual/en/accounts/accounting-reports)</b>",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-08-13 11:59:18.767407",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Financial Statements",
|
||||
"owner": "Administrator",
|
||||
"reference_report": "General Ledger",
|
||||
"report_description": "General Ledger",
|
||||
"report_reference_doctype": "GL Entry",
|
||||
"report_type": "Script Report",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Financial Statements",
|
||||
"validate_action": 1
|
||||
}
|
@ -1,21 +1,21 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"action_label": "Make a Sales Tax Template",
|
||||
"action_label": "Manage Sales Tax Templates",
|
||||
"creation": "2020-05-13 19:29:43.844463",
|
||||
"description": "# Setting up Taxes\n\nAny sophisticated accounting system, including ERPNext will have automatic tax calculations for your transactions. These calculations are based on user defined rules in compliance to local rules and regulations.\n\nERPNext allows this via *Tax Templates*. These templates can be used in Sales Orders and Sales Invoices. Other types of charges that may apply to your invoices (like shipping, insurance etc.) can also be configured as taxes.\n\nFor Tax Accounts that you want to use in the tax templates, go to:\n\n`> Accounting > Taxes > Sales Taxes and Charges Template`\n\nYou can read more about these templates in our documentation [here](https://docs.erpnext.com/docs/user/manual/en/selling/sales-taxes-and-charges-template)\n",
|
||||
"description": "# Setting up Taxes\n\nERPNext lets you configure your taxes so that they are automatically applied in your buying and selling transactions. You can configure them globally or even on Items. ERPNext taxes are pre-configured for most regions.\n",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2020-10-30 14:54:18.087383",
|
||||
"modified": "2021-08-13 11:48:37.238610",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Setup Taxes",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Sales Taxes and Charges Template",
|
||||
"show_form_tour": 1,
|
||||
"show_full_form": 1,
|
||||
"title": "Lets create a Tax Template for Sales ",
|
||||
"title": "Setting up Taxes",
|
||||
"validate_action": 0
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
{
|
||||
"action": "Watch Video",
|
||||
"action_label": "Learn how to update opening balances",
|
||||
"creation": "2021-07-12 11:53:50.525030",
|
||||
"description": "# Updating Opening Balances\n\nOnce you close the financial statement in previous accounting software, you can update the same as opening in your ERPNext's Balance Sheet accounts. This will allow you to get complete financial statements from ERPNext in the coming years, and discontinue the parallel accounting system right away.",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"intro_video_url": "https://www.youtube.com/embed/U5wPIvEn-0c",
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-08-13 11:56:45.483418",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Updating Opening Balances",
|
||||
"owner": "Administrator",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Updating Opening Balances",
|
||||
"validate_action": 1,
|
||||
"video_url": "https://www.youtube.com/embed/U5wPIvEn-0c"
|
||||
}
|
@ -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()
|
||||
]);
|
||||
|
||||
});
|
@ -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()
|
||||
]);
|
||||
|
||||
});
|
125
erpnext/assets/form_tour/asset/asset.json
Normal file
125
erpnext/assets/form_tour/asset/asset.json
Normal file
@ -0,0 +1,125 @@
|
||||
{
|
||||
"creation": "2021-08-24 16:55:10.923434",
|
||||
"docstatus": 0,
|
||||
"doctype": "Form Tour",
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"modified": "2021-08-24 16:55:10.923434",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset",
|
||||
"owner": "Administrator",
|
||||
"reference_doctype": "Asset",
|
||||
"save_on_complete": 0,
|
||||
"steps": [
|
||||
{
|
||||
"description": "Select Naming Series based on which Asset ID will be generated",
|
||||
"field": "",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Naming Series",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Naming Series"
|
||||
},
|
||||
{
|
||||
"description": "Select an Asset Item",
|
||||
"field": "",
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Item Code",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Item Code"
|
||||
},
|
||||
{
|
||||
"description": "Select a Location",
|
||||
"field": "",
|
||||
"fieldname": "location",
|
||||
"fieldtype": "Link",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Location",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Location"
|
||||
},
|
||||
{
|
||||
"description": "Check Is Existing Asset",
|
||||
"field": "",
|
||||
"fieldname": "is_existing_asset",
|
||||
"fieldtype": "Check",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Is Existing Asset",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Is Existing Asset?"
|
||||
},
|
||||
{
|
||||
"description": "Set Available for use date",
|
||||
"field": "",
|
||||
"fieldname": "available_for_use_date",
|
||||
"fieldtype": "Date",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Available-for-use Date",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Available For Use Date"
|
||||
},
|
||||
{
|
||||
"description": "Set Gross purchase amount",
|
||||
"field": "",
|
||||
"fieldname": "gross_purchase_amount",
|
||||
"fieldtype": "Currency",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Gross Purchase Amount",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Gross Purchase Amount"
|
||||
},
|
||||
{
|
||||
"description": "Set Purchase Date",
|
||||
"field": "",
|
||||
"fieldname": "purchase_date",
|
||||
"fieldtype": "Date",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Purchase Date",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Purchase Date"
|
||||
},
|
||||
{
|
||||
"description": "Check Calculate Depreciation",
|
||||
"field": "",
|
||||
"fieldname": "calculate_depreciation",
|
||||
"fieldtype": "Check",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Calculate Depreciation",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Calculate Depreciation"
|
||||
},
|
||||
{
|
||||
"description": "Enter depreciation which has already been booked for this asset",
|
||||
"field": "",
|
||||
"fieldname": "opening_accumulated_depreciation",
|
||||
"fieldtype": "Currency",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Opening Accumulated Depreciation",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Accumulated Depreciation"
|
||||
}
|
||||
],
|
||||
"title": "Asset"
|
||||
}
|
65
erpnext/assets/form_tour/asset_category/asset_category.json
Normal file
65
erpnext/assets/form_tour/asset_category/asset_category.json
Normal file
@ -0,0 +1,65 @@
|
||||
{
|
||||
"creation": "2021-08-24 12:48:20.763173",
|
||||
"docstatus": 0,
|
||||
"doctype": "Form Tour",
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"modified": "2021-08-24 12:48:20.763173",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset Category",
|
||||
"owner": "Administrator",
|
||||
"reference_doctype": "Asset Category",
|
||||
"save_on_complete": 0,
|
||||
"steps": [
|
||||
{
|
||||
"description": "Name Asset category. You can create categories based on Asset Types like Furniture, Property, Electronics etc.",
|
||||
"field": "",
|
||||
"fieldname": "asset_category_name",
|
||||
"fieldtype": "Data",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Asset Category Name",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Asset Category Name"
|
||||
},
|
||||
{
|
||||
"description": "Check to enable Capital Work in Progress accounting",
|
||||
"field": "",
|
||||
"fieldname": "enable_cwip_accounting",
|
||||
"fieldtype": "Check",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Enable Capital Work in Progress Accounting",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Enable CWIP Accounting"
|
||||
},
|
||||
{
|
||||
"description": "Add a row to define Depreciation Method and other details. Note that you can leave Finance Book blank to have it's accounting done in the primary books of accounts.",
|
||||
"field": "",
|
||||
"fieldname": "finance_books",
|
||||
"fieldtype": "Table",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Finance Books",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Finance Book Detail"
|
||||
},
|
||||
{
|
||||
"description": "Select the Fixed Asset and Depreciation accounts applicable for this Asset Category type",
|
||||
"field": "",
|
||||
"fieldname": "accounts",
|
||||
"fieldtype": "Table",
|
||||
"has_next_condition": 0,
|
||||
"is_table_field": 0,
|
||||
"label": "Accounts",
|
||||
"parent_field": "",
|
||||
"position": "Bottom",
|
||||
"title": "Accounts"
|
||||
}
|
||||
],
|
||||
"title": "Asset Category"
|
||||
}
|
@ -13,26 +13,26 @@
|
||||
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/asset",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"modified": "2020-07-08 14:05:51.828497",
|
||||
"modified": "2021-08-24 17:50:41.573281",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Assets",
|
||||
"owner": "Administrator",
|
||||
"steps": [
|
||||
{
|
||||
"step": "Introduction to Assets"
|
||||
"step": "Fixed Asset Accounts"
|
||||
},
|
||||
{
|
||||
"step": "Create a Fixed Asset Item"
|
||||
"step": "Asset Category"
|
||||
},
|
||||
{
|
||||
"step": "Create an Asset Category"
|
||||
"step": "Asset Item"
|
||||
},
|
||||
{
|
||||
"step": "Purchase an Asset Item"
|
||||
"step": "Asset Purchase"
|
||||
},
|
||||
{
|
||||
"step": "Create an Asset"
|
||||
"step": "Existing Asset"
|
||||
}
|
||||
],
|
||||
"subtitle": "Assets, Depreciations, Repairs, and more.",
|
||||
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Show Form Tour",
|
||||
"action_label": "Let's review existing Asset Category",
|
||||
"creation": "2021-08-13 14:26:18.656303",
|
||||
"description": "# Asset Category\n\nAn Asset Category classifies different assets of a Company.\n\nYou can create an Asset Category based on the type of assets. For example, all your desktops and laptops can be part of an Asset Category named \"Electronic Equipments\". Create a separate category for furniture. Also, you can update default properties for each category, like:\n - Depreciation type and duration\n - Fixed asset account\n - Depreciation account\n",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-08-24 12:49:37.665239",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Asset Category",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Asset Category",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Define Asset Category",
|
||||
"validate_action": 1
|
||||
}
|
21
erpnext/assets/onboarding_step/asset_item/asset_item.json
Normal file
21
erpnext/assets/onboarding_step/asset_item/asset_item.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Show Form Tour",
|
||||
"action_label": "Let's create a new Asset item",
|
||||
"creation": "2021-08-13 14:27:07.277167",
|
||||
"description": "# Asset Item\n\nAsset items are created based on Asset Category. You can create one or multiple items against once Asset Category. The sales and purchase transaction for Asset is done via Asset Item. ",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-08-16 13:59:18.362233",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Asset Item",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Item",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Create an Asset Item",
|
||||
"validate_action": 1
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Show Form Tour",
|
||||
"action_label": "Let's create a Purchase Receipt",
|
||||
"creation": "2021-08-13 14:27:53.678621",
|
||||
"description": "# Purchase an Asset\n\nAssets purchases process if done following the standard Purchase cycle. If capital work in progress is enabled in Asset Category, Asset will be created as soon as Purchase Receipt is created for it. You can quickly create a Purchase Receipt for Asset and see its impact on books of accounts.",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-08-24 17:26:57.180637",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Asset Purchase",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Purchase Receipt",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Purchase an Asset",
|
||||
"validate_action": 1
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Show Form Tour",
|
||||
"action_label": "Add an existing Asset",
|
||||
"creation": "2021-08-13 14:28:30.650459",
|
||||
"description": "# Add an Existing Asset\n\nIf you are just starting with ERPNext, you will need to enter Assets you already possess. You can add them as existing fixed assets in ERPNext. Please note that you will have to make a Journal Entry separately updating the opening balance in the fixed asset account.",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-08-16 14:03:48.850471",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Existing Asset",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Asset",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Add an Existing Asset",
|
||||
"validate_action": 1
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Go to Page",
|
||||
"action_label": "Let's walk-through Chart of Accounts to review setup",
|
||||
"creation": "2021-08-13 14:23:09.297765",
|
||||
"description": "# Fixed Asset Accounts\n\nWith the company, a host of fixed asset accounts are pre-configured. To ensure your asset transactions are leading to correct accounting entries, you can review and set up following asset accounts as per your business requirements.\n - Fixed asset accounts (Asset account)\n - Accumulated depreciation\n - Capital Work in progress (CWIP) account\n - Asset Depreciation account (Expense account)",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2021-08-24 17:46:37.646174",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Fixed Asset Accounts",
|
||||
"owner": "Administrator",
|
||||
"path": "app/account/view/tree",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Review Fixed Asset Accounts",
|
||||
"validate_action": 1
|
||||
}
|
@ -14,7 +14,7 @@ from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_a
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
from erpnext.buying.utils import update_last_purchase_rate
|
||||
from erpnext.controllers.sales_and_purchase_return import validate_return
|
||||
from erpnext.accounts.party import get_party_account_currency, validate_party_frozen_disabled
|
||||
from erpnext.accounts.party import get_party_account_currency, validate_party_frozen_disabled, get_party_account
|
||||
from erpnext.accounts.doctype.pricing_rule.utils import (apply_pricing_rule_on_transaction,
|
||||
apply_pricing_rule_for_free_items, get_applied_pricing_rules)
|
||||
from erpnext.exceptions import InvalidCurrency
|
||||
@ -1363,6 +1363,67 @@ class AccountsController(TransactionBase):
|
||||
|
||||
return False
|
||||
|
||||
def process_common_party_accounting(self):
|
||||
is_invoice = self.doctype in ['Sales Invoice', 'Purchase Invoice']
|
||||
if not is_invoice:
|
||||
return
|
||||
|
||||
if frappe.db.get_single_value('Accounts Settings', 'enable_common_party_accounting'):
|
||||
party_link = self.get_common_party_link()
|
||||
if party_link and self.outstanding_amount:
|
||||
self.create_advance_and_reconcile(party_link)
|
||||
|
||||
def get_common_party_link(self):
|
||||
party_type, party = self.get_party()
|
||||
return frappe.db.get_value(
|
||||
doctype='Party Link',
|
||||
filters={'secondary_role': party_type, 'secondary_party': party},
|
||||
fieldname=['primary_role', 'primary_party'],
|
||||
as_dict=True
|
||||
)
|
||||
|
||||
def create_advance_and_reconcile(self, party_link):
|
||||
secondary_party_type, secondary_party = self.get_party()
|
||||
primary_party_type, primary_party = party_link.primary_role, party_link.primary_party
|
||||
|
||||
primary_account = get_party_account(primary_party_type, primary_party, self.company)
|
||||
secondary_account = get_party_account(secondary_party_type, secondary_party, self.company)
|
||||
|
||||
jv = frappe.new_doc('Journal Entry')
|
||||
jv.voucher_type = 'Journal Entry'
|
||||
jv.posting_date = self.posting_date
|
||||
jv.company = self.company
|
||||
jv.remark = 'Adjustment for {} {}'.format(self.doctype, self.name)
|
||||
|
||||
reconcilation_entry = frappe._dict()
|
||||
advance_entry = frappe._dict()
|
||||
|
||||
reconcilation_entry.account = secondary_account
|
||||
reconcilation_entry.party_type = secondary_party_type
|
||||
reconcilation_entry.party = secondary_party
|
||||
reconcilation_entry.reference_type = self.doctype
|
||||
reconcilation_entry.reference_name = self.name
|
||||
reconcilation_entry.cost_center = self.cost_center
|
||||
|
||||
advance_entry.account = primary_account
|
||||
advance_entry.party_type = primary_party_type
|
||||
advance_entry.party = primary_party
|
||||
advance_entry.cost_center = self.cost_center
|
||||
advance_entry.is_advance = 'Yes'
|
||||
|
||||
if self.doctype == 'Sales Invoice':
|
||||
reconcilation_entry.credit_in_account_currency = self.outstanding_amount
|
||||
advance_entry.debit_in_account_currency = self.outstanding_amount
|
||||
else:
|
||||
advance_entry.credit_in_account_currency = self.outstanding_amount
|
||||
reconcilation_entry.debit_in_account_currency = self.outstanding_amount
|
||||
|
||||
jv.append('accounts', reconcilation_entry)
|
||||
jv.append('accounts', advance_entry)
|
||||
|
||||
jv.save()
|
||||
jv.submit()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_tax_rate(account_head):
|
||||
return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True)
|
||||
|
@ -5,7 +5,9 @@ import frappe
|
||||
from frappe import _
|
||||
from frappe.desk.form import assign_to
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import flt, unique
|
||||
from frappe.utils import flt, unique, add_days
|
||||
from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday
|
||||
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
|
||||
|
||||
class EmployeeBoardingController(Document):
|
||||
'''
|
||||
@ -41,10 +43,14 @@ class EmployeeBoardingController(Document):
|
||||
|
||||
def create_task_and_notify_user(self):
|
||||
# create the task for the given project and assign to the concerned person
|
||||
holiday_list = self.get_holiday_list()
|
||||
|
||||
for activity in self.activities:
|
||||
if activity.task:
|
||||
continue
|
||||
|
||||
dates = self.get_task_dates(activity, holiday_list)
|
||||
|
||||
task = frappe.get_doc({
|
||||
'doctype': 'Task',
|
||||
'project': self.project,
|
||||
@ -52,7 +58,9 @@ class EmployeeBoardingController(Document):
|
||||
'description': activity.description,
|
||||
'department': self.department,
|
||||
'company': self.company,
|
||||
'task_weight': activity.task_weight
|
||||
'task_weight': activity.task_weight,
|
||||
'exp_start_date': dates[0],
|
||||
'exp_end_date': dates[1]
|
||||
}).insert(ignore_permissions=True)
|
||||
activity.db_set('task', task.name)
|
||||
|
||||
@ -79,6 +87,36 @@ class EmployeeBoardingController(Document):
|
||||
if users:
|
||||
self.assign_task_to_users(task, users)
|
||||
|
||||
def get_holiday_list(self):
|
||||
if self.doctype == 'Employee Separation':
|
||||
return get_holiday_list_for_employee(self.employee)
|
||||
else:
|
||||
if self.employee:
|
||||
return get_holiday_list_for_employee(self.employee)
|
||||
else:
|
||||
if not self.holiday_list:
|
||||
frappe.throw(_('Please set the Holiday List.'), frappe.MandatoryError)
|
||||
else:
|
||||
return self.holiday_list
|
||||
|
||||
def get_task_dates(self, activity, holiday_list):
|
||||
start_date = end_date = None
|
||||
|
||||
if activity.begin_on:
|
||||
start_date = add_days(self.boarding_begins_on, activity.begin_on)
|
||||
start_date = self.update_if_holiday(start_date, holiday_list)
|
||||
|
||||
if activity.duration:
|
||||
end_date = add_days(self.boarding_begins_on, activity.begin_on + activity.duration)
|
||||
end_date = self.update_if_holiday(end_date, holiday_list)
|
||||
|
||||
return [start_date, end_date]
|
||||
|
||||
def update_if_holiday(self, date, holiday_list):
|
||||
while is_holiday(holiday_list, date):
|
||||
date = add_days(date, 1)
|
||||
return date
|
||||
|
||||
def assign_task_to_users(self, task, users):
|
||||
for user in users:
|
||||
args = {
|
||||
@ -103,7 +141,8 @@ class EmployeeBoardingController(Document):
|
||||
@frappe.whitelist()
|
||||
def get_onboarding_details(parent, parenttype):
|
||||
return frappe.get_all('Employee Boarding Activity',
|
||||
fields=['activity_name', 'role', 'user', 'required_for_employee_creation', 'description', 'task_weight'],
|
||||
fields=['activity_name', 'role', 'user', 'required_for_employee_creation',
|
||||
'description', 'task_weight', 'begin_on', 'duration'],
|
||||
filters={'parent': parent, 'parenttype': parenttype},
|
||||
order_by= 'idx')
|
||||
|
||||
|
@ -394,8 +394,22 @@ def get_rate_for_return(voucher_type, voucher_no, item_code, return_against=None
|
||||
if not return_against:
|
||||
return_against = frappe.get_cached_value(voucher_type, voucher_no, "return_against")
|
||||
|
||||
if not return_against and voucher_type == 'Sales Invoice' and sle:
|
||||
return get_incoming_rate({
|
||||
return_against_item_field = get_return_against_item_fields(voucher_type)
|
||||
|
||||
filters = get_filters(voucher_type, voucher_no, voucher_detail_no,
|
||||
return_against, item_code, return_against_item_field, item_row)
|
||||
|
||||
if voucher_type in ("Purchase Receipt", "Purchase Invoice"):
|
||||
select_field = "incoming_rate"
|
||||
else:
|
||||
select_field = "abs(stock_value_difference / actual_qty)"
|
||||
|
||||
rate = flt(frappe.db.get_value("Stock Ledger Entry", filters, select_field))
|
||||
if not (rate and return_against) and voucher_type in ['Sales Invoice', 'Delivery Note']:
|
||||
rate = frappe.db.get_value(f'{voucher_type} Item', voucher_detail_no, 'incoming_rate')
|
||||
|
||||
if not rate and sle:
|
||||
rate = get_incoming_rate({
|
||||
"item_code": sle.item_code,
|
||||
"warehouse": sle.warehouse,
|
||||
"posting_date": sle.get('posting_date'),
|
||||
@ -407,17 +421,7 @@ def get_rate_for_return(voucher_type, voucher_no, item_code, return_against=None
|
||||
"voucher_no": sle.voucher_no
|
||||
}, raise_error_if_no_rate=False)
|
||||
|
||||
return_against_item_field = get_return_against_item_fields(voucher_type)
|
||||
|
||||
filters = get_filters(voucher_type, voucher_no, voucher_detail_no,
|
||||
return_against, item_code, return_against_item_field, item_row)
|
||||
|
||||
if voucher_type in ("Purchase Receipt", "Purchase Invoice"):
|
||||
select_field = "incoming_rate"
|
||||
else:
|
||||
select_field = "abs(stock_value_difference / actual_qty)"
|
||||
|
||||
return flt(frappe.db.get_value("Stock Ledger Entry", filters, select_field))
|
||||
return rate
|
||||
|
||||
def get_return_against_item_fields(voucher_type):
|
||||
return_against_item_fields = {
|
||||
|
@ -362,7 +362,7 @@ class SellingController(StockController):
|
||||
sales_order.update_reserved_qty(so_item_rows)
|
||||
|
||||
def set_incoming_rate(self):
|
||||
if self.doctype not in ("Delivery Note", "Sales Invoice", "Sales Order"):
|
||||
if self.doctype not in ("Delivery Note", "Sales Invoice"):
|
||||
return
|
||||
|
||||
items = self.get("items") + (self.get("packed_items") or [])
|
||||
@ -371,6 +371,7 @@ class SellingController(StockController):
|
||||
# Get incoming rate based on original item cost based on valuation method
|
||||
qty = flt(d.get('stock_qty') or d.get('actual_qty'))
|
||||
|
||||
if not d.incoming_rate:
|
||||
d.incoming_rate = get_incoming_rate({
|
||||
"item_code": d.item_code,
|
||||
"warehouse": d.warehouse,
|
||||
@ -422,7 +423,7 @@ class SellingController(StockController):
|
||||
or (cint(self.is_return) and self.docstatus==2)):
|
||||
sl_entries.append(self.get_sle_for_source_warehouse(d))
|
||||
|
||||
if d.target_warehouse:
|
||||
if d.target_warehouse and self.get("is_internal_customer"):
|
||||
sl_entries.append(self.get_sle_for_target_warehouse(d))
|
||||
|
||||
if d.warehouse and ((not cint(self.is_return) and self.docstatus==2)
|
||||
|
@ -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()
|
||||
]);
|
||||
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user