Merge branch 'develop' into so-days-taken-to-deliver
diff --git a/dev-requirements.txt b/dev-requirements.txt
new file mode 100644
index 0000000..15545c0
--- /dev/null
+++ b/dev-requirements.txt
@@ -0,0 +1 @@
+hypothesis~=6.31.0
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index a5de50f..0b4696c 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -55,9 +55,9 @@
company.enable_perpetual_inventory = enable
company.save()
-def encode_company_abbr(name, company):
+def encode_company_abbr(name, company=None, abbr=None):
'''Returns name encoded with company abbreviation'''
- company_abbr = frappe.get_cached_value('Company', company, "abbr")
+ company_abbr = abbr or frappe.get_cached_value('Company', company, "abbr")
parts = name.rsplit(" - ", 1)
if parts[-1].lower() != company_abbr.lower():
diff --git a/erpnext/accounts/doctype/account/tests/test_account.js b/erpnext/accounts/doctype/account/tests/test_account.js
deleted file mode 100644
index 039e33e..0000000
--- a/erpnext/accounts/doctype/account/tests/test_account.js
+++ /dev/null
@@ -1,29 +0,0 @@
-QUnit.module('accounts');
-
-QUnit.test("test account", function(assert) {
- assert.expect(4);
- let done = assert.async();
- frappe.run_serially([
- () => frappe.set_route('Tree', 'Account'),
- () => frappe.timeout(3),
- () => frappe.click_button('Expand All'),
- () => frappe.timeout(1),
- () => frappe.click_link('Debtors'),
- () => frappe.click_button('Edit'),
- () => frappe.timeout(1),
- () => {
- assert.ok(cur_frm.doc.root_type=='Asset');
- assert.ok(cur_frm.doc.report_type=='Balance Sheet');
- assert.ok(cur_frm.doc.account_type=='Receivable');
- },
- () => frappe.click_button('Ledger'),
- () => frappe.timeout(1),
- () => {
- // check if general ledger report shown
- assert.deepEqual(frappe.get_route(), ['query-report', 'General Ledger']);
- window.history.back();
- return frappe.timeout(1);
- },
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/account/tests/test_account_with_number.js b/erpnext/accounts/doctype/account/tests/test_account_with_number.js
deleted file mode 100644
index c03e278..0000000
--- a/erpnext/accounts/doctype/account/tests/test_account_with_number.js
+++ /dev/null
@@ -1,69 +0,0 @@
-QUnit.module('accounts');
-
-QUnit.test("test account with number", function(assert) {
- assert.expect(7);
- let done = assert.async();
- frappe.run_serially([
- () => frappe.set_route('Tree', 'Account'),
- () => frappe.click_link('Income'),
- () => frappe.click_button('Add Child'),
- () => frappe.timeout(.5),
- () => {
- cur_dialog.fields_dict.account_name.$input.val("Test Income");
- cur_dialog.fields_dict.account_number.$input.val("4010");
- },
- () => frappe.click_button('Create New'),
- () => frappe.timeout(1),
- () => {
- assert.ok($('a:contains("4010 - Test Income"):visible').length!=0, "Account created with number");
- },
- () => frappe.click_link('4010 - Test Income'),
- () => frappe.click_button('Edit'),
- () => frappe.timeout(.5),
- () => frappe.click_button('Update Account Number'),
- () => frappe.timeout(.5),
- () => {
- cur_dialog.fields_dict.account_number.$input.val("4020");
- },
- () => frappe.timeout(1),
- () => cur_dialog.primary_action(),
- () => frappe.timeout(1),
- () => cur_frm.refresh_fields(),
- () => frappe.timeout(.5),
- () => {
- var abbr = frappe.get_abbr(frappe.defaults.get_default("Company"));
- var new_account = "4020 - Test Income - " + abbr;
- assert.ok(cur_frm.doc.name==new_account, "Account renamed");
- assert.ok(cur_frm.doc.account_name=="Test Income", "account name remained same");
- assert.ok(cur_frm.doc.account_number=="4020", "Account number updated to 4020");
- },
- () => frappe.timeout(1),
- () => frappe.click_button('Menu'),
- () => frappe.click_link('Rename'),
- () => frappe.timeout(.5),
- () => {
- cur_dialog.fields_dict.new_name.$input.val("4030 - Test Income");
- },
- () => frappe.timeout(.5),
- () => frappe.click_button("Rename"),
- () => frappe.timeout(2),
- () => {
- assert.ok(cur_frm.doc.account_name=="Test Income", "account name remained same");
- assert.ok(cur_frm.doc.account_number=="4030", "Account number updated to 4030");
- },
- () => frappe.timeout(.5),
- () => frappe.click_button('Chart of Accounts'),
- () => frappe.timeout(.5),
- () => frappe.click_button('Menu'),
- () => frappe.click_link('Refresh'),
- () => frappe.click_button('Expand All'),
- () => frappe.click_link('4030 - Test Income'),
- () => frappe.click_button('Delete'),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(.5),
- () => {
- assert.ok($('a:contains("4030 - Test Account"):visible').length==0, "Account deleted");
- },
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/account/tests/test_make_tax_account.js b/erpnext/accounts/doctype/account/tests/test_make_tax_account.js
deleted file mode 100644
index a0e09a1..0000000
--- a/erpnext/accounts/doctype/account/tests/test_make_tax_account.js
+++ /dev/null
@@ -1,46 +0,0 @@
-QUnit.module('accounts');
-QUnit.test("test account", assert => {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => frappe.set_route('Tree', 'Account'),
- () => frappe.click_button('Expand All'),
- () => frappe.click_link('Duties and Taxes - '+ frappe.get_abbr(frappe.defaults.get_default("Company"))),
- () => {
- if($('a:contains("CGST"):visible').length == 0){
- return frappe.map_tax.make('CGST', 9);
- }
- },
- () => {
- if($('a:contains("SGST"):visible').length == 0){
- return frappe.map_tax.make('SGST', 9);
- }
- },
- () => {
- if($('a:contains("IGST"):visible').length == 0){
- return frappe.map_tax.make('IGST', 18);
- }
- },
- () => {
- assert.ok($('a:contains("CGST"):visible').length!=0, "CGST Checked");
- assert.ok($('a:contains("SGST"):visible').length!=0, "SGST Checked");
- assert.ok($('a:contains("IGST"):visible').length!=0, "IGST Checked");
- },
- () => done()
- ]);
-});
-
-
-frappe.map_tax = {
- make:function(text,rate){
- return frappe.run_serially([
- () => frappe.click_button('Add Child'),
- () => frappe.timeout(0.2),
- () => cur_dialog.set_value('account_name',text),
- () => cur_dialog.set_value('account_type','Tax'),
- () => cur_dialog.set_value('tax_rate',rate),
- () => cur_dialog.set_value('account_currency','INR'),
- () => frappe.click_button('Create New'),
- ]);
- }
-};
diff --git a/erpnext/accounts/doctype/accounts_settings/test_accounts_settings.js b/erpnext/accounts/doctype/accounts_settings/test_accounts_settings.js
deleted file mode 100644
index f9aa166..0000000
--- a/erpnext/accounts/doctype/accounts_settings/test_accounts_settings.js
+++ /dev/null
@@ -1,35 +0,0 @@
-QUnit.module('accounts');
-
-QUnit.test("test: Accounts Settings doesn't allow negatives", function (assert) {
- let done = assert.async();
-
- assert.expect(2);
-
- frappe.run_serially([
- () => frappe.set_route('Form', 'Accounts Settings', 'Accounts Settings'),
- () => frappe.timeout(2),
- () => unchecked_if_checked(cur_frm, 'Allow Stale Exchange Rates', frappe.click_check),
- () => cur_frm.set_value('stale_days', 0),
- () => frappe.click_button('Save'),
- () => frappe.timeout(2),
- () => {
- assert.ok(cur_dialog);
- },
- () => frappe.click_button('Close'),
- () => cur_frm.set_value('stale_days', -1),
- () => frappe.click_button('Save'),
- () => frappe.timeout(2),
- () => {
- assert.ok(cur_dialog);
- },
- () => frappe.click_button('Close'),
- () => done()
- ]);
-
-});
-
-const unchecked_if_checked = function(frm, field_name, fn){
- if (frm.doc.allow_stale) {
- return fn(field_name);
- }
-};
diff --git a/erpnext/accounts/doctype/journal_entry/test_journal_entry.js b/erpnext/accounts/doctype/journal_entry/test_journal_entry.js
deleted file mode 100644
index 28ccd95..0000000
--- a/erpnext/accounts/doctype/journal_entry/test_journal_entry.js
+++ /dev/null
@@ -1,39 +0,0 @@
-QUnit.module('Journal Entry');
-
-QUnit.test("test journal entry", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Journal Entry', [
- {posting_date:frappe.datetime.add_days(frappe.datetime.nowdate(), 0)},
- {accounts: [
- [
- {'account':'Debtors - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {'party_type':'Customer'},
- {'party':'Test Customer 1'},
- {'credit_in_account_currency':1000},
- {'is_advance':'Yes'},
- ],
- [
- {'account':'HDFC - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {'debit_in_account_currency':1000},
- ]
- ]},
- {cheque_no:1234},
- {cheque_date: frappe.datetime.add_days(frappe.datetime.nowdate(), -1)},
- {user_remark: 'Test'},
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.total_debit==1000, "total debit correct");
- assert.ok(cur_frm.doc.total_credit==1000, "total credit correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
index 2a923f0..ddb833f 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
@@ -159,7 +159,8 @@
frappe.scrub(row.party_type): row.party,
"is_pos": 0,
"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice",
- "update_stock": 0
+ "update_stock": 0,
+ "invoice_number": row.invoice_number
})
accounting_dimension = get_accounting_dimensions()
@@ -200,10 +201,13 @@
names = []
for idx, d in enumerate(invoices):
try:
+ invoice_number = None
+ if d.invoice_number:
+ invoice_number = d.invoice_number
publish(idx, len(invoices), d.doctype)
doc = frappe.get_doc(d)
doc.flags.ignore_mandatory = True
- doc.insert()
+ doc.insert(set_name=invoice_number)
doc.submit()
frappe.db.commit()
names.append(doc.name)
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
index c795e83..b5aae98 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
@@ -18,10 +18,10 @@
if not frappe.db.exists("Company", "_Test Opening Invoice Company"):
make_company()
- def make_invoices(self, invoice_type="Sales", company=None, party_1=None, party_2=None):
+ def make_invoices(self, invoice_type="Sales", company=None, party_1=None, party_2=None, invoice_number=None):
doc = frappe.get_single("Opening Invoice Creation Tool")
args = get_opening_invoice_creation_dict(invoice_type=invoice_type, company=company,
- party_1=party_1, party_2=party_2)
+ party_1=party_1, party_2=party_2, invoice_number=invoice_number)
doc.update(args)
return doc.make_invoices()
@@ -92,6 +92,20 @@
# teardown
frappe.db.set_value("Company", company, "default_receivable_account", old_default_receivable_account)
+ def test_renaming_of_invoice_using_invoice_number_field(self):
+ company = "_Test Opening Invoice Company"
+ party_1, party_2 = make_customer("Customer A"), make_customer("Customer B")
+ self.make_invoices(company=company, party_1=party_1, party_2=party_2, invoice_number="TEST-NEW-INV-11")
+
+ sales_inv1 = frappe.get_all('Sales Invoice', filters={'customer':'Customer A'})[0].get("name")
+ sales_inv2 = frappe.get_all('Sales Invoice', filters={'customer':'Customer B'})[0].get("name")
+ self.assertEqual(sales_inv1, "TEST-NEW-INV-11")
+
+ #teardown
+ for inv in [sales_inv1, sales_inv2]:
+ doc = frappe.get_doc('Sales Invoice', inv)
+ doc.cancel()
+
def get_opening_invoice_creation_dict(**args):
party = "Customer" if args.get("invoice_type", "Sales") == "Sales" else "Supplier"
company = args.get("company", "_Test Company")
@@ -107,7 +121,8 @@
"item_name": "Opening Item",
"due_date": "2016-09-10",
"posting_date": "2016-09-05",
- "temporary_opening_account": get_temporary_opening_account(company)
+ "temporary_opening_account": get_temporary_opening_account(company),
+ "invoice_number": args.get("invoice_number")
},
{
"qty": 2.0,
@@ -116,7 +131,8 @@
"item_name": "Opening Item",
"due_date": "2016-09-10",
"posting_date": "2016-09-05",
- "temporary_opening_account": get_temporary_opening_account(company)
+ "temporary_opening_account": get_temporary_opening_account(company),
+ "invoice_number": None
}
]
})
@@ -132,7 +148,7 @@
company.company_name = "_Test Opening Invoice Company"
company.abbr = "_TOIC"
company.default_currency = "INR"
- company.country = "India"
+ company.country = "Pakistan"
company.insert()
return company
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json b/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json
index 4ce8cb9..5c19091 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json
@@ -1,9 +1,11 @@
{
+ "actions": [],
"creation": "2017-08-29 04:26:36.159247",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
+ "invoice_number",
"party_type",
"party",
"temporary_opening_account",
@@ -103,10 +105,18 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
+ },
+ {
+ "description": "Reference number of the invoice from the previous system",
+ "fieldname": "invoice_number",
+ "fieldtype": "Data",
+ "in_list_view": 1,
+ "label": "Invoice Number"
}
],
"istable": 1,
- "modified": "2019-07-25 15:00:00.460695",
+ "links": [],
+ "modified": "2021-12-17 19:25:06.053187",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Opening Invoice Creation Tool Item",
diff --git a/erpnext/accounts/doctype/payment_entry/tests/test_payment_against_invoice.js b/erpnext/accounts/doctype/payment_entry/tests/test_payment_against_invoice.js
deleted file mode 100644
index 4f27b74..0000000
--- a/erpnext/accounts/doctype/payment_entry/tests/test_payment_against_invoice.js
+++ /dev/null
@@ -1,55 +0,0 @@
-QUnit.module('Payment Entry');
-
-QUnit.test("test payment entry", function(assert) {
- assert.expect(6);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Invoice', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'item_code': 'Test Product 1'},
- {'qty': 1},
- {'rate': 101},
- ]
- ]}
- ]);
- },
- () => cur_frm.save(),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Close'),
- () => frappe.timeout(1),
- () => frappe.click_button('Make'),
- () => frappe.timeout(1),
- () => frappe.click_link('Payment'),
- () => frappe.timeout(2),
- () => {
- assert.equal(frappe.get_route()[1], 'Payment Entry',
- 'made payment entry');
- assert.equal(cur_frm.doc.party, 'Test Customer 1',
- 'customer set in payment entry');
- assert.equal(cur_frm.doc.paid_amount, 101,
- 'paid amount set in payment entry');
- assert.equal(cur_frm.doc.references[0].allocated_amount, 101,
- 'amount allocated against sales invoice');
- },
- () => frappe.timeout(1),
- () => cur_frm.set_value('paid_amount', 100),
- () => frappe.timeout(1),
- () => {
- frappe.model.set_value("Payment Entry Reference", cur_frm.doc.references[0].name,
- "allocated_amount", 101);
- },
- () => frappe.timeout(1),
- () => frappe.click_button('Write Off Difference Amount'),
- () => frappe.timeout(1),
- () => {
- assert.equal(cur_frm.doc.difference_amount, 0, 'difference amount is zero');
- assert.equal(cur_frm.doc.deductions[0].amount, 1, 'Write off amount = 1');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/payment_entry/tests/test_payment_against_purchase_invoice.js b/erpnext/accounts/doctype/payment_entry/tests/test_payment_against_purchase_invoice.js
deleted file mode 100644
index e8db2c3..0000000
--- a/erpnext/accounts/doctype/payment_entry/tests/test_payment_against_purchase_invoice.js
+++ /dev/null
@@ -1,60 +0,0 @@
-QUnit.module('Payment Entry');
-
-QUnit.test("test payment entry", function(assert) {
- assert.expect(7 );
- let done = assert.async();
-
- frappe.run_serially([
- () => {
- return frappe.tests.make('Purchase Invoice', [
- {supplier: 'Test Supplier'},
- {bill_no: 'in1234'},
- {items: [
- [
- {'qty': 2},
- {'item_code': 'Test Product 1'},
- {'rate':1000},
- ]
- ]},
- {update_stock:1},
- {supplier_address: 'Test1-Billing'},
- {contact_person: 'Contact 3-Test Supplier'},
- {tc_name: 'Test Term 1'},
- {terms: 'This is just a Test'}
- ]);
- },
-
- () => cur_frm.save(),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(1),
- () => frappe.click_button('Make'),
- () => frappe.timeout(2),
- () => frappe.click_link('Payment'),
- () => frappe.timeout(3),
- () => cur_frm.set_value('mode_of_payment','Cash'),
- () => frappe.timeout(3),
- () => {
- assert.equal(frappe.get_route()[1], 'Payment Entry',
- 'made payment entry');
- assert.equal(cur_frm.doc.party, 'Test Supplier',
- 'supplier set in payment entry');
- assert.equal(cur_frm.doc.paid_amount, 2000,
- 'paid amount set in payment entry');
- assert.equal(cur_frm.doc.references[0].allocated_amount, 2000,
- 'amount allocated against purchase invoice');
- assert.equal(cur_frm.doc.references[0].bill_no, 'in1234',
- 'invoice number allocated against purchase invoice');
- assert.equal(cur_frm.get_field('total_allocated_amount').value, 2000,
- 'correct amount allocated in Write Off');
- assert.equal(cur_frm.get_field('unallocated_amount').value, 0,
- 'correct amount unallocated in Write Off');
- },
-
- () => cur_frm.save(),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(3),
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/payment_entry/tests/test_payment_entry.js b/erpnext/accounts/doctype/payment_entry/tests/test_payment_entry.js
deleted file mode 100644
index 34af79f..0000000
--- a/erpnext/accounts/doctype/payment_entry/tests/test_payment_entry.js
+++ /dev/null
@@ -1,28 +0,0 @@
-QUnit.module('Accounts');
-
-QUnit.test("test payment entry", function(assert) {
- assert.expect(1);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Payment Entry', [
- {payment_type:'Receive'},
- {mode_of_payment:'Cash'},
- {party_type:'Customer'},
- {party:'Test Customer 3'},
- {paid_amount:675},
- {reference_no:123},
- {reference_date: frappe.datetime.add_days(frappe.datetime.nowdate(), 0)},
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.total_allocated_amount==675, "Allocated AmountCorrect");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/payment_entry/tests/test_payment_entry_write_off.js b/erpnext/accounts/doctype/payment_entry/tests/test_payment_entry_write_off.js
deleted file mode 100644
index 8c7f6f4..0000000
--- a/erpnext/accounts/doctype/payment_entry/tests/test_payment_entry_write_off.js
+++ /dev/null
@@ -1,67 +0,0 @@
-QUnit.module('Payment Entry');
-
-QUnit.test("test payment entry", function(assert) {
- assert.expect(8);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Invoice', [
- {customer: 'Test Customer 1'},
- {company: 'For Testing'},
- {currency: 'INR'},
- {selling_price_list: '_Test Price List'},
- {items: [
- [
- {'qty': 1},
- {'item_code': 'Test Product 1'},
- ]
- ]}
- ]);
- },
- () => frappe.timeout(1),
- () => cur_frm.save(),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(1.5),
- () => frappe.click_button('Close'),
- () => frappe.timeout(0.5),
- () => frappe.click_button('Make'),
- () => frappe.timeout(1),
- () => frappe.click_link('Payment'),
- () => frappe.timeout(2),
- () => cur_frm.set_value("paid_to", "_Test Cash - FT"),
- () => frappe.timeout(0.5),
- () => {
- assert.equal(frappe.get_route()[1], 'Payment Entry', 'made payment entry');
- assert.equal(cur_frm.doc.party, 'Test Customer 1', 'customer set in payment entry');
- assert.equal(cur_frm.doc.paid_from, 'Debtors - FT', 'customer account set in payment entry');
- assert.equal(cur_frm.doc.paid_amount, 100, 'paid amount set in payment entry');
- assert.equal(cur_frm.doc.references[0].allocated_amount, 100,
- 'amount allocated against sales invoice');
- },
- () => cur_frm.set_value('paid_amount', 95),
- () => frappe.timeout(1),
- () => {
- frappe.model.set_value("Payment Entry Reference",
- cur_frm.doc.references[0].name, "allocated_amount", 100);
- },
- () => frappe.timeout(.5),
- () => {
- assert.equal(cur_frm.doc.difference_amount, 5, 'difference amount is 5');
- },
- () => {
- frappe.db.set_value("Company", "For Testing", "write_off_account", "_Test Write Off - FT");
- frappe.timeout(1);
- frappe.db.set_value("Company", "For Testing",
- "exchange_gain_loss_account", "_Test Exchange Gain/Loss - FT");
- },
- () => frappe.timeout(1),
- () => frappe.click_button('Write Off Difference Amount'),
- () => frappe.timeout(2),
- () => {
- assert.equal(cur_frm.doc.difference_amount, 0, 'difference amount is zero');
- assert.equal(cur_frm.doc.deductions[0].amount, 5, 'Write off amount = 5');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/pricing_rule/tests/test_pricing_rule.js b/erpnext/accounts/doctype/pricing_rule/tests/test_pricing_rule.js
deleted file mode 100644
index 8279b59..0000000
--- a/erpnext/accounts/doctype/pricing_rule/tests/test_pricing_rule.js
+++ /dev/null
@@ -1,28 +0,0 @@
-QUnit.module('Pricing Rule');
-
-QUnit.test("test pricing rule", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make("Pricing Rule", [
- {title: 'Test Pricing Rule'},
- {item_code:'Test Product 2'},
- {selling:1},
- {applicable_for:'Customer'},
- {customer:'Test Customer 3'},
- {currency: frappe.defaults.get_default("currency")}
- {min_qty:1},
- {max_qty:20},
- {valid_upto: frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {discount_percentage:10},
- {for_price_list:'Standard Selling'}
- ]);
- },
- () => {
- assert.ok(cur_frm.doc.item_code=='Test Product 2');
- assert.ok(cur_frm.doc.customer=='Test Customer 3');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/pricing_rule/tests/test_pricing_rule_with_different_currency.js b/erpnext/accounts/doctype/pricing_rule/tests/test_pricing_rule_with_different_currency.js
deleted file mode 100644
index 4a29956..0000000
--- a/erpnext/accounts/doctype/pricing_rule/tests/test_pricing_rule_with_different_currency.js
+++ /dev/null
@@ -1,58 +0,0 @@
-QUnit.module('Pricing Rule');
-
-QUnit.test("test pricing rule with different currency", function(assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make("Pricing Rule", [
- {title: 'Test Pricing Rule 2'},
- {apply_on: 'Item Code'},
- {item_code:'Test Product 4'},
- {selling:1},
- {priority: 1},
- {min_qty:1},
- {max_qty:20},
- {valid_upto: frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {margin_type: 'Amount'},
- {margin_rate_or_amount: 20},
- {rate_or_discount: 'Rate'},
- {rate:200},
- {currency:'USD'}
-
- ]);
- },
- () => cur_frm.save(),
- () => frappe.timeout(0.3),
- () => {
- assert.ok(cur_frm.doc.item_code=='Test Product 4');
- },
-
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: 'Test Customer 1'},
- {currency: 'INR'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': "Test Product 4"}
- ]
- ]}
- ]);
- },
- () => cur_frm.save(),
- () => frappe.timeout(0.3),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].pricing_rule=='Test Pricing Rule 2', "Pricing rule correct");
- // margin not applied because different currency in pricing rule
- assert.ok(cur_frm.doc.items[0].margin_type==null, "Margin correct");
- },
- () => frappe.timeout(0.3),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/pricing_rule/tests/test_pricing_rule_with_same_currency.js b/erpnext/accounts/doctype/pricing_rule/tests/test_pricing_rule_with_same_currency.js
deleted file mode 100644
index 601ff6b..0000000
--- a/erpnext/accounts/doctype/pricing_rule/tests/test_pricing_rule_with_same_currency.js
+++ /dev/null
@@ -1,56 +0,0 @@
-QUnit.module('Pricing Rule');
-
-QUnit.test("test pricing rule with same currency", function(assert) {
- assert.expect(4);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make("Pricing Rule", [
- {title: 'Test Pricing Rule 1'},
- {apply_on: 'Item Code'},
- {item_code:'Test Product 4'},
- {selling:1},
- {min_qty:1},
- {max_qty:20},
- {valid_upto: frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {rate_or_discount: 'Rate'},
- {rate:200},
- {currency:'USD'}
-
- ]);
- },
- () => cur_frm.save(),
- () => frappe.timeout(0.3),
- () => {
- assert.ok(cur_frm.doc.item_code=='Test Product 4');
- },
-
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: 'Test Customer 1'},
- {currency: 'USD'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': "Test Product 4"}
- ]
- ]}
- ]);
- },
- () => cur_frm.save(),
- () => frappe.timeout(0.3),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].pricing_rule=='Test Pricing Rule 1', "Pricing rule correct");
- assert.ok(cur_frm.doc.items[0].price_list_rate==200, "Item rate correct");
- // get_total
- assert.ok(cur_frm.doc.total== 1000, "Total correct");
- },
- () => frappe.timeout(0.3),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js
deleted file mode 100644
index 94b3b9e..0000000
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.js
+++ /dev/null
@@ -1,74 +0,0 @@
-QUnit.module('Purchase Invoice');
-
-QUnit.test("test purchase invoice", function(assert) {
- assert.expect(9);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Purchase Invoice', [
- {supplier: 'Test Supplier'},
- {bill_no: 'in123'},
- {items: [
- [
- {'qty': 5},
- {'item_code': 'Test Product 1'},
- {'rate':100},
- ]
- ]},
- {update_stock:1},
- {supplier_address: 'Test1-Billing'},
- {contact_person: 'Contact 3-Test Supplier'},
- {taxes_and_charges: 'TEST In State GST - FT'},
- {tc_name: 'Test Term 1'},
- {terms: 'This is Test'},
- {payment_terms_template: '_Test Payment Term Template UI'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- // get tax details
- assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
- // get tax account head details
- assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
- // grand_total Calculated
- assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
-
- assert.ok(cur_frm.doc.payment_terms_template, "Payment Terms Template is correct");
- assert.ok(cur_frm.doc.payment_schedule.length > 0, "Payment Term Schedule is not empty");
-
- },
- () => {
- let date = cur_frm.doc.due_date;
- frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
- frappe.timeout(0.5);
- assert.ok(cur_dialog && cur_dialog.is_visible, 'Message is displayed to user');
- },
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Close'),
- () => frappe.timeout(0.5),
- () => frappe.tests.set_form_values(cur_frm, [{'payment_terms_schedule': ''}]),
- () => {
- let date = cur_frm.doc.due_date;
- frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
- frappe.timeout(0.5);
- assert.ok(cur_dialog && cur_dialog.is_visible, 'Message is displayed to user');
- },
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Close'),
- () => frappe.timeout(0.5),
- () => frappe.tests.set_form_values(cur_frm, [{'payment_schedule': []}]),
- () => {
- let date = cur_frm.doc.due_date;
- frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
- frappe.timeout(0.5);
- assert.ok(!cur_dialog, 'Message is not shown');
- },
- () => cur_frm.save(),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(1),
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.js b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.js
deleted file mode 100644
index 10b05d0..0000000
--- a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.js
+++ /dev/null
@@ -1,28 +0,0 @@
-QUnit.module('Sales Taxes and Charges Template');
-
-QUnit.test("test sales taxes and charges template", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Purchase Taxes and Charges Template', [
- {title: "TEST In State GST"},
- {taxes:[
- [
- {charge_type:"On Net Total"},
- {account_head:"CGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
- ],
- [
- {charge_type:"On Net Total"},
- {account_head:"SGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
- ]
- ]}
- ]);
- },
- () => {
- assert.ok(cur_frm.doc.title=='TEST In State GST');
- assert.ok(cur_frm.doc.name=='TEST In State GST - FT');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js
deleted file mode 100644
index 1c052bd..0000000
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.js
+++ /dev/null
@@ -1,73 +0,0 @@
-QUnit.module('Sales Invoice');
-
-QUnit.test("test sales Invoice", function(assert) {
- assert.expect(9);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Invoice', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'qty': 5},
- {'item_code': 'Test Product 1'},
- ]
- ]},
- {update_stock:1},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {taxes_and_charges: 'TEST In State GST - FT'},
- {tc_name: 'Test Term 1'},
- {terms: 'This is Test'},
- {payment_terms_template: '_Test Payment Term Template UI'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- // get tax details
- assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
- // get tax account head details
- assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
- // grand_total Calculated
- assert.ok(cur_frm.doc.grand_total==590, "Grand Total correct");
-
- assert.ok(cur_frm.doc.payment_terms_template, "Payment Terms Template is correct");
- assert.ok(cur_frm.doc.payment_schedule.length > 0, "Payment Term Schedule is not empty");
-
- },
- () => {
- let date = cur_frm.doc.due_date;
- frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
- frappe.timeout(0.5);
- assert.ok(cur_dialog && cur_dialog.is_visible, 'Message is displayed to user');
- },
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Close'),
- () => frappe.timeout(0.5),
- () => frappe.tests.set_form_values(cur_frm, [{'payment_terms_schedule': ''}]),
- () => {
- let date = cur_frm.doc.due_date;
- frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
- frappe.timeout(0.5);
- assert.ok(cur_dialog && cur_dialog.is_visible, 'Message is displayed to user');
- },
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Close'),
- () => frappe.timeout(0.5),
- () => frappe.tests.set_form_values(cur_frm, [{'payment_schedule': []}]),
- () => {
- let date = cur_frm.doc.due_date;
- frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
- frappe.timeout(0.5);
- assert.ok(!cur_dialog, 'Message is not shown');
- },
- () => cur_frm.save(),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice.js
deleted file mode 100644
index 61d78e1..0000000
--- a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice.js
+++ /dev/null
@@ -1,42 +0,0 @@
-QUnit.module('Sales Invoice');
-
-QUnit.test("test sales Invoice", function(assert) {
- assert.expect(4);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Invoice', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'qty': 5},
- {'item_code': 'Test Product 1'},
- ]
- ]},
- {update_stock:1},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {taxes_and_charges: 'TEST In State GST - FT'},
- {tc_name: 'Test Term 1'},
- {terms: 'This is Test'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- // get tax details
- assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
- // get tax account head details
- assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
- // grand_total Calculated
- assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_margin.js b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_margin.js
deleted file mode 100644
index cf2d0fb..0000000
--- a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_margin.js
+++ /dev/null
@@ -1,35 +0,0 @@
-QUnit.module('Accounts');
-
-QUnit.test("test sales invoice with margin", function(assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Invoice', [
- {customer: 'Test Customer 1'},
- {selling_price_list: 'Test-Selling-USD'},
- {currency: 'USD'},
- {items: [
- [
- {'item_code': 'Test Product 4'},
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 1},
- {'margin_type': 'Percentage'},
- {'margin_rate_or_amount': 20}
- ]
- ]}
- ]);
- },
- () => cur_frm.save(),
- () => {
- assert.ok(cur_frm.doc.items[0].rate_with_margin == 240, "Margin rate correct");
- assert.ok(cur_frm.doc.items[0].base_rate_with_margin == cur_frm.doc.conversion_rate * 240, "Base margin rate correct");
- assert.ok(cur_frm.doc.total == 240, "Amount correct");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment.js b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment.js
deleted file mode 100644
index 45d9a14..0000000
--- a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment.js
+++ /dev/null
@@ -1,56 +0,0 @@
-QUnit.module('Sales Invoice');
-
-QUnit.test("test sales Invoice with payment", function(assert) {
- assert.expect(4);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Invoice', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'qty': 5},
- {'item_code': 'Test Product 1'},
- ]
- ]},
- {update_stock:1},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {taxes_and_charges: 'TEST In State GST - FT'},
- {tc_name: 'Test Term 1'},
- {terms: 'This is Test'},
- {payment_terms_template: '_Test Payment Term Template UI'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- // get tax details
- assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
- // grand_total Calculated
- assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(2),
- () => frappe.tests.click_button('Close'),
- () => frappe.tests.click_button('Make'),
- () => frappe.tests.click_link('Payment'),
- () => frappe.timeout(0.2),
- () => { cur_frm.set_value('mode_of_payment','Cash');},
- () => { cur_frm.set_value('paid_to','Cash - '+frappe.get_abbr(frappe.defaults.get_default('Company')));},
- () => {cur_frm.set_value('reference_no','TEST1234');},
- () => {cur_frm.set_value('reference_date',frappe.datetime.add_days(frappe.datetime.nowdate(), 0));},
- () => cur_frm.save(),
- () => {
- // get payment details
- assert.ok(cur_frm.doc.paid_amount==590, "Paid Amount Correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment_request.js b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment_request.js
deleted file mode 100644
index 0464e45..0000000
--- a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_payment_request.js
+++ /dev/null
@@ -1,51 +0,0 @@
-QUnit.module('Sales Invoice');
-
-QUnit.test("test sales Invoice with payment request", function(assert) {
- assert.expect(4);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Invoice', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'qty': 5},
- {'item_code': 'Test Product 1'},
- ]
- ]},
- {update_stock:1},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {taxes_and_charges: 'TEST In State GST - FT'},
- {tc_name: 'Test Term 1'},
- {terms: 'This is Test'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- // get tax details
- assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
- // grand_total Calculated
- assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(2),
- () => frappe.tests.click_button('Close'),
- () => frappe.tests.click_button('Make'),
- () => frappe.tests.click_link('Payment Request'),
- () => frappe.timeout(0.2),
- () => { cur_frm.set_value('print_format','GST Tax Invoice');},
- () => { cur_frm.set_value('email_to','test@gmail.com');},
- () => cur_frm.save(),
- () => {
- // get payment details
- assert.ok(cur_frm.doc.grand_total==590, "grand total Correct");
- },
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_serialize_item.js b/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_serialize_item.js
deleted file mode 100644
index af484d7..0000000
--- a/erpnext/accounts/doctype/sales_invoice/tests/test_sales_invoice_with_serialize_item.js
+++ /dev/null
@@ -1,44 +0,0 @@
-QUnit.module('Sales Invoice');
-
-QUnit.test("test sales Invoice with serialize item", function(assert) {
- assert.expect(5);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Invoice', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'qty': 2},
- {'item_code': 'Test Product 4'},
- ]
- ]},
- {update_stock:1},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {taxes_and_charges: 'TEST In State GST - FT'},
- {tc_name: 'Test Term 1'},
- {terms: 'This is Test'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- // get tax details
- assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
- // get tax account head details
- assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
- // get batch number
- assert.ok(cur_frm.doc.items[0].batch_no=='TEST-BATCH-001', " Batch Details correct");
- // grand_total Calculated
- assert.ok(cur_frm.doc.grand_total==218, "Grad Total correct");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_sales_taxes_and_charges_template.js b/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_sales_taxes_and_charges_template.js
deleted file mode 100644
index 8cd42f6..0000000
--- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/test_sales_taxes_and_charges_template.js
+++ /dev/null
@@ -1,28 +0,0 @@
-QUnit.module('Sales Taxes and Charges Template');
-
-QUnit.test("test sales taxes and charges template", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Taxes and Charges Template', [
- {title: "TEST In State GST"},
- {taxes:[
- [
- {charge_type:"On Net Total"},
- {account_head:"CGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
- ],
- [
- {charge_type:"On Net Total"},
- {account_head:"SGST - "+frappe.get_abbr(frappe.defaults.get_default("Company")) }
- ]
- ]}
- ]);
- },
- () => {
- assert.ok(cur_frm.doc.title=='TEST In State GST');
- assert.ok(cur_frm.doc.name=='TEST In State GST - FT');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.js b/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.js
deleted file mode 100644
index 63ea1bf..0000000
--- a/erpnext/accounts/doctype/shipping_rule/test_shipping_rule.js
+++ /dev/null
@@ -1,36 +0,0 @@
-QUnit.module('Shipping Rule');
-
-QUnit.test("test Shipping Rule", function(assert) {
- assert.expect(1);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make("Shipping Rule", [
- {label: "Next Day Shipping"},
- {shipping_rule_type: "Selling"},
- {calculate_based_on: 'Net Total'},
- {conditions:[
- [
- {from_value:1},
- {to_value:200},
- {shipping_amount:100}
- ],
- [
- {from_value:201},
- {to_value:2000},
- {shipping_amount:50}
- ],
- ]},
- {countries:[
- [
- {country:'India'}
- ]
- ]},
- {account:'Accounts Payable - '+frappe.get_abbr(frappe.defaults.get_default("Company"))},
- {cost_center:'Main - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ]);
- },
- () => {assert.ok(cur_frm.doc.name=='Next Day Shipping');},
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/shipping_rule/tests/test_shipping_rule_for_buying.js b/erpnext/accounts/doctype/shipping_rule/tests/test_shipping_rule_for_buying.js
deleted file mode 100644
index f3668b8..0000000
--- a/erpnext/accounts/doctype/shipping_rule/tests/test_shipping_rule_for_buying.js
+++ /dev/null
@@ -1,36 +0,0 @@
-QUnit.module('Shipping Rule');
-
-QUnit.test("test Shipping Rule", function(assert) {
- assert.expect(1);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make("Shipping Rule", [
- {label: "Two Day Shipping"},
- {shipping_rule_type: "Buying"},
- {fixed_shipping_amount: 0},
- {conditions:[
- [
- {from_value:1},
- {to_value:200},
- {shipping_amount:100}
- ],
- [
- {from_value:201},
- {to_value:3000},
- {shipping_amount:200}
- ],
- ]},
- {countries:[
- [
- {country:'India'}
- ]
- ]},
- {account:'Accounts Payable - '+frappe.get_abbr(frappe.defaults.get_default("Company"))},
- {cost_center:'Main - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ]);
- },
- () => {assert.ok(cur_frm.doc.name=='Two Day Shipping');},
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py
index 1dae87f..467d4a1 100644
--- a/erpnext/accounts/doctype/subscription/subscription.py
+++ b/erpnext/accounts/doctype/subscription/subscription.py
@@ -23,6 +23,7 @@
get_accounting_dimensions,
)
from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate
+from erpnext.accounts.party import get_party_account_currency
class Subscription(Document):
@@ -355,6 +356,9 @@
if frappe.db.get_value('Supplier', self.party, 'tax_withholding_category'):
invoice.apply_tds = 1
+ ### Add party currency to invoice
+ invoice.currency = get_party_account_currency(self.party_type, self.party, self.company)
+
## Add dimensions in invoice for subscription:
accounting_dimensions = get_accounting_dimensions()
diff --git a/erpnext/accounts/doctype/subscription/test_subscription.js b/erpnext/accounts/doctype/subscription/test_subscription.js
deleted file mode 100644
index 2872a21..0000000
--- a/erpnext/accounts/doctype/subscription/test_subscription.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Subscription", function (assert) {
- assert.expect(4);
- let done = assert.async();
- frappe.run_serially([
- // insert a new Subscription
- () => {
- return frappe.tests.make("Subscription", [
- {reference_doctype: 'Sales Invoice'},
- {reference_document: 'SINV-00004'},
- {start_date: frappe.datetime.month_start()},
- {end_date: frappe.datetime.month_end()},
- {frequency: 'Weekly'}
- ]);
- },
- () => cur_frm.savesubmit(),
- () => frappe.timeout(1),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(2),
- () => {
- assert.ok(cur_frm.doc.frequency.includes("Weekly"), "Set frequency Weekly");
- assert.ok(cur_frm.doc.reference_doctype.includes("Sales Invoice"), "Set base doctype Sales Invoice");
- assert.equal(cur_frm.doc.docstatus, 1, "Submitted subscription");
- assert.equal(cur_frm.doc.next_schedule_date,
- frappe.datetime.add_days(frappe.datetime.get_today(), 7), "Set schedule date");
- },
- () => done()
- ]);
-});
diff --git a/erpnext/accounts/doctype/subscription/test_subscription.py b/erpnext/accounts/doctype/subscription/test_subscription.py
index 9dd370b..6f67bc5 100644
--- a/erpnext/accounts/doctype/subscription/test_subscription.py
+++ b/erpnext/accounts/doctype/subscription/test_subscription.py
@@ -60,15 +60,38 @@
plan.billing_interval_count = 3
plan.insert()
+ if not frappe.db.exists('Subscription Plan', '_Test Plan Multicurrency'):
+ plan = frappe.new_doc('Subscription Plan')
+ plan.plan_name = '_Test Plan Multicurrency'
+ plan.item = '_Test Non Stock Item'
+ plan.price_determination = "Fixed Rate"
+ plan.cost = 50
+ plan.currency = 'USD'
+ plan.billing_interval = 'Month'
+ plan.billing_interval_count = 1
+ plan.insert()
+
+def create_parties():
if not frappe.db.exists('Supplier', '_Test Supplier'):
supplier = frappe.new_doc('Supplier')
supplier.supplier_name = '_Test Supplier'
supplier.supplier_group = 'All Supplier Groups'
supplier.insert()
+ if not frappe.db.exists('Customer', '_Test Subscription Customer'):
+ customer = frappe.new_doc('Customer')
+ customer.customer_name = '_Test Subscription Customer'
+ customer.billing_currency = 'USD'
+ customer.append('accounts', {
+ 'company': '_Test Company',
+ 'account': '_Test Receivable USD - _TC'
+ })
+ customer.insert()
+
class TestSubscription(unittest.TestCase):
def setUp(self):
create_plan()
+ create_parties()
def test_create_subscription_with_trial_with_correct_period(self):
subscription = frappe.new_doc('Subscription')
@@ -637,3 +660,22 @@
subscription.process()
self.assertEqual(len(subscription.invoices), 1)
+
+ def test_multicurrency_subscription(self):
+ subscription = frappe.new_doc('Subscription')
+ subscription.party_type = 'Customer'
+ subscription.party = '_Test Subscription Customer'
+ subscription.generate_invoice_at_period_start = 1
+ subscription.company = '_Test Company'
+ # select subscription start date as '2018-01-15'
+ subscription.start_date = '2018-01-01'
+ subscription.append('plans', {'plan': '_Test Plan Multicurrency', 'qty': 1})
+ subscription.save()
+
+ subscription.process()
+ self.assertEqual(len(subscription.invoices), 1)
+ self.assertEqual(subscription.status, 'Unpaid')
+
+ # Check the currency of the created invoice
+ currency = frappe.db.get_value('Sales Invoice', subscription.invoices[0].invoice, 'currency')
+ self.assertEqual(currency, 'USD')
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json
index 878ae09..563df79 100644
--- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json
+++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json
@@ -75,7 +75,8 @@
"fieldname": "cost",
"fieldtype": "Currency",
"in_list_view": 1,
- "label": "Cost"
+ "label": "Cost",
+ "options": "currency"
},
{
"depends_on": "eval:doc.price_determination==\"Based On Price List\"",
@@ -147,7 +148,7 @@
}
],
"links": [],
- "modified": "2021-08-13 10:53:44.205774",
+ "modified": "2021-12-10 15:24:15.794477",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Subscription Plan",
diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
index 01799d5..758e3e9 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
@@ -370,7 +370,7 @@
accounts = get_accounts(root_type, filters)
if not accounts:
- return None, None
+ return None, None, None
accounts = update_parent_account_names(accounts)
diff --git a/erpnext/accounts/report/deferred_revenue_and_expense/__init__.py b/erpnext/accounts/report/deferred_revenue_and_expense/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/report/deferred_revenue_and_expense/__init__.py
diff --git a/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.js b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.js
new file mode 100644
index 0000000..0056b9e
--- /dev/null
+++ b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.js
@@ -0,0 +1,114 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+function get_filters() {
+ let filters = [
+ {
+ "fieldname":"company",
+ "label": __("Company"),
+ "fieldtype": "Link",
+ "options": "Company",
+ "default": frappe.defaults.get_user_default("Company"),
+ "reqd": 1
+ },
+ {
+ "fieldname":"filter_based_on",
+ "label": __("Filter Based On"),
+ "fieldtype": "Select",
+ "options": ["Fiscal Year", "Date Range"],
+ "default": ["Fiscal Year"],
+ "reqd": 1,
+ on_change: function() {
+ let filter_based_on = frappe.query_report.get_filter_value('filter_based_on');
+ frappe.query_report.toggle_filter_display('from_fiscal_year', filter_based_on === 'Date Range');
+ frappe.query_report.toggle_filter_display('to_fiscal_year', filter_based_on === 'Date Range');
+ frappe.query_report.toggle_filter_display('period_start_date', filter_based_on === 'Fiscal Year');
+ frappe.query_report.toggle_filter_display('period_end_date', filter_based_on === 'Fiscal Year');
+
+ frappe.query_report.refresh();
+ }
+ },
+ {
+ "fieldname":"period_start_date",
+ "label": __("Start Date"),
+ "fieldtype": "Date",
+ "hidden": 1,
+ "reqd": 1
+ },
+ {
+ "fieldname":"period_end_date",
+ "label": __("End Date"),
+ "fieldtype": "Date",
+ "hidden": 1,
+ "reqd": 1
+ },
+ {
+ "fieldname":"from_fiscal_year",
+ "label": __("Start Year"),
+ "fieldtype": "Link",
+ "options": "Fiscal Year",
+ "default": frappe.defaults.get_user_default("fiscal_year"),
+ "reqd": 1
+ },
+ {
+ "fieldname":"to_fiscal_year",
+ "label": __("End Year"),
+ "fieldtype": "Link",
+ "options": "Fiscal Year",
+ "default": frappe.defaults.get_user_default("fiscal_year"),
+ "reqd": 1
+ },
+ {
+ "fieldname": "periodicity",
+ "label": __("Periodicity"),
+ "fieldtype": "Select",
+ "options": [
+ { "value": "Monthly", "label": __("Monthly") },
+ { "value": "Quarterly", "label": __("Quarterly") },
+ { "value": "Half-Yearly", "label": __("Half-Yearly") },
+ { "value": "Yearly", "label": __("Yearly") }
+ ],
+ "default": "Monthly",
+ "reqd": 1
+ },
+ {
+ "fieldname": "type",
+ "label": __("Invoice Type"),
+ "fieldtype": "Select",
+ "options": [
+ { "value": "Revenue", "label": __("Revenue") },
+ { "value": "Expense", "label": __("Expense") }
+ ],
+ "default": "Revenue",
+ "reqd": 1
+ },
+ {
+ "fieldname" : "with_upcoming_postings",
+ "label": __("Show with upcoming revenue/expense"),
+ "fieldtype": "Check",
+ "default": 1
+ }
+ ]
+
+ return filters;
+}
+
+frappe.query_reports["Deferred Revenue and Expense"] = {
+ "filters": get_filters(),
+ "formatter": function(value, row, column, data, default_formatter){
+ return default_formatter(value, row, column, data);
+ },
+ onload: function(report){
+ let fiscal_year = frappe.defaults.get_user_default("fiscal_year");
+
+ frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
+ var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
+ frappe.query_report.set_filter_value({
+ period_start_date: fy.year_start_date,
+ period_end_date: fy.year_end_date
+ });
+ });
+ }
+};
+
diff --git a/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.json b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.json
new file mode 100644
index 0000000..c7dfb3b
--- /dev/null
+++ b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.json
@@ -0,0 +1,32 @@
+{
+ "add_total_row": 0,
+ "columns": [],
+ "creation": "2021-12-10 19:27:14.654220",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2021-12-10 19:27:14.654220",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Deferred Revenue and Expense",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "GL Entry",
+ "report_name": "Deferred Revenue and Expense",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "Accounts User"
+ },
+ {
+ "role": "Accounts Manager"
+ },
+ {
+ "role": "Auditor"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py
new file mode 100644
index 0000000..a4842c1
--- /dev/null
+++ b/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py
@@ -0,0 +1,440 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# License: MIT. See LICENSE
+
+import frappe
+from frappe import _, qb
+from frappe.query_builder import Column, functions
+from frappe.utils import add_days, date_diff, flt, get_first_day, get_last_day, rounded
+
+from erpnext.accounts.report.financial_statements import get_period_list
+
+
+class Deferred_Item(object):
+ """
+ Helper class for processing items with deferred revenue/expense
+ """
+
+ def __init__(self, item, inv, gle_entries):
+ self.name = item
+ self.parent = inv.name
+ self.item_name = gle_entries[0].item_name
+ self.service_start_date = gle_entries[0].service_start_date
+ self.service_end_date = gle_entries[0].service_end_date
+ self.base_net_amount = gle_entries[0].base_net_amount
+ self.filters = inv.filters
+ self.period_list = inv.period_list
+
+ if gle_entries[0].deferred_revenue_account:
+ self.type = "Deferred Sale Item"
+ self.deferred_account = gle_entries[0].deferred_revenue_account
+ elif gle_entries[0].deferred_expense_account:
+ self.type = "Deferred Purchase Item"
+ self.deferred_account = gle_entries[0].deferred_expense_account
+
+ self.gle_entries = []
+ # holds period wise total for item
+ self.period_total = []
+ self.last_entry_date = self.service_start_date
+
+ if gle_entries:
+ self.gle_entries = gle_entries
+ for x in self.gle_entries:
+ if self.get_amount(x):
+ self.last_entry_date = x.gle_posting_date
+
+ def report_data(self):
+ """
+ Generate report data for output
+ """
+ ret_data = frappe._dict({"name": self.item_name})
+ for period in self.period_total:
+ ret_data[period.key] = period.total
+ ret_data.indent = 1
+ return ret_data
+
+ def get_amount(self, entry):
+ """
+ For a given GL/Journal posting, get balance based on item type
+ """
+ if self.type == "Deferred Sale Item":
+ return entry.debit - entry.credit
+ elif self.type == "Deferred Purchase Item":
+ return -(entry.credit - entry.debit)
+ return 0
+
+ def get_item_total(self):
+ """
+ Helper method - calculate booked amount. Includes simulated postings as well
+ """
+ total = 0
+ for gle_posting in self.gle_entries:
+ total += self.get_amount(gle_posting)
+
+ return total
+
+ def calculate_amount(self, start_date, end_date):
+ """
+ start_date, end_date - datetime.datetime.date
+ return - estimated amount to post for given period
+ Calculated based on already booked amount and item service period
+ """
+ total_months = (
+ (self.service_end_date.year - self.service_start_date.year) * 12
+ + (self.service_end_date.month - self.service_start_date.month)
+ + 1
+ )
+
+ prorate = date_diff(self.service_end_date, self.service_start_date) / date_diff(
+ get_last_day(self.service_end_date), get_first_day(self.service_start_date)
+ )
+
+ actual_months = rounded(total_months * prorate, 1)
+
+ already_booked_amount = self.get_item_total()
+ base_amount = self.base_net_amount / actual_months
+
+ if base_amount + already_booked_amount > self.base_net_amount:
+ base_amount = self.base_net_amount - already_booked_amount
+
+ if not (get_first_day(start_date) == start_date and get_last_day(end_date) == end_date):
+ partial_month = flt(date_diff(end_date, start_date)) / flt(
+ date_diff(get_last_day(end_date), get_first_day(start_date))
+ )
+ base_amount *= rounded(partial_month, 1)
+
+ return base_amount
+
+ def make_dummy_gle(self, name, date, amount):
+ """
+ return - frappe._dict() of a dummy gle entry
+ """
+ entry = frappe._dict(
+ {"name": name, "gle_posting_date": date, "debit": 0, "credit": 0, "posted": "not"}
+ )
+ if self.type == "Deferred Sale Item":
+ entry.debit = amount
+ elif self.type == "Deferred Purchase Item":
+ entry.credit = amount
+ return entry
+
+ def simulate_future_posting(self):
+ """
+ simulate future posting by creating dummy gl entries. starts from the last posting date.
+ """
+ if add_days(self.last_entry_date, 1) < self.period_list[-1].to_date:
+ self.estimate_for_period_list = get_period_list(
+ self.filters.from_fiscal_year,
+ self.filters.to_fiscal_year,
+ add_days(self.last_entry_date, 1),
+ self.period_list[-1].to_date,
+ "Date Range",
+ "Monthly",
+ company=self.filters.company,
+ )
+ for period in self.estimate_for_period_list:
+ amount = self.calculate_amount(period.from_date, period.to_date)
+ gle = self.make_dummy_gle(period.key, period.to_date, amount)
+ self.gle_entries.append(gle)
+
+ def calculate_item_revenue_expense_for_period(self):
+ """
+ calculate item postings for each period and update period_total list
+ """
+ for period in self.period_list:
+ period_sum = 0
+ actual = 0
+ for posting in self.gle_entries:
+ # if period.from_date <= posting.posting_date <= period.to_date:
+ if period.from_date <= posting.gle_posting_date <= period.to_date:
+ period_sum += self.get_amount(posting)
+ if posting.posted == "posted":
+ actual += self.get_amount(posting)
+
+ self.period_total.append(
+ frappe._dict({"key": period.key, "total": period_sum, "actual": actual})
+ )
+ return self.period_total
+
+
+class Deferred_Invoice(object):
+ def __init__(self, invoice, items, filters, period_list):
+ """
+ Helper class for processing invoices with deferred revenue/expense items
+ invoice - string : invoice name
+ items - list : frappe._dict() with item details. Refer Deferred_Item for required fields
+ """
+ self.name = invoice
+ self.posting_date = items[0].posting_date
+ self.filters = filters
+ self.period_list = period_list
+ # holds period wise total for invoice
+ self.period_total = []
+
+ if items[0].deferred_revenue_account:
+ self.type = "Sales"
+ elif items[0].deferred_expense_account:
+ self.type = "Purchase"
+
+ self.items = []
+ # for each uniq items
+ self.uniq_items = set([x.item for x in items])
+ for item in self.uniq_items:
+ self.items.append(Deferred_Item(item, self, [x for x in items if x.item == item]))
+
+ def calculate_invoice_revenue_expense_for_period(self):
+ """
+ calculate deferred revenue/expense for all items in invoice
+ """
+ # initialize period_total list for invoice
+ for period in self.period_list:
+ self.period_total.append(frappe._dict({"key": period.key, "total": 0, "actual": 0}))
+
+ for item in self.items:
+ item_total = item.calculate_item_revenue_expense_for_period()
+ # update invoice total
+ for idx, period in enumerate(self.period_list, 0):
+ self.period_total[idx].total += item_total[idx].total
+ self.period_total[idx].actual += item_total[idx].actual
+ return self.period_total
+
+ def estimate_future(self):
+ """
+ create dummy GL entries for upcoming months for all items in invoice
+ """
+ [item.simulate_future_posting() for item in self.items]
+
+ def report_data(self):
+ """
+ generate report data for invoice, includes invoice total
+ """
+ ret_data = []
+ inv_total = frappe._dict({"name": self.name})
+ for x in self.period_total:
+ inv_total[x.key] = x.total
+ inv_total.indent = 0
+ ret_data.append(inv_total)
+ list(map(lambda item: ret_data.append(item.report_data()), self.items))
+ return ret_data
+
+
+class Deferred_Revenue_and_Expense_Report(object):
+ def __init__(self, filters=None):
+ """
+ Initialize deferred revenue/expense report with user provided filters or system defaults, if none is provided
+ """
+
+ # If no filters are provided, get user defaults
+ if not filters:
+ fiscal_year = frappe.get_doc("Fiscal Year", frappe.defaults.get_user_default("fiscal_year"))
+ self.filters = frappe._dict(
+ {
+ "company": frappe.defaults.get_user_default("Company"),
+ "filter_based_on": "Fiscal Year",
+ "period_start_date": fiscal_year.year_start_date,
+ "period_end_date": fiscal_year.year_end_date,
+ "from_fiscal_year": fiscal_year.year,
+ "to_fiscal_year": fiscal_year.year,
+ "periodicity": "Monthly",
+ "type": "Revenue",
+ "with_upcoming_postings": True,
+ }
+ )
+ else:
+ self.filters = frappe._dict(filters)
+
+ self.period_list = None
+ self.deferred_invoices = []
+ # holds period wise total for report
+ self.period_total = []
+
+ def get_period_list(self):
+ """
+ Figure out selected period based on filters
+ """
+ self.period_list = get_period_list(
+ self.filters.from_fiscal_year,
+ self.filters.to_fiscal_year,
+ self.filters.period_start_date,
+ self.filters.period_end_date,
+ self.filters.filter_based_on,
+ self.filters.periodicity,
+ company=self.filters.company,
+ )
+
+ def get_invoices(self):
+ """
+ Get all sales and purchase invoices which has deferred revenue/expense items
+ """
+ gle = qb.DocType("GL Entry")
+ # column doesn't have an alias option
+ posted = Column("posted")
+
+ if self.filters.type == "Revenue":
+ inv = qb.DocType("Sales Invoice")
+ inv_item = qb.DocType("Sales Invoice Item")
+ deferred_flag_field = inv_item["enable_deferred_revenue"]
+ deferred_account_field = inv_item["deferred_revenue_account"]
+
+ elif self.filters.type == "Expense":
+ inv = qb.DocType("Purchase Invoice")
+ inv_item = qb.DocType("Purchase Invoice Item")
+ deferred_flag_field = inv_item["enable_deferred_expense"]
+ deferred_account_field = inv_item["deferred_expense_account"]
+
+ query = (
+ qb.from_(inv_item)
+ .join(inv)
+ .on(inv.name == inv_item.parent)
+ .join(gle)
+ .on((inv_item.name == gle.voucher_detail_no) & (deferred_account_field == gle.account))
+ .select(
+ inv.name.as_("doc"),
+ inv.posting_date,
+ inv_item.name.as_("item"),
+ inv_item.item_name,
+ inv_item.service_start_date,
+ inv_item.service_end_date,
+ inv_item.base_net_amount,
+ deferred_account_field,
+ gle.posting_date.as_("gle_posting_date"),
+ functions.Sum(gle.debit).as_("debit"),
+ functions.Sum(gle.credit).as_("credit"),
+ posted,
+ )
+ .where(
+ (inv.docstatus == 1)
+ & (deferred_flag_field == 1)
+ & (
+ (
+ (self.period_list[0].from_date >= inv_item.service_start_date)
+ & (inv_item.service_end_date >= self.period_list[0].from_date)
+ )
+ | (
+ (inv_item.service_start_date >= self.period_list[0].from_date)
+ & (inv_item.service_start_date <= self.period_list[-1].to_date)
+ )
+ )
+ )
+ .groupby(inv.name, inv_item.name, gle.posting_date)
+ .orderby(gle.posting_date)
+ )
+ self.invoices = query.run(as_dict=True)
+
+ uniq_invoice = set([x.doc for x in self.invoices])
+ for inv in uniq_invoice:
+ self.deferred_invoices.append(
+ Deferred_Invoice(
+ inv, [x for x in self.invoices if x.doc == inv], self.filters, self.period_list
+ )
+ )
+
+ def estimate_future(self):
+ """
+ For all Invoices estimate upcoming postings
+ """
+ for x in self.deferred_invoices:
+ x.estimate_future()
+
+ def calculate_revenue_and_expense(self):
+ """
+ calculate the deferred revenue/expense for all invoices
+ """
+ # initialize period_total list for report
+ for period in self.period_list:
+ self.period_total.append(frappe._dict({"key": period.key, "total": 0, "actual": 0}))
+
+ for inv in self.deferred_invoices:
+ inv_total = inv.calculate_invoice_revenue_expense_for_period()
+ # calculate total for whole report
+ for idx, period in enumerate(self.period_list, 0):
+ self.period_total[idx].total += inv_total[idx].total
+ self.period_total[idx].actual += inv_total[idx].actual
+
+ def get_columns(self):
+ columns = []
+ columns.append({"label": _("Name"), "fieldname": "name", "fieldtype": "Data", "read_only": 1})
+ for period in self.period_list:
+ columns.append(
+ {
+ "label": _(period.label),
+ "fieldname": period.key,
+ "fieldtype": "Currency",
+ "read_only": 1,
+ })
+ return columns
+
+ def generate_report_data(self):
+ """
+ Generate report data for all invoices. Adds total rows for revenue and expense
+ """
+ ret = []
+
+ for inv in self.deferred_invoices:
+ ret += inv.report_data()
+
+ # empty row for padding
+ ret += [{}]
+
+ # add total row
+ if ret is not []:
+ if self.filters.type == "Revenue":
+ total_row = frappe._dict({"name": "Total Deferred Income"})
+ elif self.filters.type == "Expense":
+ total_row = frappe._dict({"name": "Total Deferred Expense"})
+
+ for idx, period in enumerate(self.period_list, 0):
+ total_row[period.key] = self.period_total[idx].total
+ ret.append(total_row)
+
+ return ret
+
+ def prepare_chart(self):
+ chart = {
+ "data": {
+ "labels": [period.label for period in self.period_list],
+ "datasets": [
+ {
+ "name": "Actual Posting",
+ "chartType": "bar",
+ "values": [x.actual for x in self.period_total],
+ }
+ ],
+ },
+ "type": "axis-mixed",
+ "height": 500,
+ "axisOptions": {"xAxisMode": "Tick", "xIsSeries": True},
+ "barOptions": {"stacked": False, "spaceRatio": 0.5},
+ }
+
+ if self.filters.with_upcoming_postings:
+ chart["data"]["datasets"].append({
+ "name": "Expected",
+ "chartType": "line",
+ "values": [x.total for x in self.period_total]
+ })
+
+ return chart
+
+ def run(self, *args, **kwargs):
+ """
+ Run report and generate data
+ """
+ self.deferred_invoices.clear()
+ self.get_period_list()
+ self.get_invoices()
+
+ if self.filters.with_upcoming_postings:
+ self.estimate_future()
+ self.calculate_revenue_and_expense()
+
+
+def execute(filters=None):
+ report = Deferred_Revenue_and_Expense_Report(filters=filters)
+ report.run()
+
+ columns = report.get_columns()
+ data = report.generate_report_data()
+ message = []
+ chart = report.prepare_chart()
+
+ return columns, data, message, chart
diff --git a/erpnext/accounts/report/deferred_revenue_and_expense/test_deferred_revenue_and_expense.py b/erpnext/accounts/report/deferred_revenue_and_expense/test_deferred_revenue_and_expense.py
new file mode 100644
index 0000000..1de6fb6
--- /dev/null
+++ b/erpnext/accounts/report/deferred_revenue_and_expense/test_deferred_revenue_and_expense.py
@@ -0,0 +1,253 @@
+import unittest
+
+import frappe
+from frappe import qb
+from frappe.utils import nowdate
+
+from erpnext.accounts.doctype.account.test_account import create_account
+from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
+from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
+from erpnext.accounts.report.deferred_revenue_and_expense.deferred_revenue_and_expense import (
+ Deferred_Revenue_and_Expense_Report,
+)
+from erpnext.buying.doctype.supplier.test_supplier import create_supplier
+from erpnext.stock.doctype.item.test_item import create_item
+
+
+class TestDeferredRevenueAndExpense(unittest.TestCase):
+ @classmethod
+ def setUpClass(self):
+ clear_old_entries()
+ create_company()
+
+ def test_deferred_revenue(self):
+ # created deferred expense accounts, if not found
+ deferred_revenue_account = create_account(
+ account_name="Deferred Revenue",
+ parent_account="Current Liabilities - _CD",
+ company="_Test Company DR",
+ )
+
+ acc_settings = frappe.get_doc("Accounts Settings", "Accounts Settings")
+ acc_settings.book_deferred_entries_based_on = "Months"
+ acc_settings.save()
+
+ customer = frappe.new_doc("Customer")
+ customer.customer_name = "_Test Customer DR"
+ customer.type = "Individual"
+ customer.insert()
+
+ item = create_item(
+ "_Test Internet Subscription",
+ is_stock_item=0,
+ warehouse="All Warehouses - _CD",
+ company="_Test Company DR",
+ )
+ item.enable_deferred_revenue = 1
+ item.deferred_revenue_account = deferred_revenue_account
+ item.no_of_months = 3
+ item.save()
+
+ si = create_sales_invoice(
+ item=item.name,
+ company="_Test Company DR",
+ customer="_Test Customer DR",
+ debit_to="Debtors - _CD",
+ posting_date="2021-05-01",
+ parent_cost_center="Main - _CD",
+ cost_center="Main - _CD",
+ do_not_submit=True,
+ rate=300,
+ price_list_rate=300,
+ )
+ si.items[0].enable_deferred_revenue = 1
+ si.items[0].service_start_date = "2021-05-01"
+ si.items[0].service_end_date = "2021-08-01"
+ si.items[0].deferred_revenue_account = deferred_revenue_account
+ si.items[0].income_account = "Sales - _CD"
+ si.save()
+ si.submit()
+
+ pda = frappe.get_doc(
+ dict(
+ doctype="Process Deferred Accounting",
+ posting_date=nowdate(),
+ start_date="2021-05-01",
+ end_date="2021-08-01",
+ type="Income",
+ company="_Test Company DR",
+ )
+ )
+ pda.insert()
+ pda.submit()
+
+ # execute report
+ fiscal_year = frappe.get_doc("Fiscal Year", frappe.defaults.get_user_default("fiscal_year"))
+ self.filters = frappe._dict(
+ {
+ "company": frappe.defaults.get_user_default("Company"),
+ "filter_based_on": "Date Range",
+ "period_start_date": "2021-05-01",
+ "period_end_date": "2021-08-01",
+ "from_fiscal_year": fiscal_year.year,
+ "to_fiscal_year": fiscal_year.year,
+ "periodicity": "Monthly",
+ "type": "Revenue",
+ "with_upcoming_postings": False,
+ }
+ )
+
+ report = Deferred_Revenue_and_Expense_Report(filters=self.filters)
+ report.run()
+ expected = [
+ {"key": "may_2021", "total": 100.0, "actual": 100.0},
+ {"key": "jun_2021", "total": 100.0, "actual": 100.0},
+ {"key": "jul_2021", "total": 100.0, "actual": 100.0},
+ {"key": "aug_2021", "total": 0, "actual": 0},
+ ]
+ self.assertEqual(report.period_total, expected)
+
+ def test_deferred_expense(self):
+ # created deferred expense accounts, if not found
+ deferred_expense_account = create_account(
+ account_name="Deferred Expense",
+ parent_account="Current Assets - _CD",
+ company="_Test Company DR",
+ )
+
+ acc_settings = frappe.get_doc("Accounts Settings", "Accounts Settings")
+ acc_settings.book_deferred_entries_based_on = "Months"
+ acc_settings.save()
+
+ supplier = create_supplier(
+ supplier_name="_Test Furniture Supplier", supplier_group="Local", supplier_type="Company"
+ )
+ supplier.save()
+
+ item = create_item(
+ "_Test Office Desk",
+ is_stock_item=0,
+ warehouse="All Warehouses - _CD",
+ company="_Test Company DR",
+ )
+ item.enable_deferred_expense = 1
+ item.deferred_expense_account = deferred_expense_account
+ item.no_of_months_exp = 3
+ item.save()
+
+ pi = make_purchase_invoice(
+ item=item.name,
+ company="_Test Company DR",
+ supplier="_Test Furniture Supplier",
+ is_return=False,
+ update_stock=False,
+ posting_date=frappe.utils.datetime.date(2021, 5, 1),
+ parent_cost_center="Main - _CD",
+ cost_center="Main - _CD",
+ do_not_save=True,
+ rate=300,
+ price_list_rate=300,
+ warehouse="All Warehouses - _CD",
+ qty=1,
+ )
+ pi.set_posting_time = True
+ pi.items[0].enable_deferred_expense = 1
+ pi.items[0].service_start_date = "2021-05-01"
+ pi.items[0].service_end_date = "2021-08-01"
+ pi.items[0].deferred_expense_account = deferred_expense_account
+ pi.items[0].expense_account = "Office Maintenance Expenses - _CD"
+ pi.save()
+ pi.submit()
+
+ pda = frappe.get_doc(
+ dict(
+ doctype="Process Deferred Accounting",
+ posting_date=nowdate(),
+ start_date="2021-05-01",
+ end_date="2021-08-01",
+ type="Expense",
+ company="_Test Company DR",
+ )
+ )
+ pda.insert()
+ pda.submit()
+
+ # execute report
+ fiscal_year = frappe.get_doc("Fiscal Year", frappe.defaults.get_user_default("fiscal_year"))
+ self.filters = frappe._dict(
+ {
+ "company": frappe.defaults.get_user_default("Company"),
+ "filter_based_on": "Date Range",
+ "period_start_date": "2021-05-01",
+ "period_end_date": "2021-08-01",
+ "from_fiscal_year": fiscal_year.year,
+ "to_fiscal_year": fiscal_year.year,
+ "periodicity": "Monthly",
+ "type": "Expense",
+ "with_upcoming_postings": False,
+ }
+ )
+
+ report = Deferred_Revenue_and_Expense_Report(filters=self.filters)
+ report.run()
+ expected = [
+ {"key": "may_2021", "total": -100.0, "actual": -100.0},
+ {"key": "jun_2021", "total": -100.0, "actual": -100.0},
+ {"key": "jul_2021", "total": -100.0, "actual": -100.0},
+ {"key": "aug_2021", "total": 0, "actual": 0},
+ ]
+ self.assertEqual(report.period_total, expected)
+
+
+def create_company():
+ company = frappe.db.exists("Company", "_Test Company DR")
+ if not company:
+ company = frappe.new_doc("Company")
+ company.company_name = "_Test Company DR"
+ company.default_currency = "INR"
+ company.chart_of_accounts = "Standard"
+ company.insert()
+
+
+def clear_old_entries():
+ item = qb.DocType("Item")
+ account = qb.DocType("Account")
+ customer = qb.DocType("Customer")
+ supplier = qb.DocType("Supplier")
+ sinv = qb.DocType("Sales Invoice")
+ sinv_item = qb.DocType("Sales Invoice Item")
+ pinv = qb.DocType("Purchase Invoice")
+ pinv_item = qb.DocType("Purchase Invoice Item")
+
+ qb.from_(account).delete().where(
+ (account.account_name == "Deferred Revenue")
+ | (account.account_name == "Deferred Expense") & (account.company == "_Test Company DR")
+ ).run()
+ qb.from_(item).delete().where(
+ (item.item_code == "_Test Internet Subscription") | (item.item_code == "_Test Office Rent")
+ ).run()
+ qb.from_(customer).delete().where(customer.customer_name == "_Test Customer DR").run()
+ qb.from_(supplier).delete().where(supplier.supplier_name == "_Test Furniture Supplier").run()
+
+ # delete existing invoices with deferred items
+ deferred_invoices = (
+ qb.from_(sinv)
+ .join(sinv_item)
+ .on(sinv.name == sinv_item.parent)
+ .select(sinv.name)
+ .where(sinv_item.enable_deferred_revenue == 1)
+ .run()
+ )
+ if deferred_invoices:
+ qb.from_(sinv).delete().where(sinv.name.isin(deferred_invoices)).run()
+
+ deferred_invoices = (
+ qb.from_(pinv)
+ .join(pinv_item)
+ .on(pinv.name == pinv_item.parent)
+ .select(pinv.name)
+ .where(pinv_item.enable_deferred_expense == 1)
+ .run()
+ )
+ if deferred_invoices:
+ qb.from_(pinv).delete().where(pinv.name.isin(deferred_invoices)).run()
diff --git a/erpnext/agriculture/doctype/crop/test_crop.js b/erpnext/agriculture/doctype/crop/test_crop.js
deleted file mode 100644
index 4055563..0000000
--- a/erpnext/agriculture/doctype/crop/test_crop.js
+++ /dev/null
@@ -1,116 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Crop", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(2);
-
- frappe.run_serially([
- // insert a new Item
- () => frappe.tests.make('Item', [
- // values to be set
- {item_code: 'Basil Seeds'},
- {item_name: 'Basil Seeds'},
- {item_group: 'Seed'}
- ]),
- // insert a new Item
- () => frappe.tests.make('Item', [
- // values to be set
- {item_code: 'Twigs'},
- {item_name: 'Twigs'},
- {item_group: 'By-product'}
- ]),
- // insert a new Item
- () => frappe.tests.make('Item', [
- // values to be set
- {item_code: 'Basil Leaves'},
- {item_name: 'Basil Leaves'},
- {item_group: 'Produce'}
- ]),
- // insert a new Crop
- () => frappe.tests.make('Crop', [
- // values to be set
- {title: 'Basil from seed'},
- {crop_name: 'Basil'},
- {scientific_name: 'Ocimum basilicum'},
- {materials_required: [
- [
- {item_code: 'Basil Seeds'},
- {qty: '25'},
- {uom: 'Nos'},
- {rate: '1'}
- ],
- [
- {item_code: 'Urea'},
- {qty: '5'},
- {uom: 'Kg'},
- {rate: '10'}
- ]
- ]},
- {byproducts: [
- [
- {item_code: 'Twigs'},
- {qty: '25'},
- {uom: 'Nos'},
- {rate: '1'}
- ]
- ]},
- {produce: [
- [
- {item_code: 'Basil Leaves'},
- {qty: '100'},
- {uom: 'Nos'},
- {rate: '1'}
- ]
- ]},
- {agriculture_task: [
- [
- {task_name: "Plough the field"},
- {start_day: 1},
- {end_day: 1},
- {holiday_management: "Ignore holidays"}
- ],
- [
- {task_name: "Plant the seeds"},
- {start_day: 2},
- {end_day: 3},
- {holiday_management: "Ignore holidays"}
- ],
- [
- {task_name: "Water the field"},
- {start_day: 4},
- {end_day: 4},
- {holiday_management: "Ignore holidays"}
- ],
- [
- {task_name: "First harvest"},
- {start_day: 8},
- {end_day: 8},
- {holiday_management: "Ignore holidays"}
- ],
- [
- {task_name: "Add the fertilizer"},
- {start_day: 10},
- {end_day: 12},
- {holiday_management: "Ignore holidays"}
- ],
- [
- {task_name: "Final cut"},
- {start_day: 15},
- {end_day: 15},
- {holiday_management: "Ignore holidays"}
- ]
- ]}
- ]),
- // agriculture task list
- () => {
- assert.equal(cur_frm.doc.name, 'Basil from seed');
- assert.equal(cur_frm.doc.period, 15);
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/agriculture/doctype/crop_cycle/test_crop_cycle.js b/erpnext/agriculture/doctype/crop_cycle/test_crop_cycle.js
deleted file mode 100644
index 87184da..0000000
--- a/erpnext/agriculture/doctype/crop_cycle/test_crop_cycle.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Crop Cycle", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(1);
-
- frappe.run_serially([
- // insert a new Crop Cycle
- () => frappe.tests.make('Crop Cycle', [
- // values to be set
- {title: 'Basil from seed 2017'},
- {detected_disease: [
- [
- {start_date: '2017-11-21'},
- {disease: 'Aphids'}
- ]
- ]},
- {linked_land_unit: [
- [
- {land_unit: 'Basil Farm'}
- ]
- ]},
- {crop: 'Basil from seed'},
- {start_date: '2017-11-11'},
- {cycle_type: 'Less than a year'}
- ]),
- () => assert.equal(cur_frm.doc.name, 'Basil from seed 2017'),
- () => done()
- ]);
-});
diff --git a/erpnext/agriculture/doctype/disease/test_disease.js b/erpnext/agriculture/doctype/disease/test_disease.js
deleted file mode 100644
index 33f60c4..0000000
--- a/erpnext/agriculture/doctype/disease/test_disease.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Disease", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(1);
-
- frappe.run_serially([
- // insert a new Disease
- () => frappe.tests.make('Disease', [
- // values to be set
- {common_name: 'Aphids'},
- {scientific_name: 'Aphidoidea'},
- {treatment_task: [
- [
- {task_name: "Survey and find the aphid locations"},
- {start_day: 1},
- {end_day: 2},
- {holiday_management: "Ignore holidays"}
- ],
- [
- {task_name: "Apply Pesticides"},
- {start_day: 3},
- {end_day: 3},
- {holiday_management: "Ignore holidays"}
- ]
- ]}
- ]),
- () => {
- assert.equal(cur_frm.doc.treatment_period, 3);
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/agriculture/doctype/fertilizer/test_fertilizer.js b/erpnext/agriculture/doctype/fertilizer/test_fertilizer.js
deleted file mode 100644
index 5dd7313..0000000
--- a/erpnext/agriculture/doctype/fertilizer/test_fertilizer.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Fertilizer", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(1);
-
- frappe.run_serially([
- // insert a new Item
- () => frappe.tests.make('Item', [
- // values to be set
- {item_code: 'Urea'},
- {item_name: 'Urea'},
- {item_group: 'Fertilizer'}
- ]),
- // insert a new Fertilizer
- () => frappe.tests.make('Fertilizer', [
- // values to be set
- {fertilizer_name: 'Urea'},
- {item: 'Urea'}
- ]),
- () => {
- assert.equal(cur_frm.doc.name, 'Urea');
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/agriculture/doctype/soil_texture/test_soil_texture.js b/erpnext/agriculture/doctype/soil_texture/test_soil_texture.js
deleted file mode 100644
index d93f852..0000000
--- a/erpnext/agriculture/doctype/soil_texture/test_soil_texture.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Soil Texture", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(2);
-
- frappe.run_serially([
- // insert a new Soil Texture
- () => frappe.tests.make('Soil Texture', [
- // values to be set
- {location: '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Point","coordinates":[72.882185,19.076395]}}]}'},
- {collection_datetime: '2017-11-08'},
- {clay_composition: 20},
- {sand_composition: 30}
- ]),
- () => {
- assert.equal(cur_frm.doc.silt_composition, 50);
- assert.equal(cur_frm.doc.soil_type, 'Silt Loam');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/agriculture/doctype/water_analysis/test_water_analysis.js b/erpnext/agriculture/doctype/water_analysis/test_water_analysis.js
deleted file mode 100644
index bb01cb3..0000000
--- a/erpnext/agriculture/doctype/water_analysis/test_water_analysis.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Water Analysis", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(1);
-
- frappe.run_serially([
- // insert a new Water Analysis
- () => frappe.tests.make('Water Analysis', [
- // values to be set
- {location: '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Point","coordinates":[72.882185,19.076395]}}]}'},
- {collection_datetime: '2017-11-08 18:43:57'},
- {laboratory_testing_datetime: '2017-11-10 18:43:57'}
- ]),
- () => {
- assert.equal(cur_frm.doc.result_datetime, '2017-11-10 18:43:57');
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/assets/module_onboarding/assets/assets.json b/erpnext/assets/module_onboarding/assets/assets.json
index e6df88b..796245d 100644
--- a/erpnext/assets/module_onboarding/assets/assets.json
+++ b/erpnext/assets/module_onboarding/assets/assets.json
@@ -13,7 +13,7 @@
"documentation_url": "https://docs.erpnext.com/docs/user/manual/en/asset",
"idx": 0,
"is_complete": 0,
- "modified": "2021-08-24 17:50:41.573281",
+ "modified": "2021-12-02 11:24:37.963746",
"modified_by": "Administrator",
"module": "Assets",
"name": "Assets",
diff --git a/erpnext/assets/onboarding_step/asset_category/asset_category.json b/erpnext/assets/onboarding_step/asset_category/asset_category.json
index 033e866..58f322e 100644
--- a/erpnext/assets/onboarding_step/asset_category/asset_category.json
+++ b/erpnext/assets/onboarding_step/asset_category/asset_category.json
@@ -9,7 +9,7 @@
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2021-08-24 12:49:37.665239",
+ "modified": "2021-11-23 10:02:03.242127",
"modified_by": "Administrator",
"name": "Asset Category",
"owner": "Administrator",
diff --git a/erpnext/assets/onboarding_step/asset_item/asset_item.json b/erpnext/assets/onboarding_step/asset_item/asset_item.json
index 8a174c5..13e3e2e 100644
--- a/erpnext/assets/onboarding_step/asset_item/asset_item.json
+++ b/erpnext/assets/onboarding_step/asset_item/asset_item.json
@@ -1,21 +1,22 @@
{
- "action": "Show Form Tour",
+ "action": "Create Entry",
"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",
+ "form_tour": "Item",
"idx": 0,
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2021-08-16 13:59:18.362233",
+ "modified": "2021-12-02 11:23:48.158504",
"modified_by": "Administrator",
"name": "Asset Item",
"owner": "Administrator",
"reference_document": "Item",
- "show_form_tour": 0,
- "show_full_form": 0,
+ "show_form_tour": 1,
+ "show_full_form": 1,
"title": "Create an Asset Item",
"validate_action": 1
}
\ No newline at end of file
diff --git a/erpnext/assets/onboarding_step/asset_purchase/asset_purchase.json b/erpnext/assets/onboarding_step/asset_purchase/asset_purchase.json
index 54611ed..69fa337 100644
--- a/erpnext/assets/onboarding_step/asset_purchase/asset_purchase.json
+++ b/erpnext/assets/onboarding_step/asset_purchase/asset_purchase.json
@@ -9,7 +9,7 @@
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2021-08-24 17:26:57.180637",
+ "modified": "2021-11-23 10:02:03.235498",
"modified_by": "Administrator",
"name": "Asset Purchase",
"owner": "Administrator",
diff --git a/erpnext/assets/onboarding_step/fixed_asset_accounts/fixed_asset_accounts.json b/erpnext/assets/onboarding_step/fixed_asset_accounts/fixed_asset_accounts.json
index cebee7a..2fc6c46 100644
--- a/erpnext/assets/onboarding_step/fixed_asset_accounts/fixed_asset_accounts.json
+++ b/erpnext/assets/onboarding_step/fixed_asset_accounts/fixed_asset_accounts.json
@@ -9,7 +9,7 @@
"is_complete": 0,
"is_single": 0,
"is_skipped": 0,
- "modified": "2021-08-24 17:46:37.646174",
+ "modified": "2021-11-23 10:02:03.229566",
"modified_by": "Administrator",
"name": "Fixed Asset Accounts",
"owner": "Administrator",
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js
deleted file mode 100644
index 012b061..0000000
--- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order.js
+++ /dev/null
@@ -1,80 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: purchase order", function(assert) {
- assert.expect(16);
- let done = assert.async();
-
- frappe.run_serially([
- () => {
- return frappe.tests.make('Purchase Order', [
- {supplier: 'Test Supplier'},
- {is_subcontracted: 'No'},
- {currency: 'INR'},
- {items: [
- [
- {"item_code": 'Test Product 4'},
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 2)},
- {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
- {"qty": 5},
- {"uom": 'Unit'},
- {"rate": 100},
- {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ],
- [
- {"item_code": 'Test Product 1'},
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
- {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
- {"qty": 2},
- {"uom": 'Unit'},
- {"rate": 100},
- {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ]
- ]},
-
- {tc_name: 'Test Term 1'},
- {terms: 'This is a term.'}
- ]);
- },
-
- () => {
- // Get supplier details
- assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
- assert.ok(cur_frm.doc.schedule_date == frappe.datetime.add_days(frappe.datetime.now_date(), 1), "Schedule Date correct");
- assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Contact email correct");
- // Get item details
- assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item name correct");
- assert.ok(cur_frm.doc.items[0].description == 'Test Product 4', "Description correct");
- assert.ok(cur_frm.doc.items[0].qty == 5, "Quantity correct");
- assert.ok(cur_frm.doc.items[0].schedule_date == frappe.datetime.add_days(frappe.datetime.now_date(), 2), "Schedule Date correct");
-
- assert.ok(cur_frm.doc.items[1].item_name == 'Test Product 1', "Item name correct");
- assert.ok(cur_frm.doc.items[1].description == 'Test Product 1', "Description correct");
- assert.ok(cur_frm.doc.items[1].qty == 2, "Quantity correct");
- assert.ok(cur_frm.doc.items[1].schedule_date == cur_frm.doc.schedule_date, "Schedule Date correct");
- // Calculate total
- assert.ok(cur_frm.doc.total == 700, "Total correct");
- // Get terms
- assert.ok(cur_frm.doc.terms == 'This is a term.', "Terms correct");
- },
-
- () => cur_frm.print_doc(),
- () => frappe.timeout(2),
- () => {
- assert.ok($('.btn-print-print').is(':visible'), "Print Format Available");
- assert.ok($('div > div:nth-child(5) > div > div > table > tbody > tr > td:nth-child(4) > div').text().includes('Test Product 4'), "Print Preview Works");
- },
-
- () => cur_frm.print_doc(),
- () => frappe.timeout(1),
-
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(1),
-
- () => {
- assert.ok(cur_frm.doc.status == 'To Receive and Bill', "Submitted successfully");
- },
-
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js
deleted file mode 100644
index bc3d767..0000000
--- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_get_items.js
+++ /dev/null
@@ -1,61 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: purchase order with get items", function(assert) {
- assert.expect(4);
- let done = assert.async();
-
- frappe.run_serially([
- () => {
- return frappe.tests.make('Purchase Order', [
- {supplier: 'Test Supplier'},
- {is_subcontracted: 'No'},
- {buying_price_list: 'Test-Buying-USD'},
- {currency: 'USD'},
- {items: [
- [
- {"item_code": 'Test Product 4'},
- {"qty": 5},
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
- {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
- {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ]
- ]}
- ]);
- },
-
- () => {
- assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
- },
-
- () => frappe.timeout(0.3),
- () => frappe.click_button('Get items from'),
- () => frappe.timeout(0.3),
-
- () => frappe.click_link('Product Bundle'),
- () => frappe.timeout(0.5),
-
- () => cur_dialog.set_value('product_bundle', 'Computer'),
- () => frappe.click_button('Get Items'),
- () => frappe.timeout(1),
-
- // Check if items are fetched from Product Bundle
- () => {
- assert.ok(cur_frm.doc.items[1].item_name == 'CPU', "Product bundle item 1 correct");
- assert.ok(cur_frm.doc.items[2].item_name == 'Screen', "Product bundle item 2 correct");
- assert.ok(cur_frm.doc.items[3].item_name == 'Keyboard', "Product bundle item 3 correct");
- },
-
- () => cur_frm.doc.items[1].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")),
- () => cur_frm.doc.items[2].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")),
- () => cur_frm.doc.items[3].warehouse = 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company")),
-
- () => cur_frm.save(),
- () => frappe.timeout(1),
-
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
-
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js
deleted file mode 100644
index daf8d6c..0000000
--- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_receipt.js
+++ /dev/null
@@ -1,74 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: purchase order receipt", function(assert) {
- assert.expect(5);
- let done = assert.async();
-
- frappe.run_serially([
- () => {
- return frappe.tests.make('Purchase Order', [
- {supplier: 'Test Supplier'},
- {is_subcontracted: 'No'},
- {buying_price_list: 'Test-Buying-USD'},
- {currency: 'USD'},
- {items: [
- [
- {"item_code": 'Test Product 1'},
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
- {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
- {"qty": 5},
- {"uom": 'Unit'},
- {"rate": 100},
- {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ]
- ]},
- ]);
- },
-
- () => {
-
- // Check supplier and item details
- assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
- assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 1', "Item name correct");
- assert.ok(cur_frm.doc.items[0].description == 'Test Product 1', "Description correct");
- assert.ok(cur_frm.doc.items[0].qty == 5, "Quantity correct");
-
- },
-
- () => frappe.timeout(1),
-
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
-
- () => frappe.timeout(1.5),
- () => frappe.click_button('Close'),
- () => frappe.timeout(0.3),
-
- // Make Purchase Receipt
- () => frappe.click_button('Make'),
- () => frappe.timeout(0.3),
-
- () => frappe.click_link('Receipt'),
- () => frappe.timeout(2),
-
- () => cur_frm.save(),
-
- // Save and submit Purchase Receipt
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(1),
-
- // View Purchase order in Stock Ledger
- () => frappe.click_button('View'),
- () => frappe.timeout(0.3),
-
- () => frappe.click_link('Stock Ledger'),
- () => frappe.timeout(2),
- () => {
- assert.ok($('div.slick-cell.l2.r2 > a').text().includes('Test Product 1')
- && $('div.slick-cell.l9.r9 > div').text().includes(5), "Stock ledger entry correct");
- },
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js
deleted file mode 100644
index 83eb295..0000000
--- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_discount_on_grand_total.js
+++ /dev/null
@@ -1,47 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: purchase order with discount on grand total", function(assert) {
- assert.expect(4);
- let done = assert.async();
-
- frappe.run_serially([
- () => {
- return frappe.tests.make('Purchase Order', [
- {supplier: 'Test Supplier'},
- {is_subcontracted: 'No'},
- {buying_price_list: 'Test-Buying-EUR'},
- {currency: 'EUR'},
- {items: [
- [
- {"item_code": 'Test Product 4'},
- {"qty": 5},
- {"uom": 'Unit'},
- {"rate": 500 },
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
- {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
- {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ]
- ]},
- {apply_discount_on: 'Grand Total'},
- {additional_discount_percentage: 10}
- ]);
- },
-
- () => frappe.timeout(1),
-
- () => {
- assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
- assert.ok(cur_frm.doc.items[0].rate == 500, "Rate correct");
- // Calculate total
- assert.ok(cur_frm.doc.total == 2500, "Total correct");
- // Calculate grand total after discount
- assert.ok(cur_frm.doc.grand_total == 2250, "Grand total correct");
- },
-
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
-
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js
deleted file mode 100644
index a729dd9..0000000
--- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_item_wise_discount.js
+++ /dev/null
@@ -1,44 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: purchase order with item wise discount", function(assert) {
- assert.expect(4);
- let done = assert.async();
-
- frappe.run_serially([
- () => {
- return frappe.tests.make('Purchase Order', [
- {supplier: 'Test Supplier'},
- {is_subcontracted: 'No'},
- {buying_price_list: 'Test-Buying-EUR'},
- {currency: 'EUR'},
- {items: [
- [
- {"item_code": 'Test Product 4'},
- {"qty": 5},
- {"uom": 'Unit'},
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
- {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
- {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))},
- {"discount_percentage": 20}
- ]
- ]}
- ]);
- },
-
- () => frappe.timeout(1),
-
- () => {
- assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
- assert.ok(cur_frm.doc.items[0].discount_percentage == 20, "Discount correct");
- // Calculate totals after discount
- assert.ok(cur_frm.doc.total == 2000, "Total correct");
- assert.ok(cur_frm.doc.grand_total == 2000, "Grand total correct");
- },
-
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
-
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js
deleted file mode 100644
index b605e76..0000000
--- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_multi_uom.js
+++ /dev/null
@@ -1,39 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: purchase order with multi UOM", function(assert) {
- assert.expect(3);
- let done = assert.async();
-
- frappe.run_serially([
- () => {
- return frappe.tests.make('Purchase Order', [
- {supplier: 'Test Supplier'},
- {is_subcontracted: 'No'},
- {items: [
- [
- {"item_code": 'Test Product 4'},
- {"qty": 5},
- {"uom": 'Unit'},
- {"rate": 100},
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
- {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
- {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ]
- ]}
- ]);
- },
-
- () => {
- assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Supplier name correct");
- assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item name correct");
- assert.ok(cur_frm.doc.items[0].uom == 'Unit', "Multi UOM correct");
- },
-
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
-
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_shipping_rule.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_shipping_rule.js
deleted file mode 100644
index c258756..0000000
--- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_shipping_rule.js
+++ /dev/null
@@ -1,43 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: purchase order with shipping rule", function(assert) {
- assert.expect(3);
- let done = assert.async();
-
- frappe.run_serially([
- () => {
- return frappe.tests.make('Purchase Order', [
- {supplier: 'Test Supplier'},
- {is_subcontracted: 'No'},
- {buying_price_list: 'Test-Buying-USD'},
- {currency: 'USD'},
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
- {items: [
- [
- {"item_code": 'Test Product 4'},
- {"qty": 5},
- {"uom": 'Unit'},
- {"rate": 500 },
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
- {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
- {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ]
- ]},
-
- {shipping_rule:'Two Day Shipping'}
- ]);
- },
-
- () => {
- // Check grand total
- assert.ok(cur_frm.doc.total_taxes_and_charges == 200, "Taxes and charges correct");
- assert.ok(cur_frm.doc.grand_total == 2700, "Grand total correct");
- },
-
- () => frappe.timeout(0.3),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js b/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js
deleted file mode 100644
index ccc383f..0000000
--- a/erpnext/buying/doctype/purchase_order/tests/test_purchase_order_with_taxes_and_charges.js
+++ /dev/null
@@ -1,44 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: purchase order with taxes and charges", function(assert) {
- assert.expect(3);
- let done = assert.async();
-
- frappe.run_serially([
- () => {
- return frappe.tests.make('Purchase Order', [
- {supplier: 'Test Supplier'},
- {is_subcontracted: 'No'},
- {buying_price_list: 'Test-Buying-USD'},
- {currency: 'USD'},
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
- {items: [
- [
- {"item_code": 'Test Product 4'},
- {"qty": 5},
- {"uom": 'Unit'},
- {"rate": 500 },
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 1)},
- {"expected_delivery_date": frappe.datetime.add_days(frappe.datetime.now_date(), 5)},
- {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ]
- ]},
-
- {taxes_and_charges: 'TEST In State GST - FT'}
- ]);
- },
-
- () => {
- // Check taxes and calculate grand total
- assert.ok(cur_frm.doc.taxes[1].account_head=='SGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), "Account Head abbr correct");
- assert.ok(cur_frm.doc.total_taxes_and_charges == 225, "Taxes and charges correct");
- assert.ok(cur_frm.doc.grand_total == 2725, "Grand total correct");
- },
-
- () => frappe.timeout(0.3),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js
deleted file mode 100644
index 75f85f8..0000000
--- a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation.js
+++ /dev/null
@@ -1,76 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: request_for_quotation", function(assert) {
- assert.expect(14);
- let done = assert.async();
- let date;
- frappe.run_serially([
- () => {
- date = frappe.datetime.add_days(frappe.datetime.now_date(), 10);
- return frappe.tests.make('Request for Quotation', [
- {transaction_date: date},
- {suppliers: [
- [
- {"supplier": 'Test Supplier'},
- {"email_id": 'test@supplier.com'}
- ]
- ]},
- {items: [
- [
- {"item_code": 'Test Product 4'},
- {"qty": 5},
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(),20)},
- {"warehouse": 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ]
- ]},
- {message_for_supplier: 'Please supply the specified items at the best possible rates'},
- {tc_name: 'Test Term 1'}
- ]);
- },
- () => frappe.timeout(3),
- () => {
- assert.ok(cur_frm.doc.transaction_date == date, "Date correct");
- assert.ok(cur_frm.doc.company == cur_frm.doc.company, "Company correct");
- assert.ok(cur_frm.doc.suppliers[0].supplier_name == 'Test Supplier', "Supplier name correct");
- assert.ok(cur_frm.doc.suppliers[0].contact == 'Contact 3-Test Supplier', "Contact correct");
- assert.ok(cur_frm.doc.suppliers[0].email_id == 'test@supplier.com', "Email id correct");
- assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 4', "Item Name correct");
- assert.ok(cur_frm.doc.items[0].warehouse == 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company")), "Warehouse correct");
- assert.ok(cur_frm.doc.message_for_supplier == 'Please supply the specified items at the best possible rates', "Reply correct");
- assert.ok(cur_frm.doc.tc_name == 'Test Term 1', "Term name correct");
- },
- () => frappe.timeout(3),
- () => cur_frm.print_doc(),
- () => frappe.timeout(1),
- () => {
- assert.ok($('.btn-print-print').is(':visible'), "Print Format Available");
- assert.ok($('.section-break+ .section-break .column-break:nth-child(1) .value').text().includes("Test Product 4"), "Print Preview Works");
- },
- () => cur_frm.print_doc(),
- () => frappe.timeout(1),
- () => frappe.click_button('Get items from'),
- () => frappe.timeout(0.3),
- () => frappe.click_link('Material Request'),
- () => frappe.timeout(1),
- () => frappe.click_button('Get Items'),
- () => frappe.timeout(1),
- () => {
- assert.ok(cur_frm.doc.items[1].item_name == 'Test Product 1', "Getting items from material requests work");
- },
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(1),
- () => {
- assert.ok(cur_frm.doc.docstatus == 1, "Quotation request submitted");
- },
- () => frappe.click_button('Send Supplier Emails'),
- () => frappe.timeout(6),
- () => {
- assert.ok($('div.modal.fade.in > div.modal-dialog > div > div.modal-body.ui-front > div.msgprint').text().includes("Email sent to supplier Test Supplier"), "Send emails working");
- },
- () => frappe.click_button('Close'),
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js b/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js
deleted file mode 100644
index f06c3f3..0000000
--- a/erpnext/buying/doctype/request_for_quotation/tests/test_request_for_quotation_for_status.js
+++ /dev/null
@@ -1,128 +0,0 @@
-QUnit.module('buying');
-
-QUnit.test("Test: Request for Quotation", function (assert) {
- assert.expect(5);
- let done = assert.async();
- let rfq_name = "";
-
- frappe.run_serially([
- // Go to RFQ list
- () => frappe.set_route("List", "Request for Quotation"),
- // Create a new RFQ
- () => frappe.new_doc("Request for Quotation"),
- () => frappe.timeout(1),
- () => cur_frm.set_value("transaction_date", "04-04-2017"),
- () => cur_frm.set_value("company", "For Testing"),
- // Add Suppliers
- () => {
- cur_frm.fields_dict.suppliers.grid.grid_rows[0].toggle_view();
- },
- () => frappe.timeout(1),
- () => {
- cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.supplier = "_Test Supplier";
- frappe.click_check('Send Email');
- cur_frm.cur_grid.frm.script_manager.trigger('supplier');
- },
- () => frappe.timeout(1),
- () => {
- cur_frm.cur_grid.toggle_view();
- },
- () => frappe.timeout(1),
- () => frappe.click_button('Add Row',0),
- () => frappe.timeout(1),
- () => {
- cur_frm.fields_dict.suppliers.grid.grid_rows[1].toggle_view();
- },
- () => frappe.timeout(1),
- () => {
- cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.supplier = "_Test Supplier 1";
- frappe.click_check('Send Email');
- cur_frm.cur_grid.frm.script_manager.trigger('supplier');
- },
- () => frappe.timeout(1),
- () => {
- cur_frm.cur_grid.toggle_view();
- },
- () => frappe.timeout(1),
- // Add Item
- () => {
- cur_frm.fields_dict.items.grid.grid_rows[0].toggle_view();
- },
- () => frappe.timeout(1),
- () => {
- cur_frm.fields_dict.items.grid.grid_rows[0].doc.item_code = "_Test Item";
- frappe.set_control('item_code',"_Test Item");
- frappe.set_control('qty',5);
- frappe.set_control('schedule_date', "05-05-2017");
- cur_frm.cur_grid.frm.script_manager.trigger('supplier');
- },
- () => frappe.timeout(2),
- () => {
- cur_frm.cur_grid.toggle_view();
- },
- () => frappe.timeout(2),
- () => {
- cur_frm.fields_dict.items.grid.grid_rows[0].doc.warehouse = "_Test Warehouse - FT";
- },
- () => frappe.click_button('Save'),
- () => frappe.timeout(1),
- () => frappe.click_button('Submit'),
- () => frappe.timeout(1),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(1),
- () => frappe.click_button('Menu'),
- () => frappe.timeout(1),
- () => frappe.click_link('Reload'),
- () => frappe.timeout(1),
- () => {
- assert.equal(cur_frm.doc.docstatus, 1);
- rfq_name = cur_frm.doc.name;
- assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[0].doc.quote_status == "Pending");
- assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.quote_status == "Pending");
- },
- () => {
- cur_frm.fields_dict.suppliers.grid.grid_rows[0].toggle_view();
- },
- () => frappe.timeout(1),
- () => frappe.timeout(1),
- () => {
- cur_frm.cur_grid.toggle_view();
- },
- () => frappe.click_button('Update'),
- () => frappe.timeout(1),
-
- () => frappe.click_button('Supplier Quotation'),
- () => frappe.timeout(1),
- () => frappe.click_link('Make'),
- () => frappe.timeout(1),
- () => {
- frappe.set_control('supplier',"_Test Supplier 1");
- },
- () => frappe.timeout(1),
- () => frappe.click_button('Make Supplier Quotation'),
- () => frappe.timeout(1),
- () => cur_frm.set_value("company", "For Testing"),
- () => cur_frm.fields_dict.items.grid.grid_rows[0].doc.rate = 4.99,
- () => frappe.timeout(1),
- () => frappe.click_button('Save'),
- () => frappe.timeout(1),
- () => frappe.click_button('Submit'),
- () => frappe.timeout(1),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(1),
- () => frappe.set_route("List", "Request for Quotation"),
- () => frappe.timeout(2),
- () => frappe.set_route("List", "Request for Quotation"),
- () => frappe.timeout(2),
- () => frappe.click_link(rfq_name),
- () => frappe.timeout(1),
- () => frappe.click_button('Menu'),
- () => frappe.timeout(1),
- () => frappe.click_link('Reload'),
- () => frappe.timeout(1),
- () => {
- assert.ok(cur_frm.fields_dict.suppliers.grid.grid_rows[1].doc.quote_status == "Received");
- },
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/supplier/test_supplier.js b/erpnext/buying/doctype/supplier/test_supplier.js
deleted file mode 100644
index eaa4d09..0000000
--- a/erpnext/buying/doctype/supplier/test_supplier.js
+++ /dev/null
@@ -1,77 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: supplier", function(assert) {
- assert.expect(6);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Supplier', [
- {supplier_name: 'Test Supplier'},
- {supplier_group: 'Hardware'},
- {country: 'India'},
- {default_currency: 'INR'},
- {accounts: [
- [
- {'company': "For Testing"},
- {'account': "Creditors - FT"}
- ]]
- }
- ]);
- },
- () => frappe.timeout(1),
- () => frappe.click_button('New Address'),
- () => {
- return frappe.tests.set_form_values(cur_frm, [
- {address_title:"Test3"},
- {address_type: "Billing"},
- {address_line1: "Billing Street 3"},
- {city: "Billing City 3"},
- ]);
- },
- () => cur_frm.save(),
- () => frappe.timeout(2),
- () => frappe.click_button('New Address'),
- () => {
- return frappe.tests.set_form_values(cur_frm, [
- {address_title:"Test3"},
- {address_type: "Shipping"},
- {address_line1: "Shipping Street 3"},
- {city: "Shipping City 3"},
- ]);
- },
- () => cur_frm.save(),
- () => frappe.timeout(2),
- () => frappe.click_button('New Address'),
- () => {
- return frappe.tests.set_form_values(cur_frm, [
- {address_title:"Test3"},
- {address_type: "Warehouse"},
- {address_line1: "Warehouse Street 3"},
- {city: "Warehouse City 3"},
- ]);
- },
- () => cur_frm.save(),
- () => frappe.timeout(2),
- () => frappe.click_button('New Contact'),
- () => {
- return frappe.tests.set_form_values(cur_frm, [
- {first_name: "Contact 3"},
- {email_id: "test@supplier.com"}
- ]);
- },
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => frappe.set_route('Form', 'Supplier', 'Test Supplier'),
- () => frappe.timeout(0.3),
-
- () => {
- assert.ok(cur_frm.doc.supplier_name == 'Test Supplier', "Name correct");
- assert.ok(cur_frm.doc.supplier_group == 'Hardware', "Type correct");
- assert.ok(cur_frm.doc.default_currency == 'INR', "Currency correct");
- assert.ok(cur_frm.doc.accounts[0].account == 'Creditors - '+frappe.get_abbr('For Testing'), " Account Head abbr correct");
- assert.ok($('.address-box:nth-child(3) p').text().includes('Shipping City 3'), "Address correct");
- assert.ok($('.col-sm-6+ .col-sm-6 .h6').text().includes('Contact 3'), "Contact correct");
- },
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js
deleted file mode 100644
index 20fb430..0000000
--- a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation.js
+++ /dev/null
@@ -1,74 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: supplier quotation", function(assert) {
- assert.expect(11);
- let done = assert.async();
- let date;
-
- frappe.run_serially([
- () => {
- date = frappe.datetime.add_days(frappe.datetime.now_date(), 10);
- return frappe.tests.make('Supplier Quotation', [
- {supplier: 'Test Supplier'},
- {transaction_date: date},
- {currency: 'INR'},
- {items: [
- [
- {"item_code": 'Test Product 4'},
- {"qty": 5},
- {"uom": 'Unit'},
- {"rate": 200},
- {"warehouse": 'All Warehouses - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ]
- ]},
- {apply_discount_on: 'Grand Total'},
- {additional_discount_percentage: 10},
- {tc_name: 'Test Term 1'},
- {terms: 'This is a term'}
- ]);
- },
- () => frappe.timeout(3),
- () => {
- // Get Supplier details
- assert.ok(cur_frm.doc.supplier == 'Test Supplier', "Supplier correct");
- assert.ok(cur_frm.doc.company == cur_frm.doc.company, "Company correct");
- // Get Contact details
- assert.ok(cur_frm.doc.contact_person == 'Contact 3-Test Supplier', "Conatct correct");
- assert.ok(cur_frm.doc.contact_email == 'test@supplier.com', "Email correct");
- // Get uom
- assert.ok(cur_frm.doc.items[0].uom == 'Unit', "Multi uom correct");
- assert.ok(cur_frm.doc.total == 1000, "Total correct");
- // Calculate total after discount
- assert.ok(cur_frm.doc.grand_total == 900, "Grand total correct");
- // Get terms
- assert.ok(cur_frm.doc.tc_name == 'Test Term 1', "Terms correct");
- },
-
- () => cur_frm.print_doc(),
- () => frappe.timeout(2),
- () => {
- assert.ok($('.btn-print-print').is(':visible'), "Print Format Available");
- assert.ok($("table > tbody > tr > td:nth-child(3) > div").text().includes("Test Product 4"), "Print Preview Works As Expected");
- },
- () => cur_frm.print_doc(),
- () => frappe.timeout(1),
- () => frappe.click_button('Get items from'),
- () => frappe.timeout(0.3),
- () => frappe.click_link('Material Request'),
- () => frappe.timeout(0.3),
- () => frappe.click_button('Get Items'),
- () => frappe.timeout(1),
- () => {
- // Get item from Material Requests
- assert.ok(cur_frm.doc.items[1].item_name == 'Test Product 1', "Getting items from material requests work");
- },
-
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
-
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js
deleted file mode 100644
index 0a51565..0000000
--- a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_item_wise_discount.js
+++ /dev/null
@@ -1,34 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: supplier quotation with item wise discount", function(assert){
- assert.expect(2);
- let done = assert.async();
-
- frappe.run_serially([
- () => {
- return frappe.tests.make('Supplier Quotation', [
- {supplier: 'Test Supplier'},
- {company: 'For Testing'},
- {items: [
- [
- {"item_code": 'Test Product 4'},
- {"qty": 5},
- {"uom": 'Unit'},
- {"warehouse": 'All Warehouses - FT'},
- {'discount_percentage': 10},
- ]
- ]}
- ]);
- },
-
- () => {
- assert.ok(cur_frm.doc.total == 900, "Total correct");
- assert.ok(cur_frm.doc.grand_total == 900, "Grand total correct");
- },
-
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js b/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js
deleted file mode 100644
index 7ea3e60..0000000
--- a/erpnext/buying/doctype/supplier_quotation/tests/test_supplier_quotation_for_taxes_and_charges.js
+++ /dev/null
@@ -1,37 +0,0 @@
-QUnit.module('Buying');
-
-QUnit.test("test: supplier quotation with taxes and charges", function(assert) {
- assert.expect(3);
- let done = assert.async();
- let supplier_quotation_name;
-
- frappe.run_serially([
- () => {
- return frappe.tests.make('Supplier Quotation', [
- {supplier: 'Test Supplier'},
- {items: [
- [
- {"item_code": 'Test Product 4'},
- {"qty": 5},
- {"rate": 100},
- {"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- ]
- ]},
- {taxes_and_charges:'TEST In State GST - FT'},
- ]);
- },
- () => {supplier_quotation_name = cur_frm.doc.name;},
- () => {
- assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
- assert.ok(cur_frm.doc.total_taxes_and_charges == 45, "Taxes and charges correct");
- assert.ok(cur_frm.doc.grand_total == 545, "Grand total correct");
- },
-
- () => cur_frm.save(),
- () => frappe.timeout(0.3),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py
index 9adbe8b..c31b068 100644
--- a/erpnext/crm/doctype/lead/lead.py
+++ b/erpnext/crm/doctype/lead/lead.py
@@ -8,7 +8,6 @@
from frappe.email.inbox import link_communication_to_document
from frappe.model.mapper import get_mapped_doc
from frappe.utils import (
- cint,
comma_and,
cstr,
get_link_to_form,
@@ -39,11 +38,7 @@
self.check_email_id_is_unique()
self.validate_email_id()
self.validate_contact_date()
- self._prev = frappe._dict({
- "contact_date": frappe.db.get_value("Lead", self.name, "contact_date") if (not cint(self.is_new())) else None,
- "ends_on": frappe.db.get_value("Lead", self.name, "ends_on") if (not cint(self.is_new())) else None,
- "contact_by": frappe.db.get_value("Lead", self.name, "contact_by") if (not cint(self.is_new())) else None,
- })
+ self.set_prev()
def set_full_name(self):
if self.first_name:
@@ -75,6 +70,16 @@
self.add_calendar_event()
self.update_prospects()
+ def set_prev(self):
+ if self.is_new():
+ self._prev = frappe._dict({
+ "contact_date": None,
+ "ends_on": None,
+ "contact_by": None
+ })
+ else:
+ self._prev = frappe.db.get_value("Lead", self.name, ["contact_date", "ends_on", "contact_by"], as_dict=1)
+
def before_insert(self):
self.contact_doc = self.create_contact()
diff --git a/erpnext/crm/doctype/lead/tests/test_lead_individual.js b/erpnext/crm/doctype/lead/tests/test_lead_individual.js
deleted file mode 100644
index 66d3337..0000000
--- a/erpnext/crm/doctype/lead/tests/test_lead_individual.js
+++ /dev/null
@@ -1,43 +0,0 @@
-QUnit.module("sales");
-
-QUnit.test("test: lead", function (assert) {
- assert.expect(4);
- let done = assert.async();
- let lead_name = frappe.utils.get_random(10);
- frappe.run_serially([
- // test lead creation
- () => frappe.set_route("List", "Lead"),
- () => frappe.new_doc("Lead"),
- () => frappe.timeout(1),
- () => cur_frm.set_value("lead_name", lead_name),
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => {
- assert.ok(cur_frm.doc.lead_name.includes(lead_name),
- 'name correctly set');
- frappe.lead_name = cur_frm.doc.name;
- },
- // create address and contact
- () => frappe.click_link('Address & Contact'),
- () => frappe.click_button('New Address'),
- () => frappe.timeout(1),
- () => frappe.set_control('address_line1', 'Gateway'),
- () => frappe.set_control('city', 'Mumbai'),
- () => cur_frm.save(),
- () => frappe.timeout(3),
- () => assert.equal(frappe.get_route()[1], 'Lead',
- 'back to lead form'),
- () => frappe.click_link('Address & Contact'),
- () => assert.ok($('.address-box').text().includes('Mumbai'),
- 'city is seen in address box'),
-
- // make opportunity
- () => frappe.click_button('Make'),
- () => frappe.click_link('Opportunity'),
- () => frappe.timeout(2),
- () => assert.equal(cur_frm.doc.lead, frappe.lead_name,
- 'lead name correctly mapped'),
-
- () => done()
- ]);
-});
diff --git a/erpnext/crm/doctype/lead/tests/test_lead_organization.js b/erpnext/crm/doctype/lead/tests/test_lead_organization.js
deleted file mode 100644
index 7fb9573..0000000
--- a/erpnext/crm/doctype/lead/tests/test_lead_organization.js
+++ /dev/null
@@ -1,55 +0,0 @@
-QUnit.module("sales");
-
-QUnit.test("test: lead", function (assert) {
- assert.expect(5);
- let done = assert.async();
- let lead_name = frappe.utils.get_random(10);
- frappe.run_serially([
- // test lead creation
- () => frappe.set_route("List", "Lead"),
- () => frappe.new_doc("Lead"),
- () => frappe.timeout(1),
- () => cur_frm.set_value("company_name", lead_name),
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => {
- assert.ok(cur_frm.doc.lead_name.includes(lead_name),
- 'name correctly set');
- frappe.lead_name = cur_frm.doc.name;
- },
- // create address and contact
- () => frappe.click_link('Address & Contact'),
- () => frappe.click_button('New Address'),
- () => frappe.timeout(1),
- () => frappe.set_control('address_line1', 'Gateway'),
- () => frappe.set_control('city', 'Mumbai'),
- () => cur_frm.save(),
- () => frappe.timeout(3),
- () => assert.equal(frappe.get_route()[1], 'Lead',
- 'back to lead form'),
- () => frappe.click_link('Address & Contact'),
- () => assert.ok($('.address-box').text().includes('Mumbai'),
- 'city is seen in address box'),
-
- () => frappe.click_button('New Contact'),
- () => frappe.timeout(1),
- () => frappe.set_control('first_name', 'John'),
- () => frappe.set_control('last_name', 'Doe'),
- () => cur_frm.save(),
- () => frappe.timeout(3),
- () => frappe.set_route('Form', 'Lead', cur_frm.doc.links[0].link_name),
- () => frappe.timeout(1),
- () => frappe.click_link('Address & Contact'),
- () => assert.ok($('.address-box').text().includes('John'),
- 'contact is seen in contact box'),
-
- // make customer
- () => frappe.click_button('Make'),
- () => frappe.click_link('Customer'),
- () => frappe.timeout(2),
- () => assert.equal(cur_frm.doc.lead_name, frappe.lead_name,
- 'lead name correctly mapped'),
-
- () => done()
- ]);
-});
diff --git a/erpnext/crm/doctype/opportunity/test_opportunity.js b/erpnext/crm/doctype/opportunity/test_opportunity.js
deleted file mode 100644
index 45b97dd..0000000
--- a/erpnext/crm/doctype/opportunity/test_opportunity.js
+++ /dev/null
@@ -1,56 +0,0 @@
-QUnit.test("test: opportunity", function (assert) {
- assert.expect(8);
- let done = assert.async();
- frappe.run_serially([
- () => frappe.set_route('List', 'Opportunity'),
- () => frappe.timeout(1),
- () => frappe.click_button('New'),
- () => frappe.timeout(1),
- () => cur_frm.set_value('opportunity_from', 'Customer'),
- () => cur_frm.set_value('customer', 'Test Customer 1'),
-
- // check items
- () => cur_frm.set_value('with_items', 1),
- () => frappe.tests.set_grid_values(cur_frm, 'items', [
- [
- {item_code:'Test Product 1'},
- {qty: 4}
- ]
- ]),
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => {
- assert.notOk(cur_frm.is_new(), 'saved');
- frappe.opportunity_name = cur_frm.doc.name;
- },
-
- // close and re-open
- () => frappe.click_button('Close'),
- () => frappe.timeout(1),
- () => assert.equal(cur_frm.doc.status, 'Closed',
- 'closed'),
-
- () => frappe.click_button('Reopen'),
- () => assert.equal(cur_frm.doc.status, 'Open',
- 'reopened'),
- () => frappe.timeout(1),
-
- // make quotation
- () => frappe.click_button('Make'),
- () => frappe.click_link('Quotation', 1),
- () => frappe.timeout(2),
- () => {
- assert.equal(frappe.get_route()[1], 'Quotation',
- 'made quotation');
- assert.equal(cur_frm.doc.customer, 'Test Customer 1',
- 'customer set in quotation');
- assert.equal(cur_frm.doc.items[0].item_code, 'Test Product 1',
- 'item set in quotation');
- assert.equal(cur_frm.doc.items[0].qty, 4,
- 'qty set in quotation');
- assert.equal(cur_frm.doc.items[0].prevdoc_docname, frappe.opportunity_name,
- 'opportunity set in quotation');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/academic_term/test_academic_term.js b/erpnext/education/doctype/academic_term/test_academic_term.js
deleted file mode 100644
index 383b65a..0000000
--- a/erpnext/education/doctype/academic_term/test_academic_term.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Testing Setup Module in Education
-QUnit.module('education');
-
-QUnit.test('Test: Academic Term', function(assert){
- assert.expect(4);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Academic Term', [
- {academic_year: '2016-17'},
- {term_name: "Semester 1"},
- {term_start_date: '2016-07-20'},
- {term_end_date:'2017-06-20'},
- ]);
- },
- () => {
- assert.ok(cur_frm.doc.academic_year=='2016-17');
- assert.ok(cur_frm.doc.term_name=='Semester 1');
- assert.ok(cur_frm.doc.term_start_date=='2016-07-20');
- assert.ok(cur_frm.doc.term_end_date=='2017-06-20');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/assessment_criteria/test_assessment_criteria.js b/erpnext/education/doctype/assessment_criteria/test_assessment_criteria.js
deleted file mode 100644
index 724c4da..0000000
--- a/erpnext/education/doctype/assessment_criteria/test_assessment_criteria.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// Education Assessment module
-QUnit.module('education');
-
-QUnit.test('Test: Assessment Criteria', function(assert){
- assert.expect(0);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Assessment Criteria', [
- {assessment_criteria: 'Pass'},
- {assessment_criteria_group: 'Reservation'}
- ]);
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/assessment_criteria_group/test_assessment_criteria_group.js b/erpnext/education/doctype/assessment_criteria_group/test_assessment_criteria_group.js
deleted file mode 100644
index ab27e63..0000000
--- a/erpnext/education/doctype/assessment_criteria_group/test_assessment_criteria_group.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// Education Assessment module
-QUnit.module('education');
-
-QUnit.test('Test: Assessment Criteria Group', function(assert){
- assert.expect(0);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Assessment Criteria Group', [
- {assessment_criteria_group: 'Reservation'}
- ]);
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/assessment_group/test_assessment_group.js b/erpnext/education/doctype/assessment_group/test_assessment_group.js
deleted file mode 100644
index 00e6309..0000000
--- a/erpnext/education/doctype/assessment_group/test_assessment_group.js
+++ /dev/null
@@ -1,65 +0,0 @@
-// Education Assessment module
-QUnit.module('education');
-
-QUnit.test('Test: Assessment Group', function(assert){
- assert.expect(4);
- let done = assert.async();
-
- frappe.run_serially([
- () => frappe.set_route('Tree', 'Assessment Group'),
-
- // Checking adding child without selecting any Node
- () => frappe.tests.click_button('New'),
- () => frappe.timeout(0.2),
- () => {assert.equal($(`.msgprint`).text(), "Select a group node first.", "Error message success");},
- () => frappe.tests.click_button('Close'),
- () => frappe.timeout(0.2),
-
- // Creating child nodes
- () => frappe.tests.click_link('All Assessment Groups'),
- () => frappe.map_group.make('Assessment-group-1'),
- () => frappe.map_group.make('Assessment-group-4', "All Assessment Groups", 1),
- () => frappe.tests.click_link('Assessment-group-4'),
- () => frappe.map_group.make('Assessment-group-5', "Assessment-group-3", 0),
-
- // Checking Edit button
- () => frappe.timeout(0.5),
- () => frappe.tests.click_link('Assessment-group-1'),
- () => frappe.tests.click_button('Edit'),
- () => frappe.timeout(0.5),
- () => {assert.deepEqual(frappe.get_route(), ["Form", "Assessment Group", "Assessment-group-1"], "Edit route checks");},
-
- // Deleting child Node
- () => frappe.set_route('Tree', 'Assessment Group'),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_link('Assessment-group-1'),
- () => frappe.tests.click_button('Delete'),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Yes'),
-
- // Checking Collapse and Expand button
- () => frappe.timeout(2),
- () => frappe.tests.click_link('Assessment-group-4'),
- () => frappe.click_button('Collapse'),
- () => frappe.tests.click_link('All Assessment Groups'),
- () => frappe.click_button('Collapse'),
- () => {assert.ok($('.opened').size() == 0, 'Collapsed');},
- () => frappe.click_button('Expand'),
- () => {assert.ok($('.opened').size() > 0, 'Expanded');},
-
- () => done()
- ]);
-});
-
-frappe.map_group = {
- make:function(assessment_group_name, parent_assessment_group = 'All Assessment Groups', is_group = 0){
- return frappe.run_serially([
- () => frappe.click_button('Add Child'),
- () => frappe.timeout(0.2),
- () => cur_dialog.set_value('is_group', is_group),
- () => cur_dialog.set_value('assessment_group_name', assessment_group_name),
- () => cur_dialog.set_value('parent_assessment_group', parent_assessment_group),
- () => frappe.click_button('Create New'),
- ]);
- }
-};
diff --git a/erpnext/education/doctype/assessment_plan/test_assessment_plan.js b/erpnext/education/doctype/assessment_plan/test_assessment_plan.js
deleted file mode 100644
index b0bff26..0000000
--- a/erpnext/education/doctype/assessment_plan/test_assessment_plan.js
+++ /dev/null
@@ -1,54 +0,0 @@
-// Testing Assessment Module in education
-QUnit.module('education');
-
-QUnit.test('Test: Assessment Plan', function(assert){
- assert.expect(6);
- let done = assert.async();
- let room_name, instructor_name, assessment_name;
-
- frappe.run_serially([
- () => frappe.db.get_value('Room', {'room_name': 'Room 1'}, 'name'),
- (room) => {room_name = room.message.name;}, // Fetching Room name
- () => frappe.db.get_value('Instructor', {'instructor_name': 'Instructor 1'}, 'name'),
- (instructor) => {instructor_name = instructor.message.name;}, // Fetching Instructor name
-
- () => {
- return frappe.tests.make('Assessment Plan', [
- {assessment_name: "Test-Mid-Term"},
- {assessment_group: 'Assessment-group-5'},
- {maximum_assessment_score: 100},
- {student_group: 'test-course-wise-group-2'},
- {course: 'Test_Sub'},
- {grading_scale: 'GTU'},
- {schedule_date: frappe.datetime.nowdate()},
- {room: room_name},
- {examiner: instructor_name},
- {supervisor: instructor_name},
- {from_time: "12:30:00"},
- {to_time: "2:30:00"}
- ]);
- },
-
- () => {
- assessment_name = cur_frm.doc.name; // Storing the name of current Assessment Plan
- assert.equal(cur_frm.doc.assessment_criteria[0].assessment_criteria, 'Pass', 'Assessment Criteria auto-filled correctly');
- assert.equal(cur_frm.doc.assessment_criteria[0].maximum_score, 100, 'Maximum score correctly set');
- }, // Checking if the table was auto-filled upon selecting appropriate fields
-
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Submit'),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.5),
- () => {assert.equal(cur_frm.doc.docstatus, 1, "Assessment Plan submitted successfully");},
-
- () => frappe.click_button('Assessment Result'), // Checking out Assessment Result button option
- () => frappe.timeout(0.5),
- () => {
- assert.deepEqual(frappe.get_route(), ["Form", "Assessment Result Tool"], 'Assessment Result properly linked');
- assert.equal(cur_frm.doc.assessment_plan, assessment_name, 'Assessment correctly set');
- assert.equal(cur_frm.doc.student_group, 'test-course-wise-group-2', 'Course for Assessment correctly set');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/assessment_result/test_assessment_result.js b/erpnext/education/doctype/assessment_result/test_assessment_result.js
deleted file mode 100644
index d4eb4b8..0000000
--- a/erpnext/education/doctype/assessment_result/test_assessment_result.js
+++ /dev/null
@@ -1,73 +0,0 @@
-// Education Assessment module
-QUnit.module('education');
-
-QUnit.test('Test: Assessment Result', function(assert){
- assert.expect(25);
- let done = assert.async();
- let student_list = [];
- let assessment_name;
- let tasks = []
-
- frappe.run_serially([
- // Saving Assessment Plan name
- () => frappe.db.get_value('Assessment Plan', {'assessment_name': 'Test-Mid-Term'}, 'name'),
- (assessment_plan) => {assessment_name = assessment_plan.message.name;},
- // Fetching list of Student for which Result is supposed to be set
- () => frappe.set_route('Form', 'Assessment Plan', assessment_name),
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Assessment Result'),
- () => frappe.timeout(1),
- () => cur_frm.refresh(),
- () => frappe.timeout(1),
- () => {
- $("tbody tr").each( function(i, input){
- student_list.push($(input).data().student);
- });
- },
-
- // Looping through each student in the list and setting up their score
- () => {
- student_list.forEach(index => {
- tasks.push(
- () => frappe.set_route('List', 'Assessment Result', 'List'),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('New'),
- () => frappe.timeout(0.5),
- () => cur_frm.set_value('student', index),
- () => cur_frm.set_value('assessment_plan', assessment_name),
- () => frappe.timeout(0.2),
- () => cur_frm.doc.details[0].score = (39 + (15 * student_list.indexOf(index))),
- () => cur_frm.save(),
- () => frappe.timeout(0.5),
-
- () => frappe.db.get_value('Assessment Plan', {'name': 'ASP00001'}, ['grading_scale', 'maximum_assessment_score']),
- (assessment_plan) => {
- assert.equal(cur_frm.doc.grading_scale, assessment_plan.message.grading_scale, 'Grading scale correctly fetched');
- assert.equal(cur_frm.doc.maximum_score, assessment_plan.message.maximum_assessment_score, 'Maximum score correctly fetched');
-
- frappe.call({
- method: "erpnext.education.api.get_grade",
- args: {
- "grading_scale": assessment_plan.message.grading_scale,
- "percentage": cur_frm.doc.total_score
- },
- callback: function(r){
- assert.equal(cur_frm.doc.grade, r.message, "Grade correctly calculated");
- }
- });
- },
-
- () => frappe.tests.click_button('Submit'),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.5),
- () => {assert.equal();},
- () => {assert.equal(cur_frm.doc.docstatus, 1, "Submitted successfully");},
- );
- });
- return frappe.run_serially(tasks);
- },
-
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/assessment_result_tool/test_assessment_result_tool.js b/erpnext/education/doctype/assessment_result_tool/test_assessment_result_tool.js
deleted file mode 100644
index 7ef5c68..0000000
--- a/erpnext/education/doctype/assessment_result_tool/test_assessment_result_tool.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// Education Assessment module
-QUnit.module('education');
-
-QUnit.test('Test: Assessment Result Tool', function(assert){
- assert.expect(1);
- let done = assert.async();
- let i, count = 0, assessment_name;
-
- frappe.run_serially([
- // Saving Assessment Plan name
- () => frappe.db.get_value('Assessment Plan', {'assessment_name': 'Test-Mid-Term'}, 'name'),
- (assessment_plan) => {assessment_name = assessment_plan.message.name;},
-
- () => frappe.set_route('Form', 'Assessment Plan', assessment_name),
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Assessment Result'),
- () => frappe.timeout(1),
- () => cur_frm.refresh(),
- () => frappe.timeout(1),
- () => {
- for(i = 2; i < $('tbody tr').size() * 4; i = (i + 4)){
- if(($(`tbody td:eq("${i}")`) != "") && ($(`tbody td:eq("${i+1}")`) != ""))
- count++;
- }
- assert.equal($('tbody tr').size(), count, 'All grades correctly displayed');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/course/test_course.js b/erpnext/education/doctype/course/test_course.js
deleted file mode 100644
index 2b6860c..0000000
--- a/erpnext/education/doctype/course/test_course.js
+++ /dev/null
@@ -1,36 +0,0 @@
-// Testing Setup Module in education
-QUnit.module('education');
-
-QUnit.test('test course', function(assert) {
- assert.expect(8);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Course', [
- {course_name: 'Test_Subject'},
- {course_code: 'Test_Sub'},
- {department: 'Test Department'},
- {course_abbreviation: 'Test_Sub'},
- {course_intro: 'Test Subject Intro'},
- {default_grading_scale: 'GTU'},
- {assessment_criteria: [
- [
- {assessment_criteria: 'Pass'},
- {weightage: 100}
- ]
- ]}
- ]);
- },
- () => {
- assert.ok(cur_frm.doc.course_name == 'Test_Subject', 'Course name correctly set');
- assert.ok(cur_frm.doc.course_code == 'Test_Sub', 'Course code correctly set');
- assert.ok(cur_frm.doc.department == 'Test Department', 'Department selected correctly');
- assert.ok(cur_frm.doc.course_abbreviation == 'Test_Sub');
- assert.ok(cur_frm.doc.course_intro == 'Test Subject Intro');
- assert.ok(cur_frm.doc.default_grading_scale == 'GTU', 'Grading scale selected correctly');
- assert.ok(cur_frm.doc.assessment_criteria[0].assessment_criteria == 'Pass', 'Assessment criteria selected correctly');
- assert.ok(cur_frm.doc.assessment_criteria[0].weightage == '100');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/education_settings/test_education_settings.js b/erpnext/education/doctype/education_settings/test_education_settings.js
deleted file mode 100644
index 990b0aa..0000000
--- a/erpnext/education/doctype/education_settings/test_education_settings.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-// Testing Setup Module in Education
-QUnit.module('education');
-
-QUnit.test("test: Education Settings", function (assert) {
- let done = assert.async();
-
- assert.expect(3);
-
- frappe.run_serially([
- () => frappe.set_route("List", "Education Settings"),
- () => frappe.timeout(0.4),
- () => {
- return frappe.tests.set_form_values(cur_frm, [
- {current_academic_year: '2016-17'},
- {current_academic_term: '2016-17 (Semester 1)'},
- {attendance_freeze_date: '2016-07-20'}
- ]);
- },
- () => {
- cur_frm.save();
- assert.ok(cur_frm.doc.current_academic_year=="2016-17");
- assert.ok(cur_frm.doc.current_academic_term=="2016-17 (Semester 1)");
- assert.ok(cur_frm.doc.attendance_freeze_date=="2016-07-20");
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/fees/test_fees.js b/erpnext/education/doctype/fees/test_fees.js
deleted file mode 100644
index 22e987e..0000000
--- a/erpnext/education/doctype/fees/test_fees.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Fees", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(1);
-
- frappe.run_serially('Fees', [
-
- // insert a new Fees
- () => {
- return frappe.tests.make('Fees', [
- {student: 'STUD00001'},
- {due_date: frappe.datetime.get_today()},
- {fee_structure: 'FS00001'}
- ]);
- },
- () => {
- assert.equal(cur_frm.doc.grand_total===cur_frm.doc.outstanding_amount);
- },
- () => frappe.timeout(0.3),
- () => cur_frm.save(),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => done()
- ]);
-
-});
diff --git a/erpnext/education/doctype/grading_scale/test_grading_scale.js b/erpnext/education/doctype/grading_scale/test_grading_scale.js
deleted file mode 100644
index fb56918..0000000
--- a/erpnext/education/doctype/grading_scale/test_grading_scale.js
+++ /dev/null
@@ -1,102 +0,0 @@
-// Education Assessment module
-QUnit.module('education');
-
-QUnit.test('Test: Grading Scale', function(assert){
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Grading Scale', [
- {grading_scale_name: 'GTU'},
- {description: 'The score will be set according to 100 based system.'},
- {intervals: [
- [
- {grade_code: 'AA'},
- {threshold: '95'},
- {grade_description: 'First Class + Distinction'}
- ],
- [
- {grade_code: 'AB'},
- {threshold: '90'},
- {grade_description: 'First Class'}
- ],
- [
- {grade_code: 'BB'},
- {threshold: '80'},
- {grade_description: 'Distinction'}
- ],
- [
- {grade_code: 'BC'},
- {threshold: '70'},
- {grade_description: 'Second Class'}
- ],
- [
- {grade_code: 'CC'},
- {threshold: '60'},
- {grade_description: 'Third Class'}
- ],
- [
- {grade_code: 'CD'},
- {threshold: '50'},
- {grade_description: 'Average'}
- ],
- [
- {grade_code: 'DD'},
- {threshold: '40'},
- {grade_description: 'Pass'}
- ],
- [
- {grade_code: 'FF'},
- {threshold: '0'},
- {grade_description: 'Fail'}
- ],
- ]}
- ]);
- },
- () => {
- return frappe.tests.make('Grading Scale', [
- {grading_scale_name: 'GTU-2'},
- {description: 'The score will be set according to 100 based system.'},
- {intervals: [
- [
- {grade_code: 'AA'},
- {threshold: '90'},
- {grade_description: 'Distinction'}
- ],
- [
- {grade_code: 'FF'},
- {threshold: '0'},
- {grade_description: 'Fail'}
- ]
- ]}
- ]);
- },
-
- () => {
- let grading_scale = ['GTU', 'GTU-2'];
- let tasks = [];
- grading_scale.forEach(index => {
- tasks.push(
- () => frappe.set_route('Form', 'Grading Scale', index),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Submit'),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Yes'),
- () => {assert.equal(cur_frm.doc.docstatus, 1, 'Submitted successfully');}
- );
- });
- return frappe.run_serially(tasks);
- },
-
- () => frappe.timeout(1),
- () => frappe.set_route('Form', 'Grading Scale','GTU-2'),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Cancel'),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.5),
- () => {assert.equal(cur_frm.doc.docstatus, 2, 'Cancelled successfully');},
-
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/guardian/test_guardian.js b/erpnext/education/doctype/guardian/test_guardian.js
deleted file mode 100644
index 1ea6dc2..0000000
--- a/erpnext/education/doctype/guardian/test_guardian.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Testing Student Module in education
-QUnit.module('education');
-
-QUnit.test('Test: Guardian', function(assert){
- assert.expect(9);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Guardian', [
- {guardian_name: 'Test Guardian'},
- {email_address: 'guardian@testmail.com'},
- {mobile_number: 9898980000},
- {alternate_number: 8989890000},
- {date_of_birth: '1982-07-22'},
- {education: 'Testing'},
- {occupation: 'Testing'},
- {designation: 'Testing'},
- {work_address: 'Testing address'}
- ]);
- },
- () => {
- assert.ok(cur_frm.doc.guardian_name == 'Test Guardian');
- assert.ok(cur_frm.doc.email_address == 'guardian@testmail.com');
- assert.ok(cur_frm.doc.mobile_number == 9898980000);
- assert.ok(cur_frm.doc.alternate_number == 8989890000);
- assert.ok(cur_frm.doc.date_of_birth == '1982-07-22');
- assert.ok(cur_frm.doc.education == 'Testing');
- assert.ok(cur_frm.doc.occupation == 'Testing');
- assert.ok(cur_frm.doc.designation == 'Testing');
- assert.ok(cur_frm.doc.work_address == 'Testing address');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/instructor/test_instructor.js b/erpnext/education/doctype/instructor/test_instructor.js
deleted file mode 100644
index c584f45..0000000
--- a/erpnext/education/doctype/instructor/test_instructor.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Testing Setup Module in education
-QUnit.module('education');
-
-QUnit.test('Test: Instructor', function(assert){
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make("Instructor", [
- {instructor_name: 'Instructor 1'},
- {department: 'Test Department'}
- ]);
- },
- () => {
- assert.ok(cur_frm.doc.instructor_name == 'Instructor 1');
- assert.ok(cur_frm.doc.department = 'Test Department');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/program/test_program.js b/erpnext/education/doctype/program/test_program.js
deleted file mode 100644
index b9ca41a..0000000
--- a/erpnext/education/doctype/program/test_program.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Testing Setup Module in education
-QUnit.module('education');
-
-QUnit.test('Test: Program', function(assert){
- assert.expect(6);
- let done = assert.async();
- let fee_structure_code;
- frappe.run_serially([
- () => {
- return frappe.tests.make('Program', [
- {program_name: 'Standard Test'},
- {program_code: 'Standard Test'},
- {department: 'Test Department'},
- {program_abbreviation: 'Standard Test'},
- {courses: [
- [
- {course: 'Test_Sub'},
- {required: true}
- ]
- ]}
- ]);
- },
-
- () => {
- assert.ok(cur_frm.doc.program_name == 'Standard Test');
- assert.ok(cur_frm.doc.program_code == 'Standard Test');
- assert.ok(cur_frm.doc.department == 'Test Department');
- assert.ok(cur_frm.doc.program_abbreviation == 'Standard Test');
- assert.ok(cur_frm.doc.courses[0].course == 'Test_Sub');
- assert.ok(cur_frm.doc.courses[0].required == true);
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/room/test_room.js b/erpnext/education/doctype/room/test_room.js
deleted file mode 100644
index fdcbe92..0000000
--- a/erpnext/education/doctype/room/test_room.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Testing Setup Module in Education
-QUnit.module('education');
-
-QUnit.test('Test: Room', function(assert){
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Room', [
- {room_name: 'Room 1'},
- {room_number: '1'},
- {seating_capacity: '60'},
- ]);
- },
- () => {
- assert.ok(cur_frm.doc.room_name == 'Room 1');
- assert.ok(cur_frm.doc.room_number = '1');
- assert.ok(cur_frm.doc.seating_capacity = '60');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/student_admission/test_student_admission.js b/erpnext/education/doctype/student_admission/test_student_admission.js
deleted file mode 100644
index e01791a..0000000
--- a/erpnext/education/doctype/student_admission/test_student_admission.js
+++ /dev/null
@@ -1,40 +0,0 @@
-// Testing Admission Module in Education
-QUnit.module('education');
-
-QUnit.test('Test: Student Admission', function(assert) {
- assert.expect(10);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Student Admission', [
- {academic_year: '2016-17'},
- {admission_start_date: '2016-04-20'},
- {admission_end_date: '2016-05-31'},
- {title: '2016-17 Admissions'},
- {enable_admission_application: 1},
- {introduction: 'Test intro'},
- {program_details: [
- [
- {'program': 'Standard Test'},
- {'application_fee': 1000},
- {'applicant_naming_series': 'AP'},
- ]
- ]}
- ]);
- },
- () => cur_frm.save(),
- () => {
- assert.ok(cur_frm.doc.academic_year == '2016-17');
- assert.ok(cur_frm.doc.admission_start_date == '2016-04-20');
- assert.ok(cur_frm.doc.admission_end_date == '2016-05-31');
- assert.ok(cur_frm.doc.title == '2016-17 Admissions');
- assert.ok(cur_frm.doc.enable_admission_application == 1);
- assert.ok(cur_frm.doc.introduction == 'Test intro');
- assert.ok(cur_frm.doc.program_details[0].program == 'Standard Test', 'Program correctly selected');
- assert.ok(cur_frm.doc.program_details[0].application_fee == 1000);
- assert.ok(cur_frm.doc.program_details[0].applicant_naming_series == 'AP');
- assert.ok(cur_frm.doc.route == 'admissions/2016-17-Admissions', "Route successfully set");
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/student_applicant/tests/test_student_applicant.js b/erpnext/education/doctype/student_applicant/tests/test_student_applicant.js
deleted file mode 100644
index fa67977..0000000
--- a/erpnext/education/doctype/student_applicant/tests/test_student_applicant.js
+++ /dev/null
@@ -1,95 +0,0 @@
-// Testing Admission module in Education
-QUnit.module('education');
-
-QUnit.test('Test: Student Applicant', function(assert){
- assert.expect(24);
- let done = assert.async();
- let guradian_auto_code;
- let guardian_name;
- frappe.run_serially([
- () => frappe.set_route('List', 'Guardian'),
- () => frappe.timeout(0.5),
- () => {$(`a:contains("Test Guardian"):visible`)[0].click();},
- () => frappe.timeout(1),
- () => {
- guardian_name = cur_frm.doc.guardian_name;
- guradian_auto_code = frappe.get_route()[2];
- },
- // Testing data entry for Student Applicant
- () => {
- return frappe.tests.make('Student Applicant',[
- {first_name: 'Fname'},
- {middle_name: 'Mname'},
- {last_name: 'Lname'},
- {program: 'Standard Test'},
- {student_admission: '2016-17 Admissions'},
- {academic_year: '2016-17'},
- {date_of_birth: '1995-07-20'},
- {student_email_id: 'test@testmail.com'},
- {gender: 'Male'},
- {student_mobile_number: '9898980000'},
- {blood_group: 'O+'},
- {address_line_1: 'Test appt, Test Society,'},
- {address_line_2: 'Test district, Test city.'},
- {city: 'Test'},
- {state: 'Test'},
- {pincode: '400086'}
- ]);
- },
- // Entry in Guardian child table
- () => $('a:contains("Guardian Details"):visible').click(),
- () => $('.btn:contains("Add Row"):visible').click(),
- () => {
- cur_frm.get_field("guardians").grid.grid_rows[0].doc.guardian = guradian_auto_code;
- cur_frm.get_field("guardians").grid.grid_rows[0].doc.relation = "Father";
- cur_frm.get_field("guardians").grid.grid_rows[0].doc.guardian_name = guardian_name;
- $('a:contains("Guardian Details"):visible').click();
- },
- // Entry in Sibling child table
- () => $('a:contains("Sibling Details"):visible').click(),
- () => $('.btn:contains("Add Row"):visible').click(),
- () => {
- cur_frm.get_field("siblings").grid.grid_rows[0].doc.full_name = "Test Name";
- cur_frm.get_field("siblings").grid.grid_rows[0].doc.gender = "Male";
- cur_frm.get_field("siblings").grid.grid_rows[0].doc.institution = "Test Institution";
- cur_frm.get_field("siblings").grid.grid_rows[0].doc.program = "Test Program";
- cur_frm.get_field("siblings").grid.grid_rows[0].doc.date_of_birth = "1995-07-20";
- $('span.hidden-xs.octicon.octicon-triangle-up').click();
- cur_frm.save();
- },
- () => {
- assert.ok(cur_frm.doc.first_name == 'Fname');
- assert.ok(cur_frm.doc.middle_name == 'Mname');
- assert.ok(cur_frm.doc.last_name == 'Lname');
- assert.ok(cur_frm.doc.program == 'Standard Test', 'Program selected correctly');
- assert.ok(cur_frm.doc.student_admission == '2016-17 Admissions', 'Student Admission entry correctly selected');
- assert.ok(cur_frm.doc.academic_year == '2016-17');
- assert.ok(cur_frm.doc.date_of_birth == '1995-07-20');
- assert.ok(cur_frm.doc.student_email_id == 'test@testmail.com');
- assert.ok(cur_frm.doc.gender == 'Male');
- assert.ok(cur_frm.doc.student_mobile_number == '9898980000');
- assert.ok(cur_frm.doc.blood_group == 'O+');
- assert.ok(cur_frm.doc.address_line_1 == 'Test appt, Test Society,');
- assert.ok(cur_frm.doc.address_line_2 == 'Test district, Test city.');
- assert.ok(cur_frm.doc.city == 'Test');
- assert.ok(cur_frm.doc.state == 'Test');
- assert.ok(cur_frm.doc.pincode == '400086');
- },
- () => frappe.timeout(1),
- () => $('a:contains("Guardian Details"):visible').click(),
- () => {
- assert.ok(cur_frm.get_field("guardians").grid.grid_rows[0].doc.guardian == guradian_auto_code, 'Guardian correctly selected from dropdown');
- assert.ok(cur_frm.get_field("guardians").grid.grid_rows[0].doc.relation == 'Father');
- assert.ok(cur_frm.get_field("guardians").grid.grid_rows[0].doc.guardian_name == guardian_name, 'Guardian name was correctly retrieved');
- },
- () => $('a:contains("Sibling Details"):visible').click(),
- () => {
- assert.ok(cur_frm.get_field("siblings").grid.grid_rows[0].doc.full_name == 'Test Name');
- assert.ok(cur_frm.get_field("siblings").grid.grid_rows[0].doc.gender == 'Male');
- assert.ok(cur_frm.get_field("siblings").grid.grid_rows[0].doc.institution == 'Test Institution');
- assert.ok(cur_frm.get_field("siblings").grid.grid_rows[0].doc.program == 'Test Program');
- assert.ok(cur_frm.get_field("siblings").grid.grid_rows[0].doc.date_of_birth == '1995-07-20');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/student_applicant/tests/test_student_applicant_dummy_data.js b/erpnext/education/doctype/student_applicant/tests/test_student_applicant_dummy_data.js
deleted file mode 100644
index 03101e4..0000000
--- a/erpnext/education/doctype/student_applicant/tests/test_student_applicant_dummy_data.js
+++ /dev/null
@@ -1,87 +0,0 @@
-QUnit.module('Admission');
-
-QUnit.test('Make Students', function(assert){
- assert.expect(0);
- let done = assert.async();
- let tasks = [];
- let loop = [1,2,3,4];
- let fname;
-
- frappe.run_serially([
- // Making School House to be used in this test and later
- () => frappe.set_route('Form', 'School House/New School House'),
- () => frappe.timeout(0.5),
- () => cur_frm.doc.house_name = 'Test_house',
- () => cur_frm.save(),
-
- // Making Student Applicant entries
- () => {
- loop.forEach(index => {
- tasks.push(() => {
- fname = "Fname" + index;
-
- return frappe.tests.make('Student Applicant', [
- {first_name: fname},
- {middle_name: "Mname"},
- {last_name: "Lname"},
- {program: "Standard Test"},
- {student_admission: "2016-17 Admissions"},
- {date_of_birth: '1995-08-20'},
- {student_email_id: ('test' + (index+3) + '@testmail.com')},
- {gender: 'Male'},
- {student_mobile_number: (9898980000 + index)},
- {blood_group: 'O+'},
- {address_line_1: 'Test appt, Test Society,'},
- {address_line_2: 'Test district, Test city.'},
- {city: 'Test'},
- {state: 'Test'},
- {pincode: '395007'}
- ]);
- });
- });
- return frappe.run_serially(tasks);
- },
-
- // Using Program Enrollment Tool to enroll all dummy student at once
- () => frappe.set_route('Form', 'Program Enrollment Tool'),
- () => {
- cur_frm.set_value("get_students_from", "Student Applicants");
- cur_frm.set_value("academic_year", "2016-17");
- cur_frm.set_value("program", "Standard Test");
- },
- () => frappe.tests.click_button("Get Students"),
- () => frappe.timeout(1),
- () => frappe.tests.click_button("Enroll Students"),
- () => frappe.timeout(1.5),
- () => frappe.tests.click_button("Close"),
-
- // Submitting required data for each enrolled Student
- () => {
- tasks = [];
- loop.forEach(index => {
- tasks.push(
- () => {fname = "Fname" + index + " Mname Lname";},
- () => frappe.set_route('List', 'Program Enrollment/List'),
- () => frappe.timeout(0.6),
- () => frappe.tests.click_link(fname),
- () => frappe.timeout(0.4),
- () => {
- cur_frm.set_value('program', 'Standard Test');
- cur_frm.set_value('student_category', 'Reservation');
- cur_frm.set_value('student_batch_name', 'A');
- cur_frm.set_value('academic_year', '2016-17');
- cur_frm.set_value('academic_term', '2016-17 (Semester 1)');
- cur_frm.set_value('school_house', 'Test_house');
- },
- () => cur_frm.save(),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.5)
- );
- });
- return frappe.run_serially(tasks);
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/student_applicant/tests/test_student_applicant_options.js b/erpnext/education/doctype/student_applicant/tests/test_student_applicant_options.js
deleted file mode 100644
index daa36e7..0000000
--- a/erpnext/education/doctype/student_applicant/tests/test_student_applicant_options.js
+++ /dev/null
@@ -1,110 +0,0 @@
-// Testing Admission module in Education
-QUnit.module('education');
-
-QUnit.test('test student applicant', function(assert){
- assert.expect(11);
- let done = assert.async();
- let testing_status;
- frappe.run_serially([
- () => frappe.set_route('List', 'Student Applicant'),
- () => frappe.timeout(0.5),
- () => {$(`a:contains("Fname Mname Lname"):visible`)[0].click();},
-
- // Checking different options
- // 1. Moving forward with Submit
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.5),
- () => {
- testing_status = $('span.indicator.orange').text();
- assert.ok(testing_status.indexOf('Submit this document to confirm') == -1); // checking if submit has been successfull
- },
-
- // 2. Cancelling the Submit request
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Cancel'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.5),
- () => {
- testing_status = $('h1.editable-title').text();
- assert.ok(testing_status.indexOf('Cancelled') != -1); // checking if cancel request has been successfull
- },
-
- // 3. Checking Amend option
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Amend'),
- () => cur_frm.doc.student_email_id = "test2@testmail.com", // updating email id since same id again is not allowed
- () => cur_frm.save(),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'), // Submitting again after amend
- () => {
- testing_status = $('span.indicator.orange').text();
- assert.ok(testing_status.indexOf('Submit this document to confirm') == -1); // checking if submit has been successfull after amend
- },
-
- // Checking different Application status option
- () => {
- testing_status = $('h1.editable-title').text();
- assert.ok(testing_status.indexOf('Applied') != -1); // checking if Applied has been successfull
- },
- () => cur_frm.set_value('application_status', "Rejected"), // Rejected Status
- () => frappe.tests.click_button('Update'),
- () => {
- testing_status = $('h1.editable-title').text();
- assert.ok(testing_status.indexOf('Rejected') != -1); // checking if Rejected has been successfull
- },
- () => cur_frm.set_value('application_status', "Admitted"), // Admitted Status
- () => frappe.tests.click_button('Update'),
- () => {
- testing_status = $('h1.editable-title').text();
- assert.ok(testing_status.indexOf('Admitted') != -1); // checking if Admitted has been successfull
- },
- () => cur_frm.set_value('application_status', "Approved"), // Approved Status
- () => frappe.tests.click_button('Update'),
- () => {
- testing_status = $('h1.editable-title').text();
- assert.ok(testing_status.indexOf('Approved') != -1); // checking if Approved has been successfull
- },
-
- // Clicking on Enroll button should add the applicant's entry in Student doctype, and take you to Program Enrollment page
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Enroll'),
- () => frappe.timeout(0.5),
- () => {
- assert.ok(frappe.get_route()[0] == 'Form'); // Checking if the current page is Program Enrollment page or not
- assert.ok(frappe.get_route()[1] == 'Program Enrollment');
- },
-
- // Routing to Student List to check if the Applicant's entry has been made or not
- () => frappe.timeout(0.5),
- () => frappe.set_route('List', 'Student'),
- () => frappe.timeout(0.5),
- () => {$(`a:contains("Fname Mname Lname"):visible`)[0].click();},
- () => frappe.timeout(0.5),
- () => {assert.ok(($(`h1.editable-title`).text()).indexOf('Enabled') != -1, 'Student entry successfully created');}, // Checking if the Student entry has been enabled
- // Enrolling the Student into a Program
- () => {$('.form-documents .row:nth-child(1) .col-xs-6:nth-child(1) .octicon-plus').click();},
- () => frappe.timeout(1),
- () => cur_frm.set_value('program', 'Standard Test'),
- () => frappe.timeout(1),
- () => {
- cur_frm.set_value('student_category', 'Reservation');
- cur_frm.set_value('student_batch_name', 'A');
- cur_frm.set_value('academic_year', '2016-17');
- cur_frm.set_value('academic_term', '2016-17 (Semester 1)');
- cur_frm.set_value('school_house', 'Test_house');
- },
- () => cur_frm.save(),
-
- // Submitting Program Enrollment form for our Test Student
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => {
- assert.ok(cur_frm.doc.docstatus == 1, "Program enrollment successfully submitted");
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/student_attendance/test_student_attendance.js b/erpnext/education/doctype/student_attendance/test_student_attendance.js
deleted file mode 100644
index 3d30b09..0000000
--- a/erpnext/education/doctype/student_attendance/test_student_attendance.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// Testing Attendance Module in Education
-QUnit.module('education');
-
-QUnit.test('Test: Student Attendance', function(assert){
- assert.expect(2);
- let done = assert.async();
- let student_code;
-
- frappe.run_serially([
- () => frappe.db.get_value('Student', {'student_email_id': 'test2@testmail.com'}, 'name'),
- (student) => {student_code = student.message.name;}, // fetching student code from db
-
- () => {
- return frappe.tests.make('Student Attendance', [
- {student: student_code},
- {date: frappe.datetime.nowdate()},
- {student_group: "test-batch-wise-group-2"},
- {status: "Absent"}
- ]);
- },
-
- () => frappe.timeout(0.5),
- () => {assert.equal(cur_frm.doc.status, "Absent", "Attendance correctly saved");},
-
- () => frappe.timeout(0.5),
- () => cur_frm.set_value("status", "Present"),
- () => {assert.equal(cur_frm.doc.status, "Present", "Attendance correctly saved");},
-
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/student_attendance_tool/test_student_attendance_tool.js b/erpnext/education/doctype/student_attendance_tool/test_student_attendance_tool.js
deleted file mode 100644
index b66d839..0000000
--- a/erpnext/education/doctype/student_attendance_tool/test_student_attendance_tool.js
+++ /dev/null
@@ -1,85 +0,0 @@
-// Testing Attendance Module in Education
-QUnit.module('education');
-
-QUnit.test('Test: Student Attendace Tool', function(assert){
- assert.expect(10);
- let done = assert.async();
- let i, count = 0;
-
- frappe.run_serially([
- () => frappe.timeout(0.2),
- () => frappe.set_route('Form', 'Student Attendance Tool'),
- () => frappe.timeout(0.5),
-
- () => {
- if(cur_frm.doc.based_on == 'Student Group' || cur_frm.doc.based_on == 'Course Schedule'){
- cur_frm.doc.based_on = 'Student Group';
- assert.equal(1, 1, 'Attendance basis correctly set');
- cur_frm.set_value("group_based_on", 'Batch');
- cur_frm.set_value("student_group", "test-batch-wise-group");
- cur_frm.set_value("date", frappe.datetime.nowdate());
- }
- },
- () => frappe.timeout(0.5),
- () => {
- assert.equal($('input.students-check').size(), 5, "Student list based on batch correctly fetched");
- assert.equal(frappe.datetime.nowdate(), cur_frm.doc.date, 'Current date correctly set');
-
- cur_frm.set_value("student_group", "test-batch-wise-group-2");
- assert.equal($('input.students-check').size(), 5, "Student list based on batch 2 correctly fetched");
-
- cur_frm.set_value("group_based_on", 'Course');
-
- cur_frm.set_value("student_group", "test-course-wise-group");
- assert.equal($('input.students-check').size(), 5, "Student list based on course correctly fetched");
-
- cur_frm.set_value("student_group", "test-course-wise-group-2");
- assert.equal($('input.students-check').size(), 5, "Student list based on course 2 correctly fetched");
- },
-
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Check all'), // Marking all Student as checked
- () => {
- for(i = 0; i < $('input.students-check').size(); i++){
- if($('input.students-check')[i].checked == true)
- count++;
- }
-
- if(count == $('input.students-check').size())
- assert.equal($('input.students-check').size(), count, "All students marked checked");
- },
-
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Uncheck all'), // Marking all Student as unchecked
- () => {
- count = 0;
- for(i = 0; i < $('input.students-check').size(); i++){
- if(!($('input.students-check')[i].checked))
- count++;
- }
-
- if(count == $('input.students-check').size())
- assert.equal($('input.students-check').size(), count, "All students marked checked");
- },
-
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Check all'),
- () => frappe.tests.click_button('Mark Attendance'),
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(1),
- () => {
- assert.equal($('.msgprint').text(), "Attendance has been marked successfully.", "Attendance successfully marked");
- frappe.tests.click_button('Close');
- },
-
- () => frappe.timeout(1),
- () => frappe.set_route('List', 'Student Attendance/List'),
- () => frappe.timeout(1),
- () => {
- assert.equal(cur_list.data.length, count, "Attendance list created");
- },
-
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/student_batch_name/test_student_batch_name.js b/erpnext/education/doctype/student_batch_name/test_student_batch_name.js
deleted file mode 100644
index 6c761b8..0000000
--- a/erpnext/education/doctype/student_batch_name/test_student_batch_name.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// Testing Setup Module in Education
-QUnit.module('education');
-
-QUnit.test('Test: Student Batch Name', function(assert){
- assert.expect(1);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Student Batch Name', [
- {batch_name: 'A'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- assert.ok(cur_frm.doc.batch_name=='A');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/student_category/test_student_category.js b/erpnext/education/doctype/student_category/test_student_category.js
deleted file mode 100644
index 01f50e2..0000000
--- a/erpnext/education/doctype/student_category/test_student_category.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// Testing Setup Module in Education
-QUnit.module('education');
-
-QUnit.test('Test: Student Category', function(assert){
- assert.expect(1);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Student Category', [
- {category: 'Reservation'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- assert.ok(cur_frm.doc.name=='Reservation');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/student_group/test_student_group.js b/erpnext/education/doctype/student_group/test_student_group.js
deleted file mode 100644
index 4c7e47b..0000000
--- a/erpnext/education/doctype/student_group/test_student_group.js
+++ /dev/null
@@ -1,56 +0,0 @@
-// Testing Student Module in Education
-QUnit.module('education');
-
-QUnit.test('Test: Student Group', function(assert){
- assert.expect(2);
- let done = assert.async();
- let group_based_on = ["test-batch-wise-group", "test-course-wise-group"];
- let tasks = [];
-
- frappe.run_serially([
- // Creating a Batch and Course based group
- () => {
- return frappe.tests.make('Student Group', [
- {academic_year: '2016-17'},
- {academic_term: '2016-17 (Semester 1)'},
- {program: "Standard Test"},
- {group_based_on: 'Batch'},
- {student_group_name: group_based_on[0]},
- {max_strength: 10},
- {batch: 'A'}
- ]);
- },
- () => {
- return frappe.tests.make('Student Group', [
- {academic_year: '2016-17'},
- {academic_term: '2016-17 (Semester 1)'},
- {program: "Standard Test"},
- {group_based_on: 'Course'},
- {student_group_name: group_based_on[1]},
- {max_strength: 10},
- {batch: 'A'},
- {course: 'Test_Sub'},
- ]);
- },
-
- // Populating the created group with Students
- () => {
- tasks = [];
- group_based_on.forEach(index => {
- tasks.push(
- () => frappe.timeout(0.5),
- () => frappe.set_route("Form", ('Student Group/' + index)),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Get Students'),
- () => frappe.timeout(1),
- () => {
- assert.equal(cur_frm.doc.students.length, 5, 'Successfully fetched list of students');
- },
- );
- });
- return frappe.run_serially(tasks);
- },
-
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/student_group_creation_tool/test_student_group_creation_tool.js b/erpnext/education/doctype/student_group_creation_tool/test_student_group_creation_tool.js
deleted file mode 100644
index fa612ba..0000000
--- a/erpnext/education/doctype/student_group_creation_tool/test_student_group_creation_tool.js
+++ /dev/null
@@ -1,84 +0,0 @@
-QUnit.module('education');
-
-QUnit.test('Test: Student Group Creation Tool', function(assert){
- assert.expect(5);
- let done = assert.async();
- let instructor_code;
-
- frappe.run_serially([
- // Saving Instructor code beforehand
- () => frappe.db.get_value('Instructor', {'instructor_name': 'Instructor 1'}, 'name'),
- (instructor) => {instructor_code = instructor.message.name;},
-
- // Setting up the creation tool to generate and save Student Group
- () => frappe.set_route('Form', 'Student Group Creation Tool'),
- () => frappe.timeout(0.5),
- () => {
- cur_frm.set_value("academic_year", "2016-17");
- cur_frm.set_value("academic_term", "2016-17 (Semester 1)");
- cur_frm.set_value("program", "Standard Test");
- frappe.tests.click_button('Get Courses');
- },
- () => frappe.timeout(1),
- () => {
- let no_of_courses = $('input.grid-row-check.pull-left').size() - 1;
- assert.equal(cur_frm.doc.courses.length, no_of_courses, 'Successfully created groups using the tool');
- },
-
- () => {
- let d, grid, grid_row;
-
- for(d = 0; d < cur_frm.doc.courses.length; d++)
- {
- grid = cur_frm.get_field("courses").grid;
- grid_row = grid.get_row(d).toggle_view(true);
- if(grid_row.doc.student_group_name == 'Standard Test/A/2016-17 (Semester 1)'){
- grid_row.doc.max_strength = 10;
- grid_row.doc.student_group_name = "test-batch-wise-group-2";
- $(`.octicon.octicon-triangle-up`).click();
- continue;
- }
- else if(grid_row.doc.student_group_name == 'Test_Sub/Standard Test/2016-17 (Semester 1)'){
- grid_row.doc.max_strength = 10;
- grid_row.doc.student_group_name = "test-course-wise-group-2";
- $(`.octicon.octicon-triangle-up`).click();
- continue;
- }
- }
- },
-
- // Generating Student Group
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button("Create Student Groups"),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button("Close"),
-
- // Goin to the generated group to set up student and instructor list
- () => {
- let group_name = ['Student Group/test-batch-wise-group-2', 'Student Group/test-course-wise-group-2'];
- let tasks = [];
- group_name.forEach(index => {
- tasks.push(
- () => frappe.timeout(1),
- () => frappe.set_route("Form", index),
- () => frappe.timeout(0.5),
- () => {
- assert.equal(cur_frm.doc.students.length, 5, 'Successfully fetched list of students');
- },
- () => frappe.timeout(0.5),
- () => {
- d = cur_frm.add_child('instructors');
- d.instructor = instructor_code;
- cur_frm.save();
- },
- () => {
- assert.equal(cur_frm.doc.instructors.length, 1, 'Instructor detail stored successfully');
- },
- );
- });
- return frappe.run_serially(tasks);
- },
-
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/student_leave_application/test_student_leave_application.js b/erpnext/education/doctype/student_leave_application/test_student_leave_application.js
deleted file mode 100644
index 6bbf17b..0000000
--- a/erpnext/education/doctype/student_leave_application/test_student_leave_application.js
+++ /dev/null
@@ -1,69 +0,0 @@
-// Testing Attendance Module in Education
-QUnit.module('education');
-
-QUnit.test('Test: Student Leave Application', function(assert){
- assert.expect(4);
- let done = assert.async();
- let student_code;
- let leave_code;
- frappe.run_serially([
- () => frappe.db.get_value('Student', {'student_email_id': 'test2@testmail.com'}, 'name'),
- (student) => {student_code = student.message.name;}, // fetching student code from db
-
- () => {
- return frappe.tests.make('Student Leave Application', [
- {student: student_code},
- {from_date: '2017-08-02'},
- {to_date: '2017-08-04'},
- {mark_as_present: 0},
- {reason: "Sick Leave."}
- ]);
- },
- () => frappe.tests.click_button('Submit'), // Submitting the leave application
- () => frappe.timeout(0.7),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.7),
- () => {
- assert.equal(cur_frm.doc.docstatus, 1, "Submitted leave application");
- leave_code = frappe.get_route()[2];
- },
- () => frappe.tests.click_button('Cancel'), // Cancelling the leave application
- () => frappe.timeout(0.7),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(1),
- () => {assert.equal(cur_frm.doc.docstatus, 2, "Cancelled leave application");},
- () => frappe.tests.click_button('Amend'), // Amending the leave application
- () => frappe.timeout(1),
- () => {
- cur_frm.doc.mark_as_present = 1;
- cur_frm.save();
- },
- () => frappe.timeout(0.7),
- () => frappe.tests.click_button('Submit'),
- () => frappe.timeout(0.7),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.7),
- () => {assert.equal(cur_frm.doc.amended_from, leave_code, "Amended successfully");},
-
- () => frappe.timeout(0.5),
- () => {
- return frappe.tests.make('Student Leave Application', [
- {student: student_code},
- {from_date: '2017-08-07'},
- {to_date: '2017-08-09'},
- {mark_as_present: 0},
- {reason: "Sick Leave."}
- ]);
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.timeout(0.7),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.7),
- () => {
- assert.equal(cur_frm.doc.docstatus, 1, "Submitted leave application");
- leave_code = frappe.get_route()[2];
- },
-
- () => done()
- ]);
-});
diff --git a/erpnext/education/doctype/student_log/test_student_log.js b/erpnext/education/doctype/student_log/test_student_log.js
deleted file mode 100644
index 4c90c5f..0000000
--- a/erpnext/education/doctype/student_log/test_student_log.js
+++ /dev/null
@@ -1,35 +0,0 @@
-// Testing Student Module in Education
-QUnit.module('education');
-
-QUnit.test('Test: Student Log', function(assert){
- assert.expect(9);
- let done = assert.async();
- let student_code;
- frappe.run_serially([
- () => frappe.db.get_value('Student', {'student_email_id': 'test2@testmail.com'}, 'name'),
- (student) => {student_code = student.message.name;},
- () => {
- return frappe.tests.make("Student Log", [
- {student: student_code},
- {academic_year: '2016-17'},
- {academic_term: '2016-17 (Semester 1)'},
- {program: "Standard Test"},
- {date: '2017-07-31'},
- {student_batch: 'A'},
- {log: 'This is Test log.'}
- ]);
- },
- () => {
- assert.equal(cur_frm.doc.student, student_code, 'Student code was fetched properly');
- assert.equal(cur_frm.doc.student_name, 'Fname Mname Lname', 'Student name was correctly auto-fetched');
- assert.equal(cur_frm.doc.type, 'General', 'Default type selected');
- assert.equal(cur_frm.doc.academic_year, '2016-17');
- assert.equal(cur_frm.doc.academic_term, '2016-17 (Semester 1)');
- assert.equal(cur_frm.doc.program, 'Standard Test', 'Program correctly selected');
- assert.equal(cur_frm.doc.student_batch, 'A');
- assert.equal(cur_frm.doc.date, '2017-07-31');
- assert.equal(cur_frm.doc.log, 'This is Test log.');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/appointment_letter/appointment_letter.py b/erpnext/hr/doctype/appointment_letter/appointment_letter.py
index 0120188..71327bf 100644
--- a/erpnext/hr/doctype/appointment_letter/appointment_letter.py
+++ b/erpnext/hr/doctype/appointment_letter/appointment_letter.py
@@ -12,14 +12,15 @@
@frappe.whitelist()
def get_appointment_letter_details(template):
body = []
- intro= frappe.get_list("Appointment Letter Template",
- fields = ['introduction', 'closing_notes'],
- filters={'name': template
- })[0]
- content = frappe.get_list("Appointment Letter content",
- fields = ['title', 'description'],
- filters={'parent': template
- })
+ intro = frappe.get_list('Appointment Letter Template',
+ fields=['introduction', 'closing_notes'],
+ filters={'name': template}
+ )[0]
+ content = frappe.get_all('Appointment Letter content',
+ fields=['title', 'description'],
+ filters={'parent': template},
+ order_by='idx'
+ )
body.append(intro)
body.append({'description': content})
return body
diff --git a/erpnext/hr/doctype/appraisal/test_appraisal.js b/erpnext/hr/doctype/appraisal/test_appraisal.js
deleted file mode 100644
index fb1354c..0000000
--- a/erpnext/hr/doctype/appraisal/test_appraisal.js
+++ /dev/null
@@ -1,57 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Expense Claim [HR]", function (assert) {
- assert.expect(3);
- let done = assert.async();
- let employee_name;
-
- frappe.run_serially([
- // Creating Appraisal
- () => frappe.set_route('List','Appraisal','List'),
- () => frappe.timeout(0.3),
- () => frappe.click_button('Make a new Appraisal'),
- () => {
- cur_frm.set_value('kra_template','Test Appraisal 1'),
- cur_frm.set_value('start_date','2017-08-21'),
- cur_frm.set_value('end_date','2017-09-21');
- },
- () => frappe.timeout(1),
- () => frappe.model.set_value('Appraisal Goal','New Appraisal Goal 1','score',4),
- () => frappe.model.set_value('Appraisal Goal','New Appraisal Goal 1','score_earned',2),
- () => frappe.model.set_value('Appraisal Goal','New Appraisal Goal 2','score',4),
- () => frappe.model.set_value('Appraisal Goal','New Appraisal Goal 2','score_earned',2),
- () => frappe.timeout(1),
- () => frappe.db.get_value('Employee', {'employee_name': 'Test Employee 1'}, 'name'),
- (r) => {
- employee_name = r.message.name;
- },
-
- () => frappe.timeout(1),
- () => cur_frm.set_value('employee',employee_name),
- () => cur_frm.set_value('employee_name','Test Employee 1'),
- () => cur_frm.set_value('company','For Testing'),
- () => frappe.click_button('Calculate Total Score'),
- () => frappe.timeout(1),
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => cur_frm.save(),
-
- // Submitting the Appraisal
- () => frappe.click_button('Submit'),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(3),
-
- // Checking if the appraisal is correctly set for the employee
- () => {
- assert.equal('Submitted',cur_frm.get_field('status').value,
- 'Appraisal is submitted');
-
- assert.equal('Test Employee 1',cur_frm.get_field('employee_name').value,
- 'Appraisal is created for correct employee');
-
- assert.equal(4,cur_frm.get_field('total_score').value,
- 'Total score is correctly calculated');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/appraisal_template/test_appraisal_template.js b/erpnext/hr/doctype/appraisal_template/test_appraisal_template.js
deleted file mode 100644
index 3eb64e0..0000000
--- a/erpnext/hr/doctype/appraisal_template/test_appraisal_template.js
+++ /dev/null
@@ -1,29 +0,0 @@
-QUnit.module('hr');
-QUnit.test("Test: Appraisal Template [HR]", function (assert) {
- assert.expect(1);
- let done = assert.async();
- frappe.run_serially([
- // Job Opening creation
- () => {
- frappe.tests.make('Appraisal Template', [
- { kra_title: 'Test Appraisal 1'},
- { description: 'This is just a test'},
- { goals: [
- [
- { kra: 'Design'},
- { per_weightage: 50}
- ],
- [
- { kra: 'Code creation'},
- { per_weightage: 50}
- ]
- ]},
- ]);
- },
- () => frappe.timeout(10),
- () => {
- assert.equal('Test Appraisal 1',cur_frm.doc.kra_title, 'Appraisal name correctly set');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/attendance/test_attendance.js b/erpnext/hr/doctype/attendance/test_attendance.js
deleted file mode 100644
index b3e7fef..0000000
--- a/erpnext/hr/doctype/attendance/test_attendance.js
+++ /dev/null
@@ -1,39 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Attendance [HR]", function (assert) {
- assert.expect(4);
- let done = assert.async();
-
- frappe.run_serially([
- // test attendance creation for one employee
- () => frappe.set_route("List", "Attendance", "List"),
- () => frappe.timeout(0.5),
- () => frappe.new_doc("Attendance"),
- () => frappe.timeout(1),
- () => assert.equal("Attendance", cur_frm.doctype,
- "Form for new Attendance opened successfully."),
- // set values in form
- () => cur_frm.set_value("company", "For Testing"),
- () => {
- frappe.db.get_value('Employee', {'employee_name':'Test Employee 1'}, 'name', function(r) {
- cur_frm.set_value("employee", r.name)
- });
- },
- () => frappe.timeout(1),
- () => cur_frm.save(),
- () => frappe.timeout(1),
- // check docstatus of attendance before submit [Draft]
- () => assert.equal("0", cur_frm.doc.docstatus,
- "attendance is currently drafted"),
- // check docstatus of attendance after submit [Present]
- () => cur_frm.savesubmit(),
- () => frappe.timeout(0.5),
- () => frappe.click_button('Yes'),
- () => assert.equal("1", cur_frm.doc.docstatus,
- "attendance is saved after submit"),
- // check if auto filled date is present day
- () => assert.equal(frappe.datetime.nowdate(), cur_frm.doc.attendance_date,
- "attendance for Present day is marked"),
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/employee/test_employee.js b/erpnext/hr/doctype/employee/test_employee.js
deleted file mode 100644
index 3a41458..0000000
--- a/erpnext/hr/doctype/employee/test_employee.js
+++ /dev/null
@@ -1,40 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Employee [HR]", function (assert) {
- assert.expect(4);
- let done = assert.async();
- // let today_date = frappe.datetime.nowdate();
- let employee_creation = (name, joining_date, birth_date) => {
- frappe.run_serially([
- // test employee creation
- () => {
- frappe.tests.make('Employee', [
- { employee_name: name},
- { salutation: 'Mr'},
- { company: 'For Testing'},
- { date_of_joining: joining_date},
- { date_of_birth: birth_date},
- { employment_type: 'Test Employment Type'},
- { holiday_list: 'Test Holiday List'},
- { branch: 'Test Branch'},
- { department: 'Test Department'},
- { designation: 'Test Designation'}
- ]);
- },
- () => frappe.timeout(2),
- () => {
- assert.ok(cur_frm.get_field('employee_name').value==name,
- 'Name of an Employee is correctly set');
- assert.ok(cur_frm.get_field('gender').value=='Male',
- 'Gender of an Employee is correctly set');
- },
- ]);
- };
- frappe.run_serially([
- () => employee_creation('Test Employee 1','2017-04-01','1992-02-02'),
- () => frappe.timeout(10),
- () => employee_creation('Test Employee 3','2017-04-01','1992-02-02'),
- () => frappe.timeout(10),
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.js b/erpnext/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.js
deleted file mode 100644
index 48d4344..0000000
--- a/erpnext/hr/doctype/employee_attendance_tool/test_employee_attendance_tool.js
+++ /dev/null
@@ -1,61 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Employee attendance tool [HR]", function (assert) {
- assert.expect(2);
- let done = assert.async();
- let today_date = frappe.datetime.nowdate();
- let date_of_attendance = frappe.datetime.add_days(today_date, -2); // previous day
-
- frappe.run_serially([
- // create employee
- () => {
- return frappe.tests.make('Employee', [
- {salutation: "Mr"},
- {employee_name: "Test Employee 2"},
- {company: "For Testing"},
- {date_of_joining: frappe.datetime.add_months(today_date, -2)}, // joined 2 month from now
- {date_of_birth: frappe.datetime.add_months(today_date, -240)}, // age is 20 years
- {employment_type: "Test Employment type"},
- {holiday_list: "Test Holiday list"},
- {branch: "Test Branch"},
- {department: "Test Department"},
- {designation: "Test Designation"}
- ]);
- },
- () => frappe.set_route("Form", "Employee Attendance Tool"),
- () => frappe.timeout(0.5),
- () => assert.equal("Employee Attendance Tool", cur_frm.doctype,
- "Form for Employee Attendance Tool opened successfully."),
- // set values in form
- () => cur_frm.set_value("date", date_of_attendance),
- () => cur_frm.set_value("branch", "Test Branch"),
- () => cur_frm.set_value("department", "Test Department"),
- () => cur_frm.set_value("company", "For Testing"),
- () => frappe.timeout(1),
- () => frappe.click_button('Check all'),
- () => frappe.click_button('Mark Present'),
- // check if attendance is marked
- () => frappe.set_route("List", "Attendance", "List"),
- () => frappe.timeout(1),
- () => {
- return frappe.call({
- method: "frappe.client.get_list",
- args: {
- doctype: "Employee",
- filters: {
- "branch": "Test Branch",
- "department": "Test Department",
- "company": "For Testing",
- "status": "Active"
- }
- },
- callback: function(r) {
- let marked_attendance = cur_list.data.filter(d => d.attendance_date == date_of_attendance);
- assert.equal(marked_attendance.length, r.message.length,
- 'all the attendance are marked for correct date');
- }
- });
- },
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/employment_type/test_employment_type.js b/erpnext/hr/doctype/employment_type/test_employment_type.js
deleted file mode 100644
index fd7c6a1..0000000
--- a/erpnext/hr/doctype/employment_type/test_employment_type.js
+++ /dev/null
@@ -1,22 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Employment type [HR]", function (assert) {
- assert.expect(1);
- let done = assert.async();
-
- frappe.run_serially([
- // test employment type creation
- () => frappe.set_route("List", "Employment Type", "List"),
- () => frappe.new_doc("Employment Type"),
- () => frappe.timeout(1),
- () => frappe.quick_entry.dialog.$wrapper.find('.edit-full').click(),
- () => frappe.timeout(1),
- () => cur_frm.set_value("employee_type_name", "Test Employment type"),
- // save form
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => assert.equal("Test Employment type", cur_frm.doc.employee_type_name,
- 'name of employment type correctly saved'),
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.js b/erpnext/hr/doctype/expense_claim/test_expense_claim.js
deleted file mode 100644
index 2529fae..0000000
--- a/erpnext/hr/doctype/expense_claim/test_expense_claim.js
+++ /dev/null
@@ -1,44 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Expense Claim [HR]", function (assert) {
- assert.expect(3);
- let done = assert.async();
- let employee_name;
- let d;
- frappe.run_serially([
- // Creating Expense Claim
- () => frappe.set_route('List','Expense Claim','List'),
- () => frappe.timeout(0.3),
- () => frappe.click_button('New'),
- () => {
- cur_frm.set_value('is_paid',1),
- cur_frm.set_value('expenses',[]),
- d = frappe.model.add_child(cur_frm.doc,'Expense Claim Detail','expenses'),
- d.expense_date = '2017-08-01',
- d.expense_type = 'Test Expense Type 1',
- d.description = 'This is just to test Expense Claim',
- d.amount = 2000,
- d.sanctioned_amount=2000,
- refresh_field('expenses');
- },
- () => frappe.timeout(1),
- () => cur_frm.set_value('employee','Test Employee 1'),
- () => cur_frm.set_value('company','For Testing'),
- () => cur_frm.set_value('payable_account','Creditors - FT'),
- () => cur_frm.set_value('cost_center','Main - FT'),
- () => cur_frm.set_value('mode_of_payment','Cash'),
- () => cur_frm.save(),
- () => frappe.click_button('Submit'),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(3),
-
- // Checking if the amount is correctly reimbursed for the employee
- () => {
- assert.equal("Test Employee 1",cur_frm.doc.employee, 'Employee name set correctly');
- assert.equal(1, cur_frm.doc.is_paid, 'Expense is paid as required');
- assert.equal(2000, cur_frm.doc.total_amount_reimbursed, 'Amount is reimbursed correctly');
-
- },
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/expense_claim_type/test_expense_claim_type.js b/erpnext/hr/doctype/expense_claim_type/test_expense_claim_type.js
deleted file mode 100644
index 3c9ed35..0000000
--- a/erpnext/hr/doctype/expense_claim_type/test_expense_claim_type.js
+++ /dev/null
@@ -1,29 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Expense Claim Type [HR]", function (assert) {
- assert.expect(1);
- let done = assert.async();
- frappe.run_serially([
- // Creating a Expense Claim Type
- () => {
- frappe.tests.make('Expense Claim Type', [
- { expense_type: 'Test Expense Type 1'},
- { description:'This is just a test'},
- { accounts: [
- [
- { company: 'For Testing'},
- { default_account: 'Rounded Off - FT'}
- ]
- ]},
- ]);
- },
- () => frappe.timeout(5),
-
- // Checking if the created type is present in the list
- () => {
- assert.equal('Test Expense Type 1', cur_frm.doc.expense_type,
- 'Expense Claim Type created successfully');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/holiday_list/test_holiday_list.js b/erpnext/hr/doctype/holiday_list/test_holiday_list.js
deleted file mode 100644
index ce76614..0000000
--- a/erpnext/hr/doctype/holiday_list/test_holiday_list.js
+++ /dev/null
@@ -1,42 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Holiday list [HR]", function (assert) {
- assert.expect(3);
- let done = assert.async();
- let date = frappe.datetime.add_months(frappe.datetime.nowdate(), -2); // date 2 months from now
-
- frappe.run_serially([
- // test holiday list creation
- () => frappe.set_route("List", "Holiday List", "List"),
- () => frappe.new_doc("Holiday List"),
- () => frappe.timeout(1),
- () => cur_frm.set_value("holiday_list_name", "Test Holiday list"),
- () => cur_frm.set_value("from_date", date),
- () => cur_frm.set_value("weekly_off", "Sunday"), // holiday list for sundays
- () => frappe.click_button('Get Weekly Off Dates'),
-
- // save form
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => assert.equal("Test Holiday list", cur_frm.doc.holiday_list_name,
- 'name of holiday list correctly saved'),
-
- // check if holiday list contains correct days
- () => {
- var list = cur_frm.doc.holidays;
- var list_length = list.length;
- var i = 0;
- for ( ; i < list_length; i++)
- if (list[i].description != 'Sunday') break;
- assert.equal(list_length, i, "all holidays are sundays in holiday list");
- },
-
- // check if to_date is set one year from from_date
- () => {
- var date_year_later = frappe.datetime.add_days(frappe.datetime.add_months(date, 12), -1); // date after one year
- assert.equal(date_year_later, cur_frm.doc.to_date,
- "to date set correctly");
- },
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/interview_feedback/test_interview_feedback.py b/erpnext/hr/doctype/interview_feedback/test_interview_feedback.py
index 4185f28..d2ec5b9 100644
--- a/erpnext/hr/doctype/interview_feedback/test_interview_feedback.py
+++ b/erpnext/hr/doctype/interview_feedback/test_interview_feedback.py
@@ -59,7 +59,7 @@
}, 'average_rating')
# 1. average should be reflected in Interview Detail.
- self.assertEqual(avg_on_interview_detail, round(feedback_1.average_rating))
+ self.assertEqual(avg_on_interview_detail, feedback_1.average_rating)
'''For Second Interviewer Feedback'''
interviewer = interview.interview_details[1].interviewer
diff --git a/erpnext/hr/doctype/job_applicant/test_job_applicant.js b/erpnext/hr/doctype/job_applicant/test_job_applicant.js
deleted file mode 100644
index 741a182..0000000
--- a/erpnext/hr/doctype/job_applicant/test_job_applicant.js
+++ /dev/null
@@ -1,28 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Job Opening [HR]", function (assert) {
- assert.expect(2);
- let done = assert.async();
-
- frappe.run_serially([
- // Job Applicant creation
- () => {
- frappe.tests.make('Job Applicant', [
- { applicant_name: 'Utkarsh Goswami'},
- { email_id: 'goswamiutkarsh0@gmail.com'},
- { job_title: 'software-developer'},
- { cover_letter: 'Highly skilled in designing, testing, and developing software.'+
- ' This is just a test.'}
- ]);
- },
- () => frappe.timeout(4),
- () => frappe.set_route('List','Job Applicant'),
- () => frappe.timeout(3),
- () => {
- assert.ok(cur_list.data.length==1, 'Job Applicant created successfully');
- assert.ok(cur_list.data[0].name=='Utkarsh Goswami - goswamiutkarsh0@gmail.com - software-developer',
- 'Correct job applicant with valid job title');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/job_offer/test_job_offer.js b/erpnext/hr/doctype/job_offer/test_job_offer.js
deleted file mode 100644
index 5339b9c..0000000
--- a/erpnext/hr/doctype/job_offer/test_job_offer.js
+++ /dev/null
@@ -1,51 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Job Offer [HR]", function (assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- // Job Offer Creation
- () => {
- frappe.tests.make('Job Offer', [
- { job_applicant: 'Utkarsh Goswami - goswamiutkarsh0@gmail.com - software-developer'},
- { applicant_name: 'Utkarsh Goswami'},
- { status: 'Accepted'},
- { designation: 'Software Developer'},
- { offer_terms: [
- [
- {offer_term: 'Responsibilities'},
- {value: 'Design, installation, testing and maintenance of software systems.'}
- ],
- [
- {offer_term: 'Department'},
- {value: 'Research & Development'}
- ],
- [
- {offer_term: 'Probationary Period'},
- {value: 'The Probation period is for 3 months.'}
- ]
- ]},
- ]);
- },
- () => frappe.timeout(10),
- () => frappe.click_button('Submit'),
- () => frappe.timeout(2),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(5),
- // To check if the fields are correctly set
- () => {
- assert.ok(cur_frm.get_field('status').value=='Accepted',
- 'Status of job offer is correct');
- assert.ok(cur_frm.get_field('designation').value=='Software Developer',
- 'Designation of applicant is correct');
- },
- () => frappe.set_route('List','Job Offer','List'),
- () => frappe.timeout(2),
- // Checking the submission of and Job Offer
- () => {
- assert.ok(cur_list.data[0].docstatus==1,'Job Offer Submitted successfully');
- },
- () => frappe.timeout(2),
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/job_opening/test_job_opening.js b/erpnext/hr/doctype/job_opening/test_job_opening.js
deleted file mode 100644
index cc2f027..0000000
--- a/erpnext/hr/doctype/job_opening/test_job_opening.js
+++ /dev/null
@@ -1,26 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Job Opening [HR]", function (assert) {
- assert.expect(2);
- let done = assert.async();
-
- frappe.run_serially([
- // Job Opening creation
- () => {
- frappe.tests.make('Job Opening', [
- { job_title: 'Software Developer'},
- { description:
- 'You might be responsible for writing and coding individual'+
- ' programmes or providing an entirely new software resource.'}
- ]);
- },
- () => frappe.timeout(4),
- () => frappe.set_route('List','Job Opening'),
- () => frappe.timeout(3),
- () => {
- assert.ok(cur_list.data.length==1, 'Job Opening created successfully');
- assert.ok(cur_list.data[0].job_title=='Software Developer', 'Job title Correctly set');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.js b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.js
deleted file mode 100644
index d5364fc..0000000
--- a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.js
+++ /dev/null
@@ -1,41 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Leave allocation [HR]", function (assert) {
- assert.expect(3);
- let done = assert.async();
- let today_date = frappe.datetime.nowdate();
-
- frappe.run_serially([
- // test creating leave alloction
- () => frappe.set_route("List", "Leave Allocation", "List"),
- () => frappe.new_doc("Leave Allocation"),
- () => frappe.timeout(1),
- () => {
- frappe.db.get_value('Employee', {'employee_name':'Test Employee 1'}, 'name', function(r) {
- cur_frm.set_value("employee", r.name)
- });
- },
- () => frappe.timeout(1),
- () => cur_frm.set_value("leave_type", "Test Leave type"),
- () => cur_frm.set_value("to_date", frappe.datetime.add_months(today_date, 2)), // for two months
- () => cur_frm.set_value("description", "This is just for testing"),
- () => cur_frm.set_value("new_leaves_allocated", 2),
- () => frappe.click_check('Add unused leaves from previous allocations'),
- // save form
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => cur_frm.savesubmit(),
- () => frappe.timeout(1),
- () => assert.equal("Confirm", cur_dialog.title,
- 'confirmation for leave alloction shown'),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(1),
- // check auto filled from date
- () => assert.equal(today_date, cur_frm.doc.from_date,
- "from date correctly set"),
- // check for total leaves
- () => assert.equal(cur_frm.doc.unused_leaves + 2, cur_frm.doc.total_leaves_allocated,
- "total leave calculation is correctly set"),
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.js b/erpnext/hr/doctype/leave_application/test_leave_application.js
deleted file mode 100644
index 0866b0b..0000000
--- a/erpnext/hr/doctype/leave_application/test_leave_application.js
+++ /dev/null
@@ -1,42 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Leave application [HR]", function (assert) {
- assert.expect(4);
- let done = assert.async();
- let today_date = frappe.datetime.nowdate();
- let leave_date = frappe.datetime.add_days(today_date, 1); // leave for tomorrow
-
- frappe.run_serially([
- // test creating leave application
- () => frappe.db.get_value('Employee', {'employee_name':'Test Employee 1'}, 'name'),
- (employee) => {
- return frappe.tests.make('Leave Application', [
- {leave_type: "Test Leave type"},
- {from_date: leave_date}, // for today
- {to_date: leave_date},
- {half_day: 1},
- {employee: employee.message.name},
- {follow_via_email: 0}
- ]);
- },
-
- () => frappe.timeout(1),
- () => frappe.click_button('Actions'),
- () => frappe.click_link('Approve'), // approve the application [as administrator]
- () => frappe.click_button('Yes'),
- () => frappe.timeout(1),
- () => assert.ok(cur_frm.doc.docstatus,
- "leave application submitted after approval"),
-
- // check auto filled posting date [today]
-
- () => assert.equal(today_date, cur_frm.doc.posting_date,
- "posting date correctly set"),
- () => frappe.set_route("List", "Leave Application", "List"),
- () => frappe.timeout(1),
- // // check approved application in list
- () => assert.deepEqual(["Test Employee 1", 1], [cur_list.data[0].employee_name, cur_list.data[0].docstatus]),
- // "leave for correct employee is submitted"),
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/leave_block_list/test_leave_block_list.js b/erpnext/hr/doctype/leave_block_list/test_leave_block_list.js
deleted file mode 100644
index b39601b..0000000
--- a/erpnext/hr/doctype/leave_block_list/test_leave_block_list.js
+++ /dev/null
@@ -1,27 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Leave block list [HR]", function (assert) {
- assert.expect(1);
- let done = assert.async();
- let today_date = frappe.datetime.nowdate();
-
- frappe.run_serially([
- // test leave block list creation
- () => frappe.set_route("List", "Leave Block List", "List"),
- () => frappe.new_doc("Leave Block List"),
- () => frappe.timeout(1),
- () => cur_frm.set_value("leave_block_list_name", "Test Leave block list"),
- () => cur_frm.set_value("company", "For Testing"),
- () => frappe.click_button('Add Row'),
- () => {
- cur_frm.fields_dict.leave_block_list_dates.grid.grid_rows[0].doc.block_date = today_date;
- cur_frm.fields_dict.leave_block_list_dates.grid.grid_rows[0].doc.reason = "Blocked leave test";
- },
- // save form
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => assert.equal("Test Leave block list", cur_frm.doc.leave_block_list_name,
- 'name of blocked leave list correctly saved'),
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.js b/erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.js
deleted file mode 100644
index 9d37327..0000000
--- a/erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.js
+++ /dev/null
@@ -1,50 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Leave control panel [HR]", function (assert) {
- assert.expect(2);
- let done = assert.async();
- let today_date = frappe.datetime.nowdate();
-
- frappe.run_serially([
- // test leave allocation using leave control panel
- () => frappe.set_route("Form", "Leave Control Panel"),
- () => frappe.timeout(1),
- () => cur_frm.set_value("leave_type", "Test Leave type"),
- () => cur_frm.set_value("company", "For Testing"),
- () => cur_frm.set_value("employment_type", "Test Employment Type"),
- () => cur_frm.set_value("branch", "Test Branch"),
- () => cur_frm.set_value("department", "Test Department"),
- () => cur_frm.set_value("designation", "Test Designation"),
- () => cur_frm.set_value("from_date", frappe.datetime.add_months(today_date, -2)),
- () => cur_frm.set_value("to_date", frappe.datetime.add_days(today_date, -1)), // for two months [not today]
- () => cur_frm.set_value("no_of_days", 3),
- // allocate leaves
- () => frappe.click_button('Allocate'),
- () => frappe.timeout(1),
- () => assert.equal("Message", cur_dialog.title, "leave alloction message shown"),
- () => frappe.click_button('Close'),
- () => frappe.set_route("List", "Leave Allocation", "List"),
- () => frappe.timeout(1),
- () => {
- return frappe.call({
- method: "frappe.client.get_list",
- args: {
- doctype: "Employee",
- filters: {
- "branch": "Test Branch",
- "department": "Test Department",
- "company": "For Testing",
- "designation": "Test Designation",
- "status": "Active"
- }
- },
- callback: function(r) {
- let leave_allocated = cur_list.data.filter(d => d.leave_type == "Test Leave type");
- assert.equal(r.message.length, leave_allocated.length,
- 'leave allocation successfully done for all the employees');
- }
- });
- },
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/leave_type/test_leave_type.js b/erpnext/hr/doctype/leave_type/test_leave_type.js
deleted file mode 100644
index db910cd..0000000
--- a/erpnext/hr/doctype/leave_type/test_leave_type.js
+++ /dev/null
@@ -1,22 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Leave type [HR]", function (assert) {
- assert.expect(1);
- let done = assert.async();
-
- frappe.run_serially([
- // test leave type creation
- () => frappe.set_route("List", "Leave Type", "List"),
- () => frappe.new_doc("Leave Type"),
- () => frappe.timeout(1),
- () => cur_frm.set_value("leave_type_name", "Test Leave type"),
- () => cur_frm.set_value("max_continuous_days_allowed", "5"),
- () => frappe.click_check('Is Carry Forward'),
- // save form
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => assert.equal("Test Leave type", cur_frm.doc.leave_type_name,
- 'leave type correctly saved'),
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/training_event/tests/test_training_event.js b/erpnext/hr/doctype/training_event/tests/test_training_event.js
deleted file mode 100644
index 08031a1..0000000
--- a/erpnext/hr/doctype/training_event/tests/test_training_event.js
+++ /dev/null
@@ -1,59 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Training Event [HR]", function (assert) {
- assert.expect(5);
- let done = assert.async();
- let employee_name;
-
- frappe.run_serially([
- // Creation of Training Event
- () => frappe.db.get_value('Employee', {'employee_name': 'Test Employee 1'}, 'name'),
- (r) => {
- employee_name = r.message.name;
- },
- () => {
- frappe.tests.make('Training Event', [
- { event_name: 'Test Training Event 1'},
- { location: 'Mumbai'},
- { start_time: '2017-09-01 11:00:0'},
- { end_time: '2017-09-01 17:00:0'},
- { introduction: 'This is just a test'},
- { employees: [
- [
- {employee: employee_name},
- {employee_name: 'Test Employee 1'},
- {attendance: 'Optional'}
- ]
- ]},
- ]);
- },
- () => frappe.timeout(7),
- () => frappe.click_button('Submit'),
- () => frappe.timeout(1),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(8),
- () => {
- // To check if the fields are correctly set
- assert.ok(cur_frm.get_field('event_name').value == 'Test Training Event 1',
- 'Event created successfully');
-
- assert.ok(cur_frm.get_field('event_status').value=='Scheduled',
- 'Status of event is correctly set');
-
- assert.ok(cur_frm.doc.employees[0].employee_name=='Test Employee 1',
- 'Attendee Employee is correctly set');
-
- assert.ok(cur_frm.doc.employees[0].attendance=='Optional',
- 'Attendance is correctly set');
- },
-
- () => frappe.set_route('List','Training Event','List'),
- () => frappe.timeout(2),
- // Checking the submission of Training Event
- () => {
- assert.ok(cur_list.data[0].docstatus==1,'Training Event Submitted successfully');
- },
- () => frappe.timeout(2),
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/training_feedback/test_training_feedback.js b/erpnext/hr/doctype/training_feedback/test_training_feedback.js
deleted file mode 100644
index 5c825ae..0000000
--- a/erpnext/hr/doctype/training_feedback/test_training_feedback.js
+++ /dev/null
@@ -1,51 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Training Feedback [HR]", function (assert) {
- assert.expect(3);
- let done = assert.async();
- let employee_name;
-
- frappe.run_serially([
- // Creating Training Feedback
- () => frappe.set_route('List','Training Feedback','List'),
- () => frappe.timeout(0.3),
- () => frappe.click_button('Make a new Training Feedback'),
- () => frappe.timeout(1),
- () => frappe.db.get_value('Employee', {'employee_name': 'Test Employee 1'}, 'name'),
- (r) => {
- employee_name = r.message.name;
- },
- () => cur_frm.set_value('employee',employee_name),
- () => cur_frm.set_value('employee_name','Test Employee 1'),
- () => cur_frm.set_value('training_event','Test Training Event 1'),
- () => cur_frm.set_value('event_name','Test Training Event 1'),
- () => cur_frm.set_value('feedback','Great Experience. This is just a test.'),
- () => frappe.timeout(1),
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => cur_frm.save(),
-
- // Submitting the feedback
- () => frappe.click_button('Submit'),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(3),
-
- // Checking if the feedback is given by correct employee
- () => {
- assert.equal('Test Employee 1',cur_frm.get_field('employee_name').value,
- 'Feedback is given by correct employee');
-
- assert.equal('Test Training Event 1',cur_frm.get_field('training_event').value,
- 'Feedback is given for correct event');
- },
-
- () => frappe.set_route('List','Training Feedback','List'),
- () => frappe.timeout(2),
-
- // Checking the submission of Training Result
- () => {
- assert.ok(cur_list.data[0].docstatus==1,'Training Feedback Submitted successfully');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/hr/doctype/training_result_employee/test_training_result.js b/erpnext/hr/doctype/training_result_employee/test_training_result.js
deleted file mode 100644
index 3f39750..0000000
--- a/erpnext/hr/doctype/training_result_employee/test_training_result.js
+++ /dev/null
@@ -1,52 +0,0 @@
-QUnit.module('hr');
-
-QUnit.test("Test: Training Result [HR]", function (assert) {
- assert.expect(5);
- let done = assert.async();
- frappe.run_serially([
- // Creating Training Result
- () => frappe.set_route('List','Training Result','List'),
- () => frappe.timeout(0.3),
- () => frappe.click_button('Make a new Training Result'),
- () => {
- cur_frm.set_value('training_event','Test Training Event 1');
- },
- () => frappe.timeout(1),
- () => frappe.model.set_value('Training Result Employee','New Training Result Employee 1','hours',4),
- () => frappe.model.set_value('Training Result Employee','New Training Result Employee 1','grade','A'),
- () => frappe.model.set_value('Training Result Employee','New Training Result Employee 1','comments','Nice Seminar'),
- () => frappe.timeout(1),
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => cur_frm.save(),
-
- // Submitting the Training Result
- () => frappe.click_button('Submit'),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(4),
-
- // Checking if the fields are correctly set
- () => {
- assert.equal('Test Training Event 1',cur_frm.get_field('training_event').value,
- 'Training Result is created');
-
- assert.equal('Test Employee 1',cur_frm.doc.employees[0].employee_name,
- 'Training Result is created for correct employee');
-
- assert.equal(4,cur_frm.doc.employees[0].hours,
- 'Hours field is correctly calculated');
-
- assert.equal('A',cur_frm.doc.employees[0].grade,
- 'Grade field is correctly set');
- },
-
- () => frappe.set_route('List','Training Result','List'),
- () => frappe.timeout(2),
-
- // Checking the submission of Training Result
- () => {
- assert.ok(cur_list.data[0].docstatus==1,'Training Result Submitted successfully');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py
index 37ea3fd..5017126 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py
+++ b/erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py
@@ -56,9 +56,14 @@
ms.submit()
s_id = ms.get_pending_data(data_type = "id", item_name = i.item_name, s_date = expected_dates[1])
- test = make_maintenance_visit(source_name = ms.name, item_name = "_Test Item", s_id = s_id)
+
+ # Check if item is mapped in visit.
+ test_map_visit = make_maintenance_visit(source_name = ms.name, item_name = "_Test Item", s_id = s_id)
+ self.assertEqual(len(test_map_visit.purposes), 1)
+ self.assertEqual(test_map_visit.purposes[0].item_name, "_Test Item")
+
visit = frappe.new_doc('Maintenance Visit')
- visit = test
+ visit = test_map_visit
visit.maintenance_schedule = ms.name
visit.maintenance_schedule_detail = s_id
visit.completion_status = "Partially Completed"
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
index 6f6ca61..d2197a6 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
@@ -47,7 +47,7 @@
frm.set_value({ status: 'Draft' });
}
if (frm.doc.__islocal) {
- frm.clear_table("purposes");
+ frm.doc.maintenance_type == 'Unscheduled' && frm.clear_table("purposes");
frm.set_value({ mntc_date: frappe.datetime.get_today() });
}
},
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 2cd8f8c..f82d9a0 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -922,7 +922,7 @@
rm_item_exists = True
if bom.item.lower() == item.lower() or \
bom.item.lower() == cstr(frappe.db.get_value("Item", item, "variant_of")).lower():
- rm_item_exists = True
+ rm_item_exists = True
if not rm_item_exists:
frappe.throw(_("BOM {0} does not belong to Item {1}").format(bom_no, item))
diff --git a/erpnext/manufacturing/doctype/bom/test_bom.js b/erpnext/manufacturing/doctype/bom/test_bom.js
deleted file mode 100644
index 98a9198..0000000
--- a/erpnext/manufacturing/doctype/bom/test_bom.js
+++ /dev/null
@@ -1,63 +0,0 @@
-QUnit.test("test: item", function (assert) {
- assert.expect(1);
- let done = assert.async();
-
- frappe.run_serially([
- // test item creation
- () => frappe.set_route("List", "Item"),
-
- // Create a BOM for a laptop
- () => frappe.tests.make(
- "BOM", [
- {item: "Laptop"},
- {quantity: 1},
- {with_operations: 1},
- {company: "For Testing"},
- {operations: [
- [
- {operation: "Assemble CPU"},
- {time_in_mins: 60},
- ],
- [
- {operation: "Assemble Keyboard"},
- {time_in_mins: 30},
- ],
- [
- {operation: "Assemble Screen"},
- {time_in_mins: 30},
- ]
- ]},
- {scrap_items: [
- [
- {item_code: "Scrap item"}
- ]
- ]},
- {items: [
- [
- {item_code: "CPU"},
- {qty: 1}
- ],
- [
- {item_code: "Keyboard"},
- {qty: 1}
- ],
- [
- {item_code: "Screen"},
- {qty: 1}
- ]
- ]},
- ]
- ),
- () => cur_frm.savesubmit(),
- () => frappe.timeout(1),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(1),
-
- () => {
- assert.ok(cur_frm.doc.operating_cost + cur_frm.doc.raw_material_cost -
- cur_frm.doc.scrap_material_cost == cur_frm.doc.total_cost, 'Total_Cost calculated correctly');
- },
-
- () => done()
- ]);
-});
diff --git a/erpnext/manufacturing/doctype/bom_operation/bom_operation.json b/erpnext/manufacturing/doctype/bom_operation/bom_operation.json
index ec617f3..c7be7ef 100644
--- a/erpnext/manufacturing/doctype/bom_operation/bom_operation.json
+++ b/erpnext/manufacturing/doctype/bom_operation/bom_operation.json
@@ -11,6 +11,7 @@
"col_break1",
"workstation",
"time_in_mins",
+ "fixed_time",
"costing_section",
"hour_rate",
"base_hour_rate",
@@ -80,6 +81,14 @@
"reqd": 1
},
{
+ "default": "0",
+ "description": "Operation time does not depend on quantity to produce",
+ "fieldname": "fixed_time",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Fixed Time"
+ },
+ {
"fieldname": "operating_cost",
"fieldtype": "Currency",
"in_list_view": 1,
@@ -177,12 +186,13 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2021-09-13 16:45:01.092868",
+ "modified": "2021-12-15 03:00:00.473173",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Operation",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
- "sort_order": "DESC"
+ "sort_order": "DESC",
+ "states": []
}
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.js b/erpnext/manufacturing/doctype/job_card/job_card.js
index dac7b36..d85b8a6 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.js
+++ b/erpnext/manufacturing/doctype/job_card/job_card.js
@@ -76,6 +76,7 @@
frm.trigger("prepare_timer_buttons");
}
+ frm.trigger("setup_quality_inspection");
if (frm.doc.work_order) {
frappe.db.get_value('Work Order', frm.doc.work_order,
'transfer_material_against').then((r) => {
@@ -86,6 +87,22 @@
}
},
+ setup_quality_inspection: function(frm) {
+ let quality_inspection_field = frm.get_docfield("quality_inspection");
+ quality_inspection_field.get_route_options_for_new_doc = function(frm) {
+ return {
+ "inspection_type": "In Process",
+ "reference_type": "Job Card",
+ "reference_name": frm.doc.name,
+ "item_code": frm.doc.production_item,
+ "item_name": frm.doc.item_name,
+ "item_serial_no": frm.doc.serial_no,
+ "batch_no": frm.doc.batch_no,
+ "quality_inspection_template": frm.doc.quality_inspection_template,
+ };
+ };
+ },
+
setup_corrective_job_card: function(frm) {
frm.add_custom_button(__('Corrective Job Card'), () => {
let operations = frm.doc.sub_operations.map(d => d.sub_operation).concat(frm.doc.operation);
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.json b/erpnext/manufacturing/doctype/job_card/job_card.json
index 6528199..5a071f1 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.json
+++ b/erpnext/manufacturing/doctype/job_card/job_card.json
@@ -19,6 +19,7 @@
"serial_no",
"column_break_12",
"wip_warehouse",
+ "quality_inspection_template",
"quality_inspection",
"project",
"batch_no",
@@ -408,11 +409,18 @@
"no_copy": 1,
"options": "Job Card Scrap Item",
"print_hide": 1
+ },
+ {
+ "fetch_from": "operation.quality_inspection_template",
+ "fieldname": "quality_inspection_template",
+ "fieldtype": "Link",
+ "label": "Quality Inspection Template",
+ "options": "Quality Inspection Template"
}
],
"is_submittable": 1,
"links": [],
- "modified": "2021-11-12 10:15:03.572401",
+ "modified": "2021-11-24 19:17:40.879235",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Job Card",
diff --git a/erpnext/manufacturing/doctype/operation/operation.json b/erpnext/manufacturing/doctype/operation/operation.json
index 10a97ed..753552c 100644
--- a/erpnext/manufacturing/doctype/operation/operation.json
+++ b/erpnext/manufacturing/doctype/operation/operation.json
@@ -13,6 +13,7 @@
"is_corrective_operation",
"job_card_section",
"create_job_card_based_on_batch_size",
+ "quality_inspection_template",
"column_break_6",
"batch_size",
"sub_operations_section",
@@ -92,15 +93,22 @@
"fieldname": "is_corrective_operation",
"fieldtype": "Check",
"label": "Is Corrective Operation"
+ },
+ {
+ "fieldname": "quality_inspection_template",
+ "fieldtype": "Link",
+ "label": "Quality Inspection Template",
+ "options": "Quality Inspection Template"
}
],
"icon": "fa fa-wrench",
"index_web_pages_for_search": 1,
"links": [],
- "modified": "2021-01-12 15:09:23.593338",
+ "modified": "2021-11-24 19:15:24.357187",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Operation",
+ "naming_rule": "Set by user",
"owner": "Administrator",
"permissions": [
{
diff --git a/erpnext/manufacturing/doctype/operation/test_operation.js b/erpnext/manufacturing/doctype/operation/test_operation.js
deleted file mode 100644
index fd7783f..0000000
--- a/erpnext/manufacturing/doctype/operation/test_operation.js
+++ /dev/null
@@ -1,49 +0,0 @@
-QUnit.test("test: operation", function (assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- // test operation creation
- () => frappe.set_route("List", "Operation"),
-
- // Create a Keyboard operation
- () => {
- return frappe.tests.make(
- "Operation", [
- {__newname: "Assemble Keyboard"},
- {workstation: "Keyboard assembly workstation"}
- ]
- );
- },
- () => frappe.timeout(3),
- () => {
- assert.ok(cur_frm.docname.includes('Assemble Keyboard'),
- 'Assemble Keyboard created successfully');
- assert.ok(cur_frm.doc.workstation.includes('Keyboard assembly workstation'),
- 'Keyboard assembly workstation was linked successfully');
- },
-
- // Create a Screen operation
- () => {
- return frappe.tests.make(
- "Operation", [
- {__newname: 'Assemble Screen'},
- {workstation: "Screen assembly workstation"}
- ]
- );
- },
- () => frappe.timeout(3),
-
- // Create a CPU operation
- () => {
- return frappe.tests.make(
- "Operation", [
- {__newname: 'Assemble CPU'},
- {workstation: "CPU assembly workstation"}
- ]
- );
- },
- () => frappe.timeout(3),
-
- () => done()
- ]);
-});
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.js b/erpnext/manufacturing/doctype/work_order/test_work_order.js
deleted file mode 100644
index 1e224eb..0000000
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.js
+++ /dev/null
@@ -1,130 +0,0 @@
-QUnit.test("test: work order", function (assert) {
- assert.expect(25);
- let done = assert.async();
- let laptop_quantity = 5;
- let items = ["CPU", "Keyboard", "Screen"];
- let operation_items = ["CPU", "Keyboard", "Screen"];
- let click_make = () => {
- let element = $(`.btn-primary:contains("Make"):visible`);
- if(!element.length) {
- throw `did not find any button containing 'Make'`;
- }
- element.click();
- return frappe.timeout(1);
- };
-
- frappe.run_serially([
- // test work order
- () => frappe.set_route("List", "Work Order", "List"),
- () => frappe.timeout(3),
-
- // Create a laptop work order
- () => {
- return frappe.tests.make('Work Order', [
- {production_item: 'Laptop'},
- {company: 'For Testing'},
- {qty: laptop_quantity},
- {scrap_warehouse: "Laptop Scrap Warehouse - FT"},
- {wip_warehouse: "Work In Progress - FT"},
- {fg_warehouse: "Finished Goods - FT"}
- ]);
- },
- () => frappe.timeout(3),
- () => {
- assert.equal(cur_frm.doc.planned_operating_cost, cur_frm.doc.total_operating_cost,
- "Total and Planned Cost is equal");
- assert.equal(cur_frm.doc.planned_operating_cost, cur_frm.doc.total_operating_cost,
- "Total and Planned Cost is equal");
-
- items.forEach(function(item, index) {
- assert.equal(item, cur_frm.doc.required_items[index].item_code, `Required item ${item} added`);
- assert.equal("Stores - FT", cur_frm.doc.required_items[index].source_warehouse, `Item ${item} warhouse verified`);
- assert.equal("5", cur_frm.doc.required_items[index].required_qty, `Item ${item} quantity verified`);
- });
-
- operation_items.forEach(function(operation_item, index) {
- assert.equal(`Assemble ${operation_item}`, cur_frm.doc.operations[index].operation,
- `Operation ${operation_item} added`);
- assert.equal(`${operation_item} assembly workstation`, cur_frm.doc.operations[index].workstation,
- `Workstation ${operation_item} linked`);
- });
- },
-
- // Submit the work order
- () => cur_frm.savesubmit(),
- () => frappe.timeout(1),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(2.5),
-
- // Confirm the work order timesheet, save and submit it
- () => frappe.click_link("TS-00"),
- () => frappe.timeout(1),
- () => frappe.click_button("Submit"),
- () => frappe.timeout(1),
- () => frappe.click_button("Yes"),
- () => frappe.timeout(2.5),
-
- // Start the work order process
- () => frappe.set_route("List", "Work Order", "List"),
- () => frappe.timeout(2),
- () => frappe.click_link("Laptop"),
- () => frappe.timeout(1),
- () => frappe.click_button("Start"),
- () => frappe.timeout(0.5),
- () => click_make(),
- () => frappe.timeout(1),
- () => frappe.click_button("Save"),
- () => frappe.timeout(0.5),
-
- () => {
- assert.equal(cur_frm.doc.total_outgoing_value, cur_frm.doc.total_incoming_value,
- "Total incoming and outgoing cost is equal");
- assert.equal(cur_frm.doc.total_outgoing_value, "99000",
- "Outgoing cost is correct"); // Price of each item x5
- },
- // Submit for work
- () => frappe.click_button("Submit"),
- () => frappe.timeout(0.5),
- () => frappe.click_button("Yes"),
- () => frappe.timeout(0.5),
-
- // Finish the work order by sending for manufacturing
- () => frappe.set_route("List", "Work Order"),
- () => frappe.timeout(1),
- () => frappe.click_link("Laptop"),
- () => frappe.timeout(1),
-
- () => {
- assert.ok(frappe.tests.is_visible("5 items in progress", 'p'), "Work order initiated");
- assert.ok(frappe.tests.is_visible("Finish"), "Finish button visible");
- },
-
- () => frappe.click_button("Finish"),
- () => frappe.timeout(0.5),
- () => click_make(),
- () => {
- assert.equal(cur_frm.doc.total_incoming_value, "105700",
- "Incoming cost is correct "+cur_frm.doc.total_incoming_value); // Price of each item x5, values are in INR
- assert.equal(cur_frm.doc.total_outgoing_value, "99000",
- "Outgoing cost is correct"); // Price of each item x5, values are in INR
- assert.equal(cur_frm.doc.total_incoming_value - cur_frm.doc.total_outgoing_value, cur_frm.doc.value_difference,
- "Value difference is correct"); // Price of each item x5, values are in INR
- },
- () => frappe.click_button("Save"),
- () => frappe.timeout(1),
- () => frappe.click_button("Submit"),
- () => frappe.timeout(1),
- () => frappe.click_button("Yes"),
- () => frappe.timeout(1),
-
- // Manufacturing finished
- () => frappe.set_route("List", "Work Order", "List"),
- () => frappe.timeout(1),
- () => frappe.click_link("Laptop"),
- () => frappe.timeout(1),
-
- () => assert.ok(frappe.tests.is_visible("5 items produced", 'p'), "Work order completed"),
-
- () => done()
- ]);
-});
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index 165e0ac..9926b15 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -199,8 +199,6 @@
# no change in reserved / projected
self.assertEqual(cint(bin1_on_end_production.reserved_qty_for_production),
cint(bin1_on_start_production.reserved_qty_for_production))
- self.assertEqual(cint(bin1_on_end_production.projected_qty),
- cint(bin1_on_end_production.projected_qty))
def test_backflush_qty_for_overpduction_manufacture(self):
cancel_stock_entry = []
@@ -846,6 +844,45 @@
close_work_order(wo_order, "Closed")
self.assertEqual(wo_order.get('status'), "Closed")
+ def test_fix_time_operations(self):
+ bom = frappe.get_doc({
+ "doctype": "BOM",
+ "item": "_Test FG Item 2",
+ "is_active": 1,
+ "is_default": 1,
+ "quantity": 1.0,
+ "with_operations": 1,
+ "operations": [
+ {
+ "operation": "_Test Operation 1",
+ "description": "_Test",
+ "workstation": "_Test Workstation 1",
+ "time_in_mins": 60,
+ "operating_cost": 140,
+ "fixed_time": 1
+ }
+ ],
+ "items": [
+ {
+ "amount": 5000.0,
+ "doctype": "BOM Item",
+ "item_code": "_Test Item",
+ "parentfield": "items",
+ "qty": 1.0,
+ "rate": 5000.0,
+ },
+ ],
+ })
+ bom.save()
+ bom.submit()
+
+
+ wo1 = make_wo_order_test_record(item=bom.item, bom_no=bom.name, qty=1, skip_transfer=1, do_not_submit=1)
+ wo2 = make_wo_order_test_record(item=bom.item, bom_no=bom.name, qty=2, skip_transfer=1, do_not_submit=1)
+
+ self.assertEqual(wo1.operations[0].time_in_mins, wo2.operations[0].time_in_mins)
+
+
def update_job_card(job_card):
job_card_doc = frappe.get_doc('Job Card', job_card)
job_card_doc.set('scrap_items', [
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py
index 0090f4d..170454c 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/work_order.py
@@ -505,16 +505,19 @@
"""Fetch operations from BOM and set in 'Work Order'"""
def _get_operations(bom_no, qty=1):
- return frappe.db.sql(
- f"""select
- operation, description, workstation, idx,
- base_hour_rate as hour_rate, time_in_mins * {qty} as time_in_mins,
- "Pending" as status, parent as bom, batch_size, sequence_id
- from
- `tabBOM Operation`
- where
- parent = %s order by idx
- """, bom_no, as_dict=1)
+ data = frappe.get_all("BOM Operation",
+ filters={"parent": bom_no},
+ fields=["operation", "description", "workstation", "idx",
+ "base_hour_rate as hour_rate", "time_in_mins", "parent as bom",
+ "batch_size", "sequence_id", "fixed_time"],
+ order_by="idx")
+
+ for d in data:
+ if not d.fixed_time:
+ d.time_in_mins = flt(d.time_in_mins) * flt(qty)
+ d.status = "Pending"
+
+ return data
self.set('operations', [])
@@ -542,7 +545,8 @@
def calculate_time(self):
for d in self.get("operations"):
- d.time_in_mins = flt(d.time_in_mins) * (flt(self.qty) / flt(d.batch_size))
+ if not d.fixed_time:
+ d.time_in_mins = flt(d.time_in_mins) * (flt(self.qty) / flt(d.batch_size))
self.calculate_operating_cost()
diff --git a/erpnext/manufacturing/doctype/workstation/test_workstation.js b/erpnext/manufacturing/doctype/workstation/test_workstation.js
deleted file mode 100644
index 1df53d0..0000000
--- a/erpnext/manufacturing/doctype/workstation/test_workstation.js
+++ /dev/null
@@ -1,89 +0,0 @@
-QUnit.test("test: workstation", function (assert) {
- assert.expect(9);
- let done = assert.async();
- let elec_rate = 50;
- let rent = 100;
- let consumable_rate = 20;
- let labour_rate = 500;
- frappe.run_serially([
- // test workstation creation
- () => frappe.set_route("List", "Workstation"),
-
- // Create a keyboard workstation
- () => frappe.tests.make(
- "Workstation", [
- {workstation_name: "Keyboard assembly workstation"},
- {hour_rate_electricity: elec_rate},
- {hour_rate_rent: rent},
- {hour_rate_consumable: consumable_rate},
- {hour_rate_labour: labour_rate},
- {working_hours: [
- [
- {enabled: 1},
- {start_time: '11:00:00'},
- {end_time: '18:00:00'}
- ]
- ]}
- ]
- ),
- () => {
- assert.ok(cur_frm.doc.workstation_name.includes('Keyboard assembly workstation'),
- 'Keyboard assembly workstation created successfully');
- assert.equal(cur_frm.doc.hour_rate_electricity, elec_rate,
- 'electricity rate set correctly');
- assert.equal(cur_frm.doc.hour_rate_rent, rent,
- 'rent set correctly');
- assert.equal(cur_frm.doc.hour_rate_consumable, consumable_rate,
- 'consumable rate set correctly');
- assert.equal(cur_frm.doc.hour_rate_labour, labour_rate,
- 'labour rate set correctly');
- assert.equal(cur_frm.doc.working_hours[0].enabled, 1,
- 'working hours enabled');
- assert.ok(cur_frm.doc.working_hours[0].start_time.includes('11:00:0'),
- 'start time set correctly');
- assert.ok(cur_frm.doc.working_hours[0].end_time.includes('18:00:0'),
- 'end time set correctly');
- assert.ok(cur_frm.doc.hour_rate_electricity+cur_frm.doc.hour_rate_rent+
- cur_frm.doc.hour_rate_consumable+cur_frm.doc.hour_rate_labour==
- cur_frm.doc.hour_rate, 'Net hour rate set correctly');
- },
-
- // Create a Screen workstation
- () => frappe.tests.make(
- "Workstation", [
- {workstation_name: "Screen assembly workstation"},
- {hour_rate_electricity: elec_rate},
- {hour_rate_rent: rent},
- {hour_rate_consumable: consumable_rate},
- {hour_rate_labour: labour_rate},
- {working_hours: [
- [
- {enabled: 1},
- {start_time: '11:00:00'},
- {end_time: '18:00:00'}
- ]
- ]}
- ]
- ),
-
- // Create a CPU workstation
- () => frappe.tests.make(
- "Workstation", [
- {workstation_name: "CPU assembly workstation"},
- {hour_rate_electricity: elec_rate},
- {hour_rate_rent: rent},
- {hour_rate_consumable: consumable_rate},
- {hour_rate_labour: labour_rate},
- {working_hours: [
- [
- {enabled: 1},
- {start_time: '11:00:00'},
- {end_time: '18:00:00'}
- ]
- ]}
- ]
- ),
-
- () => done()
- ]);
-});
diff --git a/erpnext/non_profit/doctype/donor/test_donor.js b/erpnext/non_profit/doctype/donor/test_donor.js
deleted file mode 100644
index e478b34..0000000
--- a/erpnext/non_profit/doctype/donor/test_donor.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Donor", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(3);
-
- frappe.run_serially([
- // insert a new Member
- () => frappe.tests.make('Donor', [
- // values to be set
- {donor_name: 'Test Donor'},
- {donor_type: 'Test Organization'},
- {email: 'test@example.com'}
- ]),
- () => {
- assert.equal(cur_frm.doc.donor_name, 'Test Donor');
- assert.equal(cur_frm.doc.donor_type, 'Test Organization');
- assert.equal(cur_frm.doc.email, 'test@example.com');
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/non_profit/doctype/grant_application/test_grant_application.js b/erpnext/non_profit/doctype/grant_application/test_grant_application.js
deleted file mode 100644
index 47230a5..0000000
--- a/erpnext/non_profit/doctype/grant_application/test_grant_application.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Grant Application", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(4);
-
- frappe.run_serially([
- // insert a new Member
- () => frappe.tests.make('Grant Application', [
- // values to be set
- {applicant_name: 'Test Organization'},
- {contact_person:'Test Applicant'},
- {email: 'test@example.com'},
- {grant_description:'Test message'},
- {amount: 150000}
- ]),
- () => {
- assert.equal(cur_frm.doc.applicant_name, 'Test Organization');
- assert.equal(cur_frm.doc.contact_person, 'Test Applicant');
- assert.equal(cur_frm.doc.email, 'test@example.com');
- assert.equal(cur_frm.doc.amount, 150000);
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/non_profit/doctype/member/test_member.js b/erpnext/non_profit/doctype/member/test_member.js
deleted file mode 100644
index f7cca97..0000000
--- a/erpnext/non_profit/doctype/member/test_member.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Member", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(2);
-
- frappe.run_serially([
- // insert a new Member
- () => frappe.tests.make('Member', [
- // values to be set
- {member_name: 'Test Member'},
- {membership_type: 'Gold'},
- {email: 'test@example.com'}
- ]),
- () => {
- assert.equal(cur_frm.doc.membership_type, 'Gold');
- assert.equal(cur_frm.doc.email, 'test@example.com');
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/non_profit/doctype/membership_type/test_membership_type.js b/erpnext/non_profit/doctype/membership_type/test_membership_type.js
deleted file mode 100644
index 6440df8..0000000
--- a/erpnext/non_profit/doctype/membership_type/test_membership_type.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Membership Type", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(2);
-
- frappe.run_serially([
- // insert a new Member
- () => frappe.tests.make('Membership Type', [
- // values to be set
- {membership_type: 'Gold'},
- {amount:50000}
- ]),
- () => {
- assert.equal(cur_frm.doc.membership_type, 'Gold');
- assert.equal(cur_frm.doc.amount, '50000');
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/non_profit/doctype/volunteer/test_volunteer.js b/erpnext/non_profit/doctype/volunteer/test_volunteer.js
deleted file mode 100644
index 45eb281..0000000
--- a/erpnext/non_profit/doctype/volunteer/test_volunteer.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Volunteer", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(4);
-
- frappe.run_serially([
- // insert a new Member
- () => frappe.tests.make('Volunteer', [
- // values to be set
- {volunteer_name: 'Test Volunteer'},
- {volunteer_type:'Test Work'},
- {email:'test@example.com'},
- {'availability': 'Weekends'},
- {volunteer_skills:[
- [
- {'volunteer_skills': 'Fundraiser'},
- ]
- ]},
- ]),
- () => {
- assert.equal(cur_frm.doc.volunteer_name, 'Test Volunteer');
- assert.equal(cur_frm.doc.volunteer_type, 'Test Work');
- assert.equal(cur_frm.doc.email, 'test@example.com');
- assert.equal(cur_frm.doc.availability, 'Weekends');
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.js b/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.js
deleted file mode 100644
index 08baaf0..0000000
--- a/erpnext/non_profit/doctype/volunteer_type/test_volunteer_type.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Volunteer Type", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(2);
-
- frappe.run_serially([
- // insert a new Member
- () => {
- return frappe.tests.make('Volunteer Type', [
- // values to be set
- {__newname: 'Test Work'},
- {amount: 500}
- ]);
- },
- () => {
- assert.equal(cur_frm.doc.name, 'Test Work');
- assert.equal(cur_frm.doc.amount, 500);
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 65ad79e..d9cedab 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -316,5 +316,5 @@
erpnext.patches.v14_0.rename_ongoing_status_in_sla_documents
erpnext.patches.v14_0.migrate_crm_settings
erpnext.patches.v13_0.rename_ksa_qr_field
-erpnext.patches.v13_0.disable_ksa_print_format_for_others
+erpnext.patches.v13_0.disable_ksa_print_format_for_others # 16-12-2021
erpnext.patches.v14_0.add_default_exit_questionnaire_notification_template
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/disable_ksa_print_format_for_others.py b/erpnext/patches/v13_0/disable_ksa_print_format_for_others.py
index c815b3b..aa2a2d3 100644
--- a/erpnext/patches/v13_0/disable_ksa_print_format_for_others.py
+++ b/erpnext/patches/v13_0/disable_ksa_print_format_for_others.py
@@ -3,10 +3,13 @@
import frappe
+from erpnext.regional.saudi_arabia.setup import add_print_formats
+
def execute():
company = frappe.get_all('Company', filters = {'country': 'Saudi Arabia'})
if company:
+ add_print_formats()
return
if frappe.db.exists('DocType', 'Print Format'):
diff --git a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.js b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.js
deleted file mode 100644
index d24f243..0000000
--- a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.js
+++ /dev/null
@@ -1,62 +0,0 @@
-QUnit.module('HR');
-
-QUnit.test("test: Payroll Entry", function (assert) {
- assert.expect(5);
- let done = assert.async();
- let employees, docname;
-
- frappe.run_serially([
- () => {
- return frappe.tests.make('Payroll Entry', [
- {company: 'For Testing'},
- {posting_date: frappe.datetime.add_days(frappe.datetime.nowdate(), 0)},
- {payroll_frequency: 'Monthly'},
- {cost_center: 'Main - '+frappe.get_abbr(frappe.defaults.get_default("Company"))}
- ]);
- },
-
- () => frappe.timeout(1),
- () => {
- assert.equal(cur_frm.doc.company, 'For Testing');
- assert.equal(cur_frm.doc.posting_date, frappe.datetime.add_days(frappe.datetime.nowdate(), 0));
- assert.equal(cur_frm.doc.cost_center, 'Main - FT');
- },
- () => frappe.click_button('Get Employee Details'),
- () => {
- employees = cur_frm.doc.employees.length;
- docname = cur_frm.doc.name;
- },
-
- () => frappe.click_button('Submit'),
- () => frappe.timeout(1),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(5),
-
- () => frappe.click_button('View Salary Slip'),
- () => frappe.timeout(2),
- () => assert.equal(cur_list.data.length, employees),
-
- () => frappe.set_route('Form', 'Payroll Entry', docname),
- () => frappe.timeout(2),
- () => frappe.click_button('Submit Salary Slip'),
- () => frappe.click_button('Yes'),
- () => frappe.timeout(5),
-
- () => frappe.click_button('Close'),
- () => frappe.timeout(1),
-
- () => frappe.click_button('View Salary Slip'),
- () => frappe.timeout(2),
- () => {
- let count = 0;
- for(var i = 0; i < employees; i++) {
- if(cur_list.data[i].docstatus == 1){
- count++;
- }
- }
- assert.equal(count, employees, "Salary Slip submitted for all employees");
- },
-
- () => done()
- ]);
-});
diff --git a/erpnext/payroll/doctype/payroll_entry/test_set_salary_components.js b/erpnext/payroll/doctype/payroll_entry/test_set_salary_components.js
deleted file mode 100644
index 092cbd8..0000000
--- a/erpnext/payroll/doctype/payroll_entry/test_set_salary_components.js
+++ /dev/null
@@ -1,61 +0,0 @@
-QUnit.module('HR');
-
-QUnit.test("test: Set Salary Components", function (assert) {
- assert.expect(5);
- let done = assert.async();
-
- frappe.run_serially([
- () => frappe.set_route('Form', 'Salary Component', 'Leave Encashment'),
- () => {
- var row = frappe.model.add_child(cur_frm.doc, "Salary Component Account", "accounts");
- row.company = 'For Testing';
- row.account = 'Salary - FT';
- },
-
- () => cur_frm.save(),
- () => frappe.timeout(2),
- () => assert.equal(cur_frm.doc.accounts[0].account, 'Salary - FT'),
-
- () => frappe.set_route('Form', 'Salary Component', 'Basic'),
- () => {
- var row = frappe.model.add_child(cur_frm.doc, "Salary Component Account", "accounts");
- row.company = 'For Testing';
- row.account = 'Salary - FT';
- },
-
- () => cur_frm.save(),
- () => frappe.timeout(2),
- () => assert.equal(cur_frm.doc.accounts[0].account, 'Salary - FT'),
-
- () => frappe.set_route('Form', 'Salary Component', 'Income Tax'),
- () => {
- var row = frappe.model.add_child(cur_frm.doc, "Salary Component Account", "accounts");
- row.company = 'For Testing';
- row.account = 'Salary - FT';
- },
-
- () => cur_frm.save(),
- () => frappe.timeout(2),
- () => assert.equal(cur_frm.doc.accounts[0].account, 'Salary - FT'),
-
- () => frappe.set_route('Form', 'Salary Component', 'Arrear'),
- () => {
- var row = frappe.model.add_child(cur_frm.doc, "Salary Component Account", "accounts");
- row.company = 'For Testing';
- row.account = 'Salary - FT';
- },
-
- () => cur_frm.save(),
- () => frappe.timeout(2),
- () => assert.equal(cur_frm.doc.accounts[0].account, 'Salary - FT'),
-
- () => frappe.set_route('Form', 'Company', 'For Testing'),
- () => cur_frm.set_value('default_payroll_payable_account', 'Payroll Payable - FT'),
- () => cur_frm.save(),
- () => frappe.timeout(2),
- () => assert.equal(cur_frm.doc.default_payroll_payable_account, 'Payroll Payable - FT'),
-
- () => done()
-
- ]);
-});
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.js b/erpnext/payroll/doctype/salary_slip/test_salary_slip.js
deleted file mode 100644
index a47eba1..0000000
--- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.js
+++ /dev/null
@@ -1,55 +0,0 @@
-QUnit.test("test salary slip", function(assert) {
- assert.expect(6);
- let done = assert.async();
- let employee_name;
-
- let salary_slip = (ename) => {
- frappe.run_serially([
- () => frappe.db.get_value('Employee', {'employee_name': ename}, 'name'),
- (r) => {
- employee_name = r.message.name;
- },
- () => {
- // Creating a salary slip for a employee
- frappe.tests.make('Salary Slip', [
- { employee: employee_name}
- ]);
- },
- () => frappe.timeout(3),
- () => {
- // To check if all the calculations are correctly done
- if(ename === 'Test Employee 1')
- {
- assert.ok(cur_frm.doc.gross_pay==24000,
- 'Gross amount for first employee is correctly calculated');
- assert.ok(cur_frm.doc.total_deduction==4800,
- 'Deduction amount for first employee is correctly calculated');
- assert.ok(cur_frm.doc.net_pay==19200,
- 'Net amount for first employee is correctly calculated');
- }
- if(ename === 'Test Employee 3')
- {
- assert.ok(cur_frm.doc.gross_pay==28800,
- 'Gross amount for second employee is correctly calculated');
- assert.ok(cur_frm.doc.total_deduction==5760,
- 'Deduction amount for second employee is correctly calculated');
- assert.ok(cur_frm.doc.net_pay==23040,
- 'Net amount for second employee is correctly calculated');
- }
- },
- ]);
- };
- frappe.run_serially([
- () => salary_slip('Test Employee 1'),
- () => frappe.timeout(6),
- () => salary_slip('Test Employee 3'),
- () => frappe.timeout(5),
- () => frappe.set_route('List', 'Salary Slip', 'List'),
- () => frappe.timeout(2),
- () => {$('.list-row-checkbox').click();},
- () => frappe.timeout(2),
- () => frappe.click_button('Delete'),
- () => frappe.click_button('Yes'),
- () => done()
- ]);
-});
diff --git a/erpnext/payroll/doctype/salary_structure/test_salary_structure.js b/erpnext/payroll/doctype/salary_structure/test_salary_structure.js
deleted file mode 100644
index 542fa50..0000000
--- a/erpnext/payroll/doctype/salary_structure/test_salary_structure.js
+++ /dev/null
@@ -1,78 +0,0 @@
-QUnit.test("test Salary Structure", function(assert) {
- assert.expect(7);
- let done = assert.async();
- let employee_name1;
-
- frappe.run_serially([
- () => frappe.db.get_value('Employee', {'employee_name': "Test Employee 1"}, 'name',
- (r) => {
- employee_name1 = r.name;
- }
- ),
- () => frappe.timeout(5),
- () => frappe.db.get_value('Employee', {'employee_name': "Test Employee 3"}, 'name',
- (r) => {
- // Creating Salary Structure for employees);
- return frappe.tests.make('Salary Structure', [
- { __newname: 'Test Salary Structure'},
- { company: 'For Testing'},
- { payroll_frequency: 'Monthly'},
- { employees: [
- [
- {employee: employee_name1},
- {from_date: '2017-07-01'},
- {base: 25000}
- ],
- [
- {employee: r.name},
- {from_date: '2017-07-01'},
- {base: 30000}
- ]
- ]},
- { earnings: [
- [
- {salary_component: 'Basic'},
- {formula: 'base * .80'}
- ],
- [
- {salary_component: 'Leave Encashment'},
- {formula: 'B * .20'}
- ]
- ]},
- { deductions: [
- [
- {salary_component: 'Income Tax'},
- {formula: '(B+LE) * .20'}
- ]
- ]},
- { payment_account: 'CASH - FT'},
- ]);
- }
- ),
- () => frappe.timeout(15),
- () => {
- // To check if all the fields are correctly set
- assert.ok(cur_frm.doc.employees[0].employee_name=='Test Employee 1',
- 'Employee 1 name correctly set');
-
- assert.ok(cur_frm.doc.employees[1].employee_name=='Test Employee 3',
- 'Employee 2 name correctly set');
-
- assert.ok(cur_frm.doc.employees[0].base==25000,
- 'Base value for first employee is correctly set');
-
- assert.ok(cur_frm.doc.employees[1].base==30000,
- 'Base value for second employee is correctly set');
-
- assert.ok(cur_frm.doc.earnings[0].formula.includes('base * .80'),
- 'Formula for earnings as Basic is correctly set');
-
- assert.ok(cur_frm.doc.earnings[1].formula.includes('B * .20'),
- 'Formula for earnings as Leave Encashment is correctly set');
-
- assert.ok(cur_frm.doc.deductions[0].formula.includes('(B+LE) * .20'),
- 'Formula for deductions as Income Tax is correctly set');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/projects/doctype/activity_type/test_activity_type.js b/erpnext/projects/doctype/activity_type/test_activity_type.js
deleted file mode 100644
index 62be972..0000000
--- a/erpnext/projects/doctype/activity_type/test_activity_type.js
+++ /dev/null
@@ -1,21 +0,0 @@
-QUnit.test("test: Activity Type", function (assert) {
- // number of asserts
- assert.expect(1);
- let done = assert.async();
-
- frappe.run_serially([
- // insert a new Activity Type
- () => frappe.set_route("List", "Activity Type", "List"),
- () => frappe.new_doc("Activity Type"),
- () => frappe.timeout(1),
- () => frappe.quick_entry.dialog.$wrapper.find('.edit-full').click(),
- () => frappe.timeout(1),
- () => cur_frm.set_value("activity_type", "Test Activity"),
- () => frappe.click_button('Save'),
- () => frappe.timeout(1),
- () => {
- assert.equal(cur_frm.doc.name,"Test Activity");
- },
- () => done()
- ]);
-});
diff --git a/erpnext/projects/doctype/task/tests/test_task.js b/erpnext/projects/doctype/task/tests/test_task.js
deleted file mode 100644
index 8a1a5bf..0000000
--- a/erpnext/projects/doctype/task/tests/test_task.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Task", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(2);
-
- frappe.run_serially([
- // insert a new Task
- () => frappe.tests.make('Task', [
- // values to be set
- {subject: 'new task'}
- ]),
- () => {
- assert.equal(cur_frm.doc.status, 'Open');
- assert.equal(cur_frm.doc.priority, 'Low');
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/projects/doctype/task/tests/test_task_tree.js b/erpnext/projects/doctype/task/tests/test_task_tree.js
deleted file mode 100644
index 27dccbf..0000000
--- a/erpnext/projects/doctype/task/tests/test_task_tree.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Task Tree", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(4);
-
- frappe.run_serially([
- // insert a new Task
- () => frappe.set_route('Tree', 'Task'),
- () => frappe.timeout(0.5),
-
- // Checking adding child without selecting any Node
- () => frappe.tests.click_button('New'),
- () => frappe.timeout(0.5),
- () => {assert.equal($(`.msgprint`).text(), "Select a group node first.", "Error message success");},
- () => frappe.tests.click_button('Close'),
- () => frappe.timeout(0.5),
-
- // Creating child nodes
- () => frappe.tests.click_link('All Tasks'),
- () => frappe.map_group.make('Test-1'),
- () => frappe.map_group.make('Test-3', 1),
- () => frappe.timeout(1),
- () => frappe.tests.click_link('Test-3'),
- () => frappe.map_group.make('Test-4', 0),
-
- // Checking Edit button
- () => frappe.timeout(0.5),
- () => frappe.tests.click_link('Test-1'),
- () => frappe.tests.click_button('Edit'),
- () => frappe.timeout(1),
- () => frappe.db.get_value('Task', {'subject': 'Test-1'}, 'name'),
- (task) => {assert.deepEqual(frappe.get_route(), ["Form", "Task", task.message.name], "Edit route checks");},
-
- // Deleting child Node
- () => frappe.set_route('Tree', 'Task'),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_link('Test-1'),
- () => frappe.tests.click_button('Delete'),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Yes'),
-
- // Deleting Group Node that has child nodes in it
- () => frappe.timeout(0.5),
- () => frappe.tests.click_link('Test-3'),
- () => frappe.tests.click_button('Delete'),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(1),
- () => {assert.equal(cur_dialog.title, 'Message', 'Error thrown correctly');},
- () => frappe.tests.click_button('Close'),
-
- // Add multiple child tasks
- () => frappe.tests.click_link('Test-3'),
- () => frappe.timeout(0.5),
- () => frappe.click_button('Add Multiple'),
- () => frappe.timeout(1),
- () => cur_dialog.set_value('tasks', 'Test-6\nTest-7'),
- () => frappe.timeout(0.5),
- () => frappe.click_button('Submit'),
- () => frappe.timeout(2),
- () => frappe.click_button('Expand All'),
- () => frappe.timeout(1),
- () => {
- let count = $(`a:contains("Test-6"):visible`).length + $(`a:contains("Test-7"):visible`).length;
- assert.equal(count, 2, "Multiple Tasks added successfully");
- },
-
- () => done()
- ]);
-});
-
-frappe.map_group = {
- make:function(subject, is_group = 0){
- return frappe.run_serially([
- () => frappe.click_button('Add Child'),
- () => frappe.timeout(1),
- () => cur_dialog.set_value('is_group', is_group),
- () => cur_dialog.set_value('subject', subject),
- () => frappe.click_button('Create New'),
- () => frappe.timeout(1.5)
- ]);
- }
-};
diff --git a/erpnext/public/js/queries.js b/erpnext/public/js/queries.js
index b635adc..b7d880a 100644
--- a/erpnext/public/js/queries.js
+++ b/erpnext/public/js/queries.js
@@ -83,6 +83,13 @@
};
},
+ dispatch_address_query: function(doc) {
+ return {
+ query: 'frappe.contacts.doctype.address.address.address_query',
+ filters: { link_doctype: 'Company', link_name: doc.company || '' }
+ };
+ },
+
supplier_filter: function(doc) {
if(!doc.supplier) {
frappe.throw(__("Please set {0}", [__(frappe.meta.get_label(doc.doctype, "supplier", doc.name))]));
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 6654048..9339c5d 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -430,12 +430,9 @@
qty = row.qty;
}
row[item_field] = d.alternate_item;
- frm.script_manager.trigger(item_field, row.doctype, row.name)
- .then(() => {
- frappe.model.set_value(row.doctype, row.name, 'qty', qty);
- frappe.model.set_value(row.doctype, row.name,
- opts.original_item_field, d.item_code);
- });
+ frappe.model.set_value(row.doctype, row.name, 'qty', qty);
+ frappe.model.set_value(row.doctype, row.name, opts.original_item_field, d.item_code);
+ frm.trigger(item_field, row.doctype, row.name);
});
refresh_field(opts.child_docname);
@@ -888,9 +885,11 @@
function set_time_to_resolve_and_response(frm, apply_sla_for_resolution) {
frm.dashboard.clear_headline();
- let time_to_respond = get_status(frm.doc.response_by);
+ let time_to_respond;
if (!frm.doc.first_responded_on) {
time_to_respond = get_time_left(frm.doc.response_by, frm.doc.agreement_status);
+ } else {
+ time_to_respond = get_status(frm.doc.response_by, frm.doc.first_responded_on);
}
let alert = `
@@ -903,9 +902,11 @@
if (apply_sla_for_resolution) {
- let time_to_resolve = get_status(frm.doc.resolution_by);
+ let time_to_resolve;
if (!frm.doc.resolution_date) {
time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_status);
+ } else {
+ time_to_resolve = get_status(frm.doc.resolution_by, frm.doc.resolution_date);
}
alert += `
@@ -928,8 +929,8 @@
return {'diff_display': diff_display, 'indicator': indicator};
}
-function get_status(timestamp) {
- const time_left = moment(timestamp).diff(moment());
+function get_status(expected, actual) {
+ const time_left = moment(expected).diff(moment(actual));
if (time_left >= 0) {
return {'diff_display': 'Fulfilled', 'indicator': 'green'};
} else {
diff --git a/erpnext/restaurant/doctype/restaurant/test_restaurant.js b/erpnext/restaurant/doctype/restaurant/test_restaurant.js
deleted file mode 100644
index 8fe4e7b..0000000
--- a/erpnext/restaurant/doctype/restaurant/test_restaurant.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Restaurant", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(2);
- let customer = {
- "Test Customer 1": [
- {customer_name: "Test Customer 1"}
- ],
- "Test Customer 2": [
- {customer_name: "Test Customer 2"}
- ]
- };
-
- frappe.run_serially([
- // insert a new Restaurant
- () => frappe.tests.setup_doctype('Customer', customer),
- () => {
- return frappe.tests.make('Restaurant', [
- // values to be set
- {__newname: 'Test Restaurant 1'},
- {company: 'Test Company'},
- {invoice_series_prefix: 'Test-Rest-1-Inv-'},
- {default_customer: 'Test Customer 1'}
- ])
- },
- () => frappe.timeout(3),
- () => {
- assert.equal(cur_frm.doc.company, 'Test Company');
- },
- () => {
- return frappe.tests.make('Restaurant', [
- // values to be set
- {__newname: 'Test Restaurant 2'},
- {company: 'Test Company'},
- {invoice_series_prefix: 'Test-Rest-3-Inv-'},
- {default_customer: 'Test Customer 2'}
- ]);
- },
- () => frappe.timeout(3),
- () => {
- assert.equal(cur_frm.doc.company, 'Test Company');
- },
- () => done()
- ]);
-});
diff --git a/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js b/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js
deleted file mode 100644
index f5ab9f0..0000000
--- a/erpnext/restaurant/doctype/restaurant_menu/test_restaurant_menu.js
+++ /dev/null
@@ -1,77 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Restaurant Menu", function (assert) {
- let done = assert.async();
-
- let items = {
- "Food Item 1": [
- {item_code: "Food Item 1"},
- {item_group: "Products"},
- {is_stock_item: 1},
- ],
- "Food Item 2": [
- {item_code: "Food Item 2"},
- {item_group: "Products"},
- {is_stock_item: 1},
- ],
- "Food Item 3": [
- {item_code: "Food Item 3"},
- {item_group: "Products"},
- {is_stock_item: 1},
- ]
- };
-
-
- // number of asserts
- assert.expect(0);
-
- frappe.run_serially([
- // insert a new Restaurant Menu
- () => frappe.tests.setup_doctype('Item', items),
- () => {
- return frappe.tests.make("Restaurant Menu", [
- {__newname: 'Restaurant Menu 1'},
- {restaurant: "Test Restaurant 1"},
- {items: [
- [
- {"item": "Food Item 1"},
- {"rate": 100}
- ],
- [
- {"item": "Food Item 2"},
- {"rate": 90}
- ],
- [
- {"item": "Food Item 3"},
- {"rate": 80}
- ]
- ]}
- ]);
- },
- () => frappe.timeout(2),
- () => {
- return frappe.tests.make("Restaurant Menu", [
- {__newname: 'Restaurant Menu 2'},
- {restaurant: "Test Restaurant 2"},
- {items: [
- [
- {"item": "Food Item 1"},
- {"rate": 105}
- ],
- [
- {"item": "Food Item 3"},
- {"rate": 85}
- ]
- ]}
- ]);
- },
- () => frappe.timeout(2),
- () => frappe.set_route('Form', 'Restaurant', 'Test Restaurant 1'),
- () => cur_frm.set_value('active_menu', 'Restaurant Menu 1'),
- () => cur_frm.save(),
- () => done()
- ]);
-
-});
diff --git a/erpnext/restaurant/doctype/restaurant_order_entry/test_restaurant_order_entry.js b/erpnext/restaurant/doctype/restaurant_order_entry/test_restaurant_order_entry.js
deleted file mode 100644
index fec2a21..0000000
--- a/erpnext/restaurant/doctype/restaurant_order_entry/test_restaurant_order_entry.js
+++ /dev/null
@@ -1,53 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Restaurant Order Entry", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(5);
-
- frappe.run_serially([
- // insert a new Restaurant Order Entry
- () => frappe.set_route('Form', 'Restaurant Settings'),
- () => cur_frm.set_value('default_customer', 'Test Customer 1'),
- () => cur_frm.save(),
- () => frappe.set_route('Form', 'Restaurant Order Entry'),
- () => frappe.click_button('Clear'),
- () => frappe.timeout(2),
- () => cur_frm.set_value('restaurant_table', 'Test-Restaurant-1-01'),
- () => cur_frm.set_value('add_item', 'Food Item 1'),
- () => frappe.timeout(0.5),
- () => {
- var e = $.Event( "keyup", {which: 13} );
- $('input[data-fieldname="add_item"]').trigger(e);
- return frappe.timeout(0.5);
- },
- () => cur_frm.set_value('add_item', 'Food Item 1'),
- () => {
- var e = $.Event( "keyup", {which: 13} );
- $('input[data-fieldname="add_item"]').trigger(e);
- return frappe.timeout(0.5);
- },
- () => cur_frm.set_value('add_item', 'Food Item 2'),
- () => {
- var e = $.Event( "keyup", {which: 13} );
- $('input[data-fieldname="add_item"]').trigger(e);
- return frappe.timeout(0.5);
- },
- () => {
- assert.equal(cur_frm.doc.items[0].item, 'Food Item 1');
- assert.equal(cur_frm.doc.items[0].qty, 2);
- assert.equal(cur_frm.doc.items[1].item, 'Food Item 2');
- assert.equal(cur_frm.doc.items[1].qty, 1);
- },
- () => frappe.click_button('Update'),
- () => frappe.timeout(2),
- () => {
- assert.equal(cur_frm.doc.grand_total, 290);
- }
- () => done()
- ]);
-
-});
diff --git a/erpnext/restaurant/doctype/restaurant_reservation/test_restaurant_reservation.js b/erpnext/restaurant/doctype/restaurant_reservation/test_restaurant_reservation.js
deleted file mode 100644
index eeea5a9..0000000
--- a/erpnext/restaurant/doctype/restaurant_reservation/test_restaurant_reservation.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Restaurant Reservation", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(1);
-
- frappe.run_serially([
- // insert a new Restaurant Reservation
- () => frappe.tests.make('Restaurant Reservation', [
- // values to be set
- {restaurant: 'Gokul - JP Nagar'},
- {customer_name: 'test customer'},
- {reservation_time: frappe.datetime.now_date() + " 19:00:00"},
- {no_of_people: 4},
- ]),
- () => {
- assert.equal(cur_frm.doc.reservation_end_time,
- frappe.datetime.now_date() + ' 20:00:00');
- },
- () => done()
- ]);
-
-});
diff --git a/erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.js b/erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.js
deleted file mode 100644
index 16035f0..0000000
--- a/erpnext/restaurant/doctype/restaurant_table/test_restaurant_table.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Restaurant Table", function (assert) {
- let done = assert.async();
-
- // number of asserts
- assert.expect(0);
-
- frappe.run_serially([
- // insert a new Restaurant Table
- () => frappe.tests.make('Restaurant Table', [
- // values to be set
- {restaurant: 'Test Restaurant 1'},
- {no_of_seats: 4},
- ]),
- () => frappe.tests.make('Restaurant Table', [
- // values to be set
- {restaurant: 'Test Restaurant 1'},
- {no_of_seats: 5},
- ]),
- () => frappe.tests.make('Restaurant Table', [
- // values to be set
- {restaurant: 'Test Restaurant 1'},
- {no_of_seats: 2},
- ]),
- () => frappe.tests.make('Restaurant Table', [
- // values to be set
- {restaurant: 'Test Restaurant 1'},
- {no_of_seats: 2},
- ]),
- () => frappe.tests.make('Restaurant Table', [
- // values to be set
- {restaurant: 'Test Restaurant 1'},
- {no_of_seats: 6},
- ]),
- () => done()
- ]);
-
-});
diff --git a/erpnext/selling/doctype/product_bundle/test_product_bundle.js b/erpnext/selling/doctype/product_bundle/test_product_bundle.js
deleted file mode 100644
index 0dc90ec..0000000
--- a/erpnext/selling/doctype/product_bundle/test_product_bundle.js
+++ /dev/null
@@ -1,35 +0,0 @@
-QUnit.test("test sales order", function(assert) {
- assert.expect(4);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Product Bundle', [
- {new_item_code: 'Computer'},
- {items: [
- [
- {item_code:'CPU'},
- {qty:1}
- ],
- [
- {item_code:'Screen'},
- {qty:1}
- ],
- [
- {item_code:'Keyboard'},
- {qty:1}
- ]
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_code=='CPU', "Item Code correct");
- assert.ok(cur_frm.doc.items[1].item_code=='Screen', "Item Code correct");
- assert.ok(cur_frm.doc.items[2].item_code=='Keyboard', "Item Code correct");
- assert.ok(cur_frm.doc.new_item_code == "Computer", "Parent Item correct");
- },
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation.js b/erpnext/selling/doctype/quotation/tests/test_quotation.js
deleted file mode 100644
index ad942fe..0000000
--- a/erpnext/selling/doctype/quotation/tests/test_quotation.js
+++ /dev/null
@@ -1,58 +0,0 @@
-QUnit.test("test: quotation", function (assert) {
- assert.expect(12);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make("Quotation", [
- {customer: "Test Customer 1"},
- {items: [
- [
- {"item_code": "Test Product 1"},
- {"qty": 5}
- ]]
- },
- {payment_terms_template: '_Test Payment Term Template UI'}
- ]);
- },
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name == "Test Product 1", "Added Test Product 1");
-
- // calculate_taxes_and_totals
- assert.ok(cur_frm.doc.grand_total === 500, String(cur_frm.doc.grand_total));
- },
- () => cur_frm.set_value("customer_address", "Test1-Billing"),
- () => cur_frm.set_value("shipping_address_name", "Test1-Warehouse"),
- () => cur_frm.set_value("contact_person", "Contact 1-Test Customer 1"),
- () => cur_frm.set_value("currency", "USD"),
- () => frappe.timeout(0.3),
- () => cur_frm.set_value("selling_price_list", "Test-Selling-USD"),
- () => frappe.timeout(0.5),
- () => cur_frm.doc.items[0].rate = 200,
- () => frappe.timeout(0.3),
- () => cur_frm.set_value("tc_name", "Test Term 1"),
- () => cur_frm.set_value("payment_schedule", []),
- () => frappe.timeout(0.5),
- () => cur_frm.save(),
- () => {
- // Check Address and Contact Info
- assert.ok(cur_frm.doc.address_display.includes("Billing Street 1"), "Address Changed");
- assert.ok(cur_frm.doc.shipping_address.includes("Warehouse Street 1"), "Address Changed");
- assert.ok(cur_frm.doc.contact_display == "Contact 1", "Contact info changed");
-
- // Check Currency
- assert.ok(cur_frm.doc.currency == "USD", "Currency Changed");
- assert.ok(cur_frm.doc.selling_price_list == "Test-Selling-USD", "Price List Changed");
- assert.ok(cur_frm.doc.items[0].rate == 200, "Price Changed Manually");
- assert.equal(cur_frm.doc.total, 1000, "New Total Calculated");
-
- // Check Terms and Conditions
- assert.ok(cur_frm.doc.tc_name == "Test Term 1", "Terms and Conditions Checked");
-
- assert.ok(cur_frm.doc.payment_terms_template, "Payment Terms Template is correct");
- assert.ok(cur_frm.doc.payment_schedule.length > 0, "Payment Term Schedule is not empty");
-
- },
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation_submit_cancel_amend.js b/erpnext/selling/doctype/quotation/tests/test_quotation_submit_cancel_amend.js
deleted file mode 100644
index 26a099e..0000000
--- a/erpnext/selling/doctype/quotation/tests/test_quotation_submit_cancel_amend.js
+++ /dev/null
@@ -1,41 +0,0 @@
-QUnit.module('Quotation');
-
-QUnit.test("test quotation submit cancel amend", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Quotation', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 1'}
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- // get uom details
- assert.ok(cur_frm.doc.grand_total== 500, "Grand total correct ");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(1),
- () => frappe.tests.click_button('Close'),
- () => frappe.tests.click_button('Cancel'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.5),
- () => frappe.tests.click_button('Amend'),
- () => cur_frm.save(),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation_with_discount_on_grand_total.js b/erpnext/selling/doctype/quotation/tests/test_quotation_with_discount_on_grand_total.js
deleted file mode 100644
index b59bb05..0000000
--- a/erpnext/selling/doctype/quotation/tests/test_quotation_with_discount_on_grand_total.js
+++ /dev/null
@@ -1,43 +0,0 @@
-QUnit.module('Quotation');
-
-QUnit.test("test quotation with additional discount in grand total", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Quotation', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 4'},
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {payment_terms_template: '_Test Payment Term Template UI'}
- ]);
- },
- () => {
- return frappe.tests.set_form_values(cur_frm, [
- {apply_discount_on:'Grand Total'},
- {additional_discount_percentage:10},
- {payment_schedule: []}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- // get grand_total details
- assert.ok(cur_frm.doc.grand_total== 450, "Grand total correct ");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation_with_item_wise_discount.js b/erpnext/selling/doctype/quotation/tests/test_quotation_with_item_wise_discount.js
deleted file mode 100644
index f5172fb..0000000
--- a/erpnext/selling/doctype/quotation/tests/test_quotation_with_item_wise_discount.js
+++ /dev/null
@@ -1,37 +0,0 @@
-QUnit.module('Quotation');
-
-QUnit.test("test quotation with item wise discount", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Quotation', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 4'},
- {'discount_percentage': 10},
- {'margin_type': 'Percentage'}
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- // get grand_total details
- assert.ok(cur_frm.doc.grand_total== 450, "Grand total correct ");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation_with_margin.js b/erpnext/selling/doctype/quotation/tests/test_quotation_with_margin.js
deleted file mode 100644
index 0d34099..0000000
--- a/erpnext/selling/doctype/quotation/tests/test_quotation_with_margin.js
+++ /dev/null
@@ -1,35 +0,0 @@
-QUnit.module('Selling');
-
-QUnit.test("test quotation with margin", function(assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Quotation', [
- {customer: 'Test Customer 1'},
- {selling_price_list: 'Test-Selling-USD'},
- {currency: 'USD'},
- {items: [
- [
- {'item_code': 'Test Product 4'},
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 1},
- {'margin_type': 'Percentage'},
- {'margin_rate_or_amount': 20}
- ]
- ]}
- ]);
- },
- () => cur_frm.save(),
- () => {
- assert.ok(cur_frm.doc.items[0].rate_with_margin == 240, "Margin rate correct");
- assert.ok(cur_frm.doc.items[0].base_rate_with_margin == cur_frm.doc.conversion_rate * 240, "Base margin rate correct");
- assert.ok(cur_frm.doc.total == 240, "Amount correct");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation_with_multi_uom.js b/erpnext/selling/doctype/quotation/tests/test_quotation_with_multi_uom.js
deleted file mode 100644
index 84be56f..0000000
--- a/erpnext/selling/doctype/quotation/tests/test_quotation_with_multi_uom.js
+++ /dev/null
@@ -1,38 +0,0 @@
-QUnit.module('Quotation');
-
-QUnit.test("test quotation with multi uom", function(assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Quotation', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 4'},
- {'uom': 'unit'},
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- // get uom details
- assert.ok(cur_frm.doc.items[0].uom=='Unit', "Multi Uom correct");
- // get grand_total details
- assert.ok(cur_frm.doc.grand_total== 5000, "Grand total correct ");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation_with_shipping_rule.js b/erpnext/selling/doctype/quotation/tests/test_quotation_with_shipping_rule.js
deleted file mode 100644
index 17c5dd2..0000000
--- a/erpnext/selling/doctype/quotation/tests/test_quotation_with_shipping_rule.js
+++ /dev/null
@@ -1,35 +0,0 @@
-QUnit.module('Quotation');
-
-QUnit.test("test quotation with shipping rule", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Quotation', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 4'},
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {shipping_rule:'Next Day Shipping'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- // get grand_total details
- assert.ok(cur_frm.doc.grand_total== 550, "Grand total correct ");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/quotation/tests/test_quotation_with_taxes_and_charges.js b/erpnext/selling/doctype/quotation/tests/test_quotation_with_taxes_and_charges.js
deleted file mode 100644
index 5e21f81..0000000
--- a/erpnext/selling/doctype/quotation/tests/test_quotation_with_taxes_and_charges.js
+++ /dev/null
@@ -1,40 +0,0 @@
-QUnit.module('Quotation');
-
-QUnit.test("test quotation with taxes and charges", function(assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Quotation', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 4'},
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {taxes_and_charges: 'TEST In State GST - FT'},
- {tc_name: 'Test Term 1'},
- {terms: 'This is Test'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- // get tax details
- assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
- // get tax account head details
- assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order.js
deleted file mode 100644
index c99f9ef..0000000
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order.js
+++ /dev/null
@@ -1,68 +0,0 @@
-QUnit.module('Sales Order');
-
-QUnit.test("test sales order", function(assert) {
- assert.expect(12);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5.123},
- {'item_code': 'Test Product 3'},
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {taxes_and_charges: 'TEST In State GST - FT'},
- {tc_name: 'Test Term 1'},
- {terms: 'This is Test'},
- {payment_terms_template: '_Test Payment Term Template UI'}
- ]);
- },
- () => {
- return frappe.tests.set_form_values(cur_frm, [
- {selling_price_list:'Test-Selling-USD'},
- {currency: 'USD'}
- ]);
- },
- () => frappe.timeout(1.5),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 3', "Item name correct");
- // get tax details
- assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
- // get tax account head details
- assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
- },
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => cur_frm.print_doc(),
- () => frappe.timeout(1),
- () => {
- // Payment Terms
- assert.ok(cur_frm.doc.payment_terms_template, "Payment Terms Template is correct");
- assert.ok(cur_frm.doc.payment_schedule.length > 0, "Payment Term Schedule is not empty");
-
- // totals
- assert.ok(cur_frm.doc.items[0].price_list_rate==250, "Item 1 price_list_rate");
- assert.ok(cur_frm.doc.net_total== 1280.75, "net total correct ");
- assert.ok(cur_frm.doc.base_grand_total== flt(1511.29* cur_frm.doc.conversion_rate, precision('base_grand_total')), String(flt(1511.29* cur_frm.doc.conversion_rate, precision('base_grand_total')) + ' ' + cur_frm.doc.base_grand_total));
- assert.ok(cur_frm.doc.grand_total== 1511.29 , "grand total correct ");
- assert.ok(cur_frm.doc.rounded_total== 1511.30, "rounded total correct ");
-
- // print format
- assert.ok($('.btn-print-print').is(':visible'), "Print Format Available");
- frappe.timeout(1);
- assert.ok($(".section-break+ .section-break .column-break:nth-child(1) .data-field:nth-child(1) .value").text().includes("Billing Street 1"), "Print Preview Works As Expected");
- },
- () => cur_frm.print_doc(),
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_bypass_credit_limit_check.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_bypass_credit_limit_check.js
deleted file mode 100644
index 79d798b..0000000
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_bypass_credit_limit_check.js
+++ /dev/null
@@ -1,58 +0,0 @@
-QUnit.module('Sales Order');
-
-QUnit.test("test_sales_order_with_bypass_credit_limit_check", function(assert) {
-//#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => frappe.new_doc('Customer'),
- () => frappe.timeout(1),
- () => frappe.quick_entry.dialog.$wrapper.find('.edit-full').click(),
- () => frappe.timeout(1),
- () => cur_frm.set_value("customer_name", "Test Customer 10"),
- () => cur_frm.add_child('credit_limits', {
- 'company': cur_frm.doc.company || '_Test Company'
- 'credit_limit': 1000,
- 'bypass_credit_limit_check': 1}),
- // save form
- () => cur_frm.save(),
- () => frappe.timeout(1),
-
- () => frappe.new_doc('Item'),
- () => frappe.timeout(1),
- () => frappe.quick_entry.dialog.$wrapper.find('.edit-full').click(),
- () => frappe.timeout(1),
- () => cur_frm.set_value("item_code", "Test Product 10"),
- () => cur_frm.set_value("item_group", "Products"),
- () => cur_frm.set_value("standard_rate", 100),
- // save form
- () => cur_frm.save(),
- () => frappe.timeout(1),
-
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: 'Test Customer 5'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 10'},
- ]
- ]}
-
- ]);
- },
- () => cur_frm.save(),
- () => frappe.tests.click_button('Submit'),
- () => assert.equal("Confirm", cur_dialog.title,'confirmation for submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(3),
- () => {
-
- assert.ok(cur_frm.doc.status=="To Deliver and Bill", "It is submited. Credit limit is NOT checked for sales order");
-
-
- },
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_discount_on_grand_total.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_discount_on_grand_total.js
deleted file mode 100644
index de61a61..0000000
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_discount_on_grand_total.js
+++ /dev/null
@@ -1,43 +0,0 @@
-QUnit.module('Sales Order');
-
-QUnit.test("test sales order with additional discount in grand total", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 4'},
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {payment_terms_template: '_Test Payment Term Template UI'}
- ]);
- },
- () => {
- return frappe.tests.set_form_values(cur_frm, [
- {apply_discount_on:'Grand Total'},
- {additional_discount_percentage:10},
- {payment_schedule: []}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- // get grand_total details
- assert.ok(cur_frm.doc.grand_total== 450, "Grand total correct ");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_item_wise_discount.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_item_wise_discount.js
deleted file mode 100644
index 2c48108..0000000
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_item_wise_discount.js
+++ /dev/null
@@ -1,38 +0,0 @@
-QUnit.module('Sales Order');
-
-QUnit.test("test sales order", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 4'},
- {'discount_percentage': 10},
- {'margin_type': 'Percentage'}
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {payment_terms_template: '_Test Payment Term Template UI'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- // get grand_total details
- assert.ok(cur_frm.doc.grand_total== 450, "Grand total correct ");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_margin.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_margin.js
deleted file mode 100644
index 9eebfda..0000000
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_margin.js
+++ /dev/null
@@ -1,37 +0,0 @@
-QUnit.module('Selling');
-
-QUnit.test("test sales order with margin", function(assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Order', [
- {customer:'Test Customer 1'},
- {selling_price_list: 'Test-Selling-USD'},
- {currency: 'USD'},
- {items: [
- [
- {'item_code': 'Test Product 4'},
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 1},
- {'margin_type': 'Amount'},
- {'margin_rate_or_amount': 20}
- ]
- ]},
- ]);
- },
-
- () => cur_frm.save(),
- () => {
- // get_rate_details
- assert.ok(cur_frm.doc.items[0].rate_with_margin == 220, "Margin rate correct");
- assert.ok(cur_frm.doc.items[0].base_rate_with_margin == cur_frm.doc.conversion_rate * 220, "Base margin rate correct");
- assert.ok(cur_frm.doc.total == 220, "Amount correct");
- },
-
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_multi_uom.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_multi_uom.js
deleted file mode 100644
index 84301f5..0000000
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_multi_uom.js
+++ /dev/null
@@ -1,38 +0,0 @@
-QUnit.module('Sales Order');
-
-QUnit.test("test sales order", function(assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 4'},
- {'uom': 'Unit'},
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- // get uom details
- assert.ok(cur_frm.doc.items[0].uom=='Unit', "Multi Uom correct");
- // get grand_total details
- assert.ok(cur_frm.doc.grand_total== 5000, "Grand total correct ");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_multiple_delivery_date.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_multiple_delivery_date.js
deleted file mode 100644
index be76c49..0000000
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_multiple_delivery_date.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/* eslint-disable */
-// rename this file from _test_[name] to test_[name] to activate
-// and remove above this line
-
-QUnit.test("test: Sales Order", function (assert) {
- assert.expect(2);
- let done = assert.async();
- let delivery_date = frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1);
-
- frappe.run_serially([
- // insert a new Sales Order
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: "Test Customer 1"},
- {delivery_date: delivery_date},
- {order_type: 'Sales'},
- {items: [
- [
- {"item_code": "Test Product 1"},
- {"qty": 5},
- {'rate': 100},
- ]]
- }
- ])
- },
- () => {
- assert.ok(cur_frm.doc.items[0].delivery_date == delivery_date);
- },
- () => frappe.timeout(1),
- // make SO without delivery date in parent,
- // parent delivery date should be set based on final delivery date entered in item
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: "Test Customer 1"},
- {order_type: 'Sales'},
- {items: [
- [
- {"item_code": "Test Product 1"},
- {"qty": 5},
- {'rate': 100},
- {'delivery_date': delivery_date}
- ],
- [
- {"item_code": "Test Product 2"},
- {"qty": 5},
- {'rate': 100},
- {'delivery_date': frappe.datetime.add_days(delivery_date, 5)}
- ]]
- }
- ])
- },
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => {
- assert.ok(cur_frm.doc.delivery_date == frappe.datetime.add_days(delivery_date, 5));
- },
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_pricing_rule.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_pricing_rule.js
deleted file mode 100644
index e91fb01..0000000
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_pricing_rule.js
+++ /dev/null
@@ -1,34 +0,0 @@
-QUnit.module('Sales Order');
-
-QUnit.test("test sales order with shipping rule", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: 'Test Customer 3'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 2'},
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 2', "Item name correct");
- // get grand_total details
- assert.ok(cur_frm.doc.grand_total== 675, "Grand total correct ");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_shipping_rule.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_shipping_rule.js
deleted file mode 100644
index 7d1211f..0000000
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_shipping_rule.js
+++ /dev/null
@@ -1,35 +0,0 @@
-QUnit.module('Sales Order');
-
-QUnit.test("test sales order with shipping rule", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 4'},
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {shipping_rule:'Next Day Shipping'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- // get grand_total details
- assert.ok(cur_frm.doc.grand_total== 550, "Grand total correct ");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_taxes_and_charges.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_taxes_and_charges.js
deleted file mode 100644
index a3668ab..0000000
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order_with_taxes_and_charges.js
+++ /dev/null
@@ -1,40 +0,0 @@
-QUnit.module('Sales Order');
-
-QUnit.test("test sales order with taxes and charges", function(assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: 'Test Customer 1'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 4'},
- ]
- ]},
- {customer_address: 'Test1-Billing'},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {taxes_and_charges: 'TEST In State GST - FT'},
- {tc_name: 'Test Term 1'},
- {terms: 'This is Test'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- // get tax details
- assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
- // get tax account head details
- assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/doctype/sales_order/tests/test_sales_order_without_bypass_credit_limit_check.js b/erpnext/selling/doctype/sales_order/tests/test_sales_order_without_bypass_credit_limit_check.js
deleted file mode 100644
index 8de39f9..0000000
--- a/erpnext/selling/doctype/sales_order/tests/test_sales_order_without_bypass_credit_limit_check.js
+++ /dev/null
@@ -1,62 +0,0 @@
-QUnit.module('Sales Order');
-
-QUnit.test("test_sales_order_without_bypass_credit_limit_check", function(assert) {
-//#PR : 10861, Author : ashish-greycube & jigneshpshah, Email:mr.ashish.shah@gmail.com
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => frappe.new_doc('Customer'),
- () => frappe.timeout(1),
- () => frappe.quick_entry.dialog.$wrapper.find('.edit-full').click(),
- () => frappe.timeout(1),
- () => cur_frm.set_value("customer_name", "Test Customer 11"),
- () => cur_frm.add_child('credit_limits', {
- 'credit_limit': 1000,
- 'company': '_Test Company',
- 'bypass_credit_limit_check': 1}),
- // save form
- () => cur_frm.save(),
- () => frappe.timeout(1),
-
- () => frappe.new_doc('Item'),
- () => frappe.timeout(1),
- () => frappe.click_link('Edit in full page'),
- () => cur_frm.set_value("item_code", "Test Product 11"),
- () => cur_frm.set_value("item_group", "Products"),
- () => cur_frm.set_value("standard_rate", 100),
- // save form
- () => cur_frm.save(),
- () => frappe.timeout(1),
-
- () => {
- return frappe.tests.make('Sales Order', [
- {customer: 'Test Customer 11'},
- {items: [
- [
- {'delivery_date': frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)},
- {'qty': 5},
- {'item_code': 'Test Product 11'},
- ]
- ]}
-
- ]);
- },
- () => cur_frm.save(),
- () => frappe.tests.click_button('Submit'),
- () => assert.equal("Confirm", cur_dialog.title,'confirmation for submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(3),
- () => {
-
- if (cur_dialog.body.innerText.match(/^Credit limit has been crossed for customer.*$/))
- {
- /*Match found */
- assert.ok(true, "Credit Limit crossed message received");
- }
-
-
- },
- () => cur_dialog.cancel(),
- () => done()
- ]);
-});
diff --git a/erpnext/selling/form_tour/customer/customer.json b/erpnext/selling/form_tour/customer/customer.json
new file mode 100644
index 0000000..1de45b7
--- /dev/null
+++ b/erpnext/selling/form_tour/customer/customer.json
@@ -0,0 +1,29 @@
+{
+ "creation": "2021-11-23 10:44:13.185982",
+ "docstatus": 0,
+ "doctype": "Form Tour",
+ "idx": 0,
+ "is_standard": 1,
+ "modified": "2021-11-23 10:54:09.602358",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Customer",
+ "owner": "Administrator",
+ "reference_doctype": "Customer",
+ "save_on_complete": 1,
+ "steps": [
+ {
+ "description": "Enter the Full Name of the Customer",
+ "field": "",
+ "fieldname": "customer_name",
+ "fieldtype": "Data",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Full Name",
+ "parent_field": "",
+ "position": "Left",
+ "title": "Full Name"
+ }
+ ],
+ "title": "Customer"
+}
\ No newline at end of file
diff --git a/erpnext/selling/form_tour/quotation/quotation.json b/erpnext/selling/form_tour/quotation/quotation.json
new file mode 100644
index 0000000..2a2aa5e
--- /dev/null
+++ b/erpnext/selling/form_tour/quotation/quotation.json
@@ -0,0 +1,67 @@
+{
+ "creation": "2021-11-23 12:00:36.138824",
+ "docstatus": 0,
+ "doctype": "Form Tour",
+ "idx": 0,
+ "is_standard": 1,
+ "modified": "2021-11-23 12:02:48.010298",
+ "modified_by": "Administrator",
+ "module": "Selling",
+ "name": "Quotation",
+ "owner": "Administrator",
+ "reference_doctype": "Quotation",
+ "save_on_complete": 1,
+ "steps": [
+ {
+ "description": "Select a customer or lead for whom this quotation is being prepared. Let's select a Customer.",
+ "field": "",
+ "fieldname": "quotation_to",
+ "fieldtype": "Link",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Quotation To",
+ "parent_field": "",
+ "position": "Right",
+ "title": "Quotation To"
+ },
+ {
+ "description": "Select a specific Customer to whom this quotation will be sent.",
+ "field": "",
+ "fieldname": "party_name",
+ "fieldtype": "Dynamic Link",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Party",
+ "parent_field": "",
+ "position": "Right",
+ "title": "Party"
+ },
+ {
+ "child_doctype": "Quotation Item",
+ "description": "Select an item for which you will be quoting a price.",
+ "field": "",
+ "fieldname": "items",
+ "fieldtype": "Table",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Items",
+ "parent_field": "",
+ "parent_fieldname": "items",
+ "position": "Bottom",
+ "title": "Items"
+ },
+ {
+ "description": "You can select pre-populated Sales Taxes and Charges from here.",
+ "field": "",
+ "fieldname": "taxes",
+ "fieldtype": "Table",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Sales Taxes and Charges",
+ "parent_field": "",
+ "position": "Bottom",
+ "title": "Sales Taxes and Charges"
+ }
+ ],
+ "title": "Quotation"
+}
\ No newline at end of file
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index e2e0db4..540aca2 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -41,6 +41,7 @@
me.frm.set_query('contact_person', erpnext.queries.contact_query);
me.frm.set_query('customer_address', erpnext.queries.address_query);
me.frm.set_query('shipping_address_name', erpnext.queries.address_query);
+ me.frm.set_query('dispatch_address_name', erpnext.queries.dispatch_address_query);
if(this.frm.fields_dict.selling_price_list) {
diff --git a/erpnext/setup/doctype/company/test_records.json b/erpnext/setup/doctype/company/test_records.json
index 9e55702..89be607 100644
--- a/erpnext/setup/doctype/company/test_records.json
+++ b/erpnext/setup/doctype/company/test_records.json
@@ -36,7 +36,7 @@
"abbr": "_TC3",
"company_name": "_Test Company 3",
"is_group": 1,
- "country": "India",
+ "country": "Pakistan",
"default_currency": "INR",
"doctype": "Company",
"domain": "Manufacturing",
@@ -49,7 +49,7 @@
"company_name": "_Test Company 4",
"parent_company": "_Test Company 3",
"is_group": 1,
- "country": "India",
+ "country": "Pakistan",
"default_currency": "INR",
"doctype": "Company",
"domain": "Manufacturing",
@@ -61,7 +61,7 @@
"abbr": "_TC5",
"company_name": "_Test Company 5",
"parent_company": "_Test Company 4",
- "country": "India",
+ "country": "Pakistan",
"default_currency": "INR",
"doctype": "Company",
"domain": "Manufacturing",
diff --git a/erpnext/setup/doctype/company/tests/test_company.js b/erpnext/setup/doctype/company/tests/test_company.js
deleted file mode 100644
index b568494..0000000
--- a/erpnext/setup/doctype/company/tests/test_company.js
+++ /dev/null
@@ -1,25 +0,0 @@
-QUnit.module('setup');
-
-QUnit.test("Test: Company [SetUp]", function (assert) {
- assert.expect(2);
- let done = assert.async();
-
- frappe.run_serially([
- // test company creation
- () => frappe.set_route("List", "Company", "List"),
- () => frappe.new_doc("Company"),
- () => frappe.timeout(1),
- () => cur_frm.set_value("company_name", "Test Company"),
- () => cur_frm.set_value("abbr", "TC"),
- () => cur_frm.set_value("domain", "Services"),
- () => cur_frm.set_value("default_currency", "INR"),
- // save form
- () => cur_frm.save(),
- () => frappe.timeout(1),
- () => assert.equal("Debtors - TC", cur_frm.doc.default_receivable_account,
- 'chart of acounts created'),
- () => assert.equal("Main - TC", cur_frm.doc.cost_center,
- 'chart of cost centers created'),
- () => done()
- ]);
-});
diff --git a/erpnext/setup/doctype/company/tests/test_company_production.js b/erpnext/setup/doctype/company/tests/test_company_production.js
deleted file mode 100644
index a4c1e2e..0000000
--- a/erpnext/setup/doctype/company/tests/test_company_production.js
+++ /dev/null
@@ -1,19 +0,0 @@
-QUnit.test("Test: Company", function (assert) {
- assert.expect(0);
-
- let done = assert.async();
-
- frappe.run_serially([
- // Added company for Work Order testing
- () => frappe.set_route("List", "Company"),
- () => frappe.new_doc("Company"),
- () => frappe.timeout(1),
- () => cur_frm.set_value("company_name", "For Testing"),
- () => cur_frm.set_value("abbr", "RB"),
- () => cur_frm.set_value("default_currency", "INR"),
- () => cur_frm.save(),
- () => frappe.timeout(1),
-
- () => done()
- ]);
-});
diff --git a/erpnext/setup/form_tour/company/company.json b/erpnext/setup/form_tour/company/company.json
new file mode 100644
index 0000000..c66abc0
--- /dev/null
+++ b/erpnext/setup/form_tour/company/company.json
@@ -0,0 +1,67 @@
+{
+ "creation": "2021-11-24 10:17:18.534917",
+ "docstatus": 0,
+ "doctype": "Form Tour",
+ "first_document": 1,
+ "idx": 0,
+ "include_name_field": 0,
+ "is_standard": 1,
+ "modified": "2021-11-24 15:38:21.026582",
+ "modified_by": "Administrator",
+ "module": "Setup",
+ "name": "Company",
+ "owner": "Administrator",
+ "reference_doctype": "Company",
+ "save_on_complete": 0,
+ "steps": [
+ {
+ "description": "This is the default currency for this company.",
+ "field": "",
+ "fieldname": "default_currency",
+ "fieldtype": "Link",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Default Currency",
+ "parent_field": "",
+ "position": "Right",
+ "title": "Default Currency"
+ },
+ {
+ "description": "Here, you can add multiple addresses of the company",
+ "field": "",
+ "fieldname": "company_info",
+ "fieldtype": "Section Break",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Address & Contact",
+ "parent_field": "",
+ "position": "Top",
+ "title": "Address & Contact"
+ },
+ {
+ "description": "Here, you can set default Accounts, which will ease the creation of accounting entries.",
+ "field": "",
+ "fieldname": "default_settings",
+ "fieldtype": "Section Break",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Accounts Settings",
+ "parent_field": "",
+ "position": "Top",
+ "title": "Accounts Settings"
+ },
+ {
+ "description": "This setting is recommended if you wish to track the real-time stock balance in your books of account. This will allow the creation of a General Ledger entry for every stock transaction.",
+ "field": "",
+ "fieldname": "enable_perpetual_inventory",
+ "fieldtype": "Check",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Enable Perpetual Inventory",
+ "parent_field": "",
+ "position": "Right",
+ "title": "Enable Perpetual Inventory"
+ }
+ ],
+ "title": "Company"
+}
\ No newline at end of file
diff --git a/erpnext/setup/module_onboarding/home/home.json b/erpnext/setup/module_onboarding/home/home.json
new file mode 100644
index 0000000..1b2dbc6
--- /dev/null
+++ b/erpnext/setup/module_onboarding/home/home.json
@@ -0,0 +1,62 @@
+{
+ "allow_roles": [
+ {
+ "role": "Accounts Manager"
+ },
+ {
+ "role": "Stock Manager"
+ },
+ {
+ "role": "Sales Manager"
+ },
+ {
+ "role": "Purchase Manager"
+ },
+ {
+ "role": "Manufacturing Manager"
+ },
+ {
+ "role": "Item Manager"
+ }
+ ],
+ "creation": "2021-11-22 12:19:15.888642",
+ "docstatus": 0,
+ "doctype": "Module Onboarding",
+ "documentation_url": "https://docs.erpnext.com/docs/v13/user/manual/en/setting-up/company-setup",
+ "idx": 0,
+ "is_complete": 0,
+ "modified": "2021-12-15 14:23:52.460913",
+ "modified_by": "Administrator",
+ "module": "Setup",
+ "name": "Home",
+ "owner": "Administrator",
+ "steps": [
+ {
+ "step": "Company Set Up"
+ },
+ {
+ "step": "Navigation Help"
+ },
+ {
+ "step": "Data import"
+ },
+ {
+ "step": "Create an Item"
+ },
+ {
+ "step": "Create a Customer"
+ },
+ {
+ "step": "Create a Supplier"
+ },
+ {
+ "step": "Create a Quotation"
+ },
+ {
+ "step": "Letterhead"
+ }
+ ],
+ "subtitle": "Company, Item, Customer, Supplier, Navigation Help, Data Import, Letter Head, Quotation",
+ "success_message": "Masters are all set up!",
+ "title": "Let's Set Up Some Masters"
+}
\ No newline at end of file
diff --git a/erpnext/setup/onboarding_step/company_set_up/company_set_up.json b/erpnext/setup/onboarding_step/company_set_up/company_set_up.json
new file mode 100644
index 0000000..6f65832
--- /dev/null
+++ b/erpnext/setup/onboarding_step/company_set_up/company_set_up.json
@@ -0,0 +1,21 @@
+{
+ "action": "Create Entry",
+ "action_label": "Let's review your Company",
+ "creation": "2021-11-22 11:55:48.931427",
+ "description": "# Set Up a Company\n\nA company is a legal entity for which you will set up your books of account and create accounting transactions. In ERPNext, you can 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-12-15 14:22:18.317423",
+ "modified_by": "Administrator",
+ "name": "Company Set Up",
+ "owner": "Administrator",
+ "reference_document": "Company",
+ "show_form_tour": 1,
+ "show_full_form": 1,
+ "title": "Set Up a Company",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/setup/onboarding_step/create_a_customer/create_a_customer.json b/erpnext/setup/onboarding_step/create_a_customer/create_a_customer.json
new file mode 100644
index 0000000..f74d745
--- /dev/null
+++ b/erpnext/setup/onboarding_step/create_a_customer/create_a_customer.json
@@ -0,0 +1,21 @@
+{
+ "action": "Create Entry",
+ "action_label": "Let\u2019s create your first Customer",
+ "creation": "2020-05-14 17:46:41.831517",
+ "description": "# Create a Customer\n\nThe Customer master is at the heart of your sales transactions. Customers are linked in Quotations, Sales Orders, Invoices, and Payments. Customers can be either numbered or identified by name (you would typically do this based on the number of customers you have).\n\nThrough Customer\u2019s master, you can effectively track essentials like:\n - Customer\u2019s multiple address and contacts\n - Account Receivables\n - Credit Limit and Credit Period\n",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-12-15 14:20:31.197564",
+ "modified_by": "Administrator",
+ "name": "Create a Customer",
+ "owner": "Administrator",
+ "reference_document": "Customer",
+ "show_form_tour": 0,
+ "show_full_form": 0,
+ "title": "Manage Customers",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/setup/onboarding_step/create_a_quotation/create_a_quotation.json b/erpnext/setup/onboarding_step/create_a_quotation/create_a_quotation.json
new file mode 100644
index 0000000..8bdb621
--- /dev/null
+++ b/erpnext/setup/onboarding_step/create_a_quotation/create_a_quotation.json
@@ -0,0 +1,21 @@
+{
+ "action": "Create Entry",
+ "action_label": "Let\u2019s create your first Quotation",
+ "creation": "2020-06-01 13:34:58.958641",
+ "description": "# Create a Quotation\n\nLet\u2019s get started with business transactions by creating your first Quotation. You can create a Quotation for an existing customer or a prospect. It will be an approved document, with items you sell and the proposed price + taxes applied. After completing the instructions, you will get a Quotation in a ready to share print format.",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-12-15 14:21:31.675330",
+ "modified_by": "Administrator",
+ "name": "Create a Quotation",
+ "owner": "Administrator",
+ "reference_document": "Quotation",
+ "show_form_tour": 1,
+ "show_full_form": 1,
+ "title": "Create your first Quotation",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/setup/onboarding_step/create_a_supplier/create_a_supplier.json b/erpnext/setup/onboarding_step/create_a_supplier/create_a_supplier.json
new file mode 100644
index 0000000..9574141
--- /dev/null
+++ b/erpnext/setup/onboarding_step/create_a_supplier/create_a_supplier.json
@@ -0,0 +1,21 @@
+{
+ "action": "Create Entry",
+ "action_label": "Let\u2019s create your first Supplier",
+ "creation": "2020-05-14 22:09:10.043554",
+ "description": "# Create a Supplier\n\nAlso known as Vendor, is a master at the center of your purchase transactions. Suppliers are linked in Request for Quotation, Purchase Orders, Receipts, and Payments. Suppliers can be either numbered or identified by name.\n\nThrough Supplier\u2019s master, you can effectively track essentials like:\n - Supplier\u2019s multiple address and contacts\n - Account Receivables\n - Credit Limit and Credit Period\n",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-12-15 14:21:23.518301",
+ "modified_by": "Administrator",
+ "name": "Create a Supplier",
+ "owner": "Administrator",
+ "reference_document": "Supplier",
+ "show_form_tour": 0,
+ "show_full_form": 0,
+ "title": "Manage Suppliers",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/setup/onboarding_step/create_an_item/create_an_item.json b/erpnext/setup/onboarding_step/create_an_item/create_an_item.json
new file mode 100644
index 0000000..cd29683
--- /dev/null
+++ b/erpnext/setup/onboarding_step/create_an_item/create_an_item.json
@@ -0,0 +1,23 @@
+{
+ "action": "Create Entry",
+ "action_label": "Create a new Item",
+ "creation": "2021-05-17 13:47:18.515052",
+ "description": "# Create an Item\n\nItem is a product, of a or service offered by your company, or something you buy as a part of your supplies or raw materials.\n\nItems are integral to everything you do in ERPNext - from billing, purchasing to managing inventory. Everything you buy or sell, whether it is a physical product or a service is an Item. Items can be stock, non-stock, variants, serialized, batched, assets etc.\n",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "form_tour": "Item General",
+ "idx": 0,
+ "intro_video_url": "",
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-12-15 14:19:56.297772",
+ "modified_by": "Administrator",
+ "name": "Create an Item",
+ "owner": "Administrator",
+ "reference_document": "Item",
+ "show_form_tour": 1,
+ "show_full_form": 1,
+ "title": "Manage Items",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/setup/onboarding_step/data_import/data_import.json b/erpnext/setup/onboarding_step/data_import/data_import.json
new file mode 100644
index 0000000..48741dc
--- /dev/null
+++ b/erpnext/setup/onboarding_step/data_import/data_import.json
@@ -0,0 +1,21 @@
+{
+ "action": "Watch Video",
+ "action_label": "Learn more about data migration",
+ "creation": "2021-05-19 05:29:16.809610",
+ "description": "# Import Data from Spreadsheet\n\nIn ERPNext, you can easily migrate your historical data using spreadsheets. You can use it for migrating not just masters (like Customer, Supplier, Items), but also for transactions like (outstanding invoices, opening stock and accounting entries, etc). If you are migrating from [Tally](https://tallysolutions.com/) or [Quickbooks](https://quickbooks.intuit.com/in/), we got special migration tools for you.",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-12-15 13:10:57.346422",
+ "modified_by": "Administrator",
+ "name": "Data import",
+ "owner": "Administrator",
+ "show_form_tour": 0,
+ "show_full_form": 0,
+ "title": "Import Data from Spreadsheet",
+ "validate_action": 1,
+ "video_url": "https://youtu.be/DQyqeurPI64"
+}
\ No newline at end of file
diff --git a/erpnext/setup/onboarding_step/letterhead/letterhead.json b/erpnext/setup/onboarding_step/letterhead/letterhead.json
new file mode 100644
index 0000000..8e1bb8c
--- /dev/null
+++ b/erpnext/setup/onboarding_step/letterhead/letterhead.json
@@ -0,0 +1,21 @@
+{
+ "action": "Create Entry",
+ "action_label": "Let\u2019s setup your first Letter Head",
+ "creation": "2021-11-22 12:36:34.583783",
+ "description": "# Create a Letter Head\n\nA Letter Head contains your organization's name, logo, address, etc which appears at the header and footer portion in documents. You can learn more about Setting up Letter Head in ERPNext here.\n",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-12-15 14:21:39.037742",
+ "modified_by": "Administrator",
+ "name": "Letterhead",
+ "owner": "Administrator",
+ "reference_document": "Letter Head",
+ "show_form_tour": 1,
+ "show_full_form": 1,
+ "title": "Setup Your Letterhead",
+ "validate_action": 1
+}
\ No newline at end of file
diff --git a/erpnext/setup/onboarding_step/navigation_help/navigation_help.json b/erpnext/setup/onboarding_step/navigation_help/navigation_help.json
new file mode 100644
index 0000000..388853d
--- /dev/null
+++ b/erpnext/setup/onboarding_step/navigation_help/navigation_help.json
@@ -0,0 +1,21 @@
+{
+ "action": "Watch Video",
+ "action_label": "Learn about Navigation options",
+ "creation": "2021-11-22 12:09:52.233872",
+ "description": "# Navigation in ERPNext\n\nEase of navigating and browsing around the ERPNext is one of our core strengths. In the following video, you will learn how to reach a specific feature in ERPNext via module page or awesome bar\u2019s shortcut.\n",
+ "docstatus": 0,
+ "doctype": "Onboarding Step",
+ "idx": 0,
+ "is_complete": 0,
+ "is_single": 0,
+ "is_skipped": 0,
+ "modified": "2021-12-15 14:20:55.441678",
+ "modified_by": "Administrator",
+ "name": "Navigation Help",
+ "owner": "Administrator",
+ "show_form_tour": 0,
+ "show_full_form": 0,
+ "title": "How to Navigate in ERPNext",
+ "validate_action": 1,
+ "video_url": "https://youtu.be/j60xyNFqX_A"
+}
\ No newline at end of file
diff --git a/erpnext/setup/workspace/home/home.json b/erpnext/setup/workspace/home/home.json
index 4e1ccf9..f9c585c0 100644
--- a/erpnext/setup/workspace/home/home.json
+++ b/erpnext/setup/workspace/home/home.json
@@ -1,13 +1,18 @@
{
"charts": [],
- "content": "[{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Customer\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Supplier\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Leaderboard\",\"col\":4}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\",\"level\":4,\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Human Resources\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"CRM\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Data Import and Settings\",\"col\":4}}]",
+ "content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Home\",\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Customer\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Supplier\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Leaderboard\",\"col\":4}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Accounting\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Stock\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Human Resources\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"CRM\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Data Import and Settings\",\"col\":4}}]",
"creation": "2020-01-23 13:46:38.833076",
+ "developer_mode_only": 0,
+ "disable_user_customization": 0,
"docstatus": 0,
"doctype": "Workspace",
+ "extends_another_page": 0,
"for_user": "",
"hide_custom": 0,
"icon": "getting-started",
"idx": 0,
+ "is_default": 0,
+ "is_standard": 0,
"label": "Home",
"links": [
{
@@ -271,12 +276,14 @@
"type": "Link"
}
],
- "modified": "2021-08-10 15:33:20.704741",
+ "modified": "2021-11-22 12:50:15.771366",
"modified_by": "Administrator",
"module": "Setup",
"name": "Home",
"owner": "Administrator",
"parent_page": "",
+ "pin_to_bottom": 0,
+ "pin_to_top": 0,
"public": 1,
"restrict_to_domain": "",
"roles": [],
@@ -309,4 +316,4 @@
}
],
"title": "Home"
-}
\ No newline at end of file
+}
diff --git a/erpnext/stock/doctype/batch/test_batch.js b/erpnext/stock/doctype/batch/test_batch.js
deleted file mode 100644
index 2d2150b..0000000
--- a/erpnext/stock/doctype/batch/test_batch.js
+++ /dev/null
@@ -1,22 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test Batch", function(assert) {
- assert.expect(1);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Batch', [
- {batch_id:'TEST-BATCH-001'},
- {item:'Test Product 4'},
- {expiry_date:frappe.datetime.add_days(frappe.datetime.now_date(), 2)},
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.batch_id=='TEST-BATCH-001', "Batch Id correct");
- },
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py
index 37b5411..0ef7ce2 100644
--- a/erpnext/stock/doctype/bin/bin.py
+++ b/erpnext/stock/doctype/bin/bin.py
@@ -130,8 +130,8 @@
"""WARNING: This function is deprecated. Inline this function instead of using it."""
from erpnext.stock.stock_ledger import repost_current_voucher
- update_qty(bin_name, args)
repost_current_voucher(args, allow_negative_stock, via_landed_cost_voucher)
+ update_qty(bin_name, args)
def get_bin_details(bin_name):
return frappe.db.get_value('Bin', bin_name, ['actual_qty', 'ordered_qty',
@@ -139,13 +139,23 @@
'reserved_qty_for_sub_contract'], as_dict=1)
def update_qty(bin_name, args):
- bin_details = get_bin_details(bin_name)
+ from erpnext.controllers.stock_controller import future_sle_exists
- # update the stock values (for current quantities)
- if args.get("voucher_type")=="Stock Reconciliation":
- actual_qty = args.get('qty_after_transaction')
- else:
- actual_qty = bin_details.actual_qty + flt(args.get("actual_qty"))
+ bin_details = get_bin_details(bin_name)
+ # actual qty is already updated by processing current voucher
+ actual_qty = bin_details.actual_qty
+
+ # actual qty is not up to date in case of backdated transaction
+ if future_sle_exists(args):
+ actual_qty = frappe.db.get_value("Stock Ledger Entry",
+ filters={
+ "item_code": args.get("item_code"),
+ "warehouse": args.get("warehouse"),
+ "is_cancelled": 0
+ },
+ fieldname="qty_after_transaction",
+ order_by="posting_date desc, posting_time desc, creation desc",
+ ) or 0.0
ordered_qty = flt(bin_details.ordered_qty) + flt(args.get("ordered_qty"))
reserved_qty = flt(bin_details.reserved_qty) + flt(args.get("reserved_qty"))
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.js b/erpnext/stock/doctype/delivery_note/test_delivery_note.js
deleted file mode 100644
index 76f7989..0000000
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.js
+++ /dev/null
@@ -1,35 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test delivery note", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Delivery Note', [
- {customer:'Test Customer 1'},
- {items: [
- [
- {'item_code': 'Test Product 1'},
- {'qty': 5},
- ]
- ]},
- {shipping_address_name: 'Test1-Shipping'},
- {contact_person: 'Contact 1-Test Customer 1'},
- {taxes_and_charges: 'TEST In State GST - FT'},
- {tc_name: 'Test Term 1'},
- {transporter_name:'TEST TRANSPORT'},
- {lr_no:'MH-04-FG 1111'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- assert.ok(cur_frm.doc.grand_total==590, " Grand Total correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note_with_margin.js b/erpnext/stock/doctype/delivery_note/test_delivery_note_with_margin.js
deleted file mode 100644
index 9f1375f..0000000
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note_with_margin.js
+++ /dev/null
@@ -1,36 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test delivery note with margin", function(assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Delivery Note', [
- {customer:'Test Customer 1'},
- {selling_price_list: 'Test-Selling-USD'},
- {currency: 'USD'},
- {items: [
- [
- {'item_code': 'Test Product 4'},
- {'qty': 1},
- {'margin_type': 'Amount'},
- {'margin_rate_or_amount': 10}
- ]
- ]},
- ]);
- },
-
- () => cur_frm.save(),
- () => {
- // get_rate_details
- assert.ok(cur_frm.doc.items[0].rate_with_margin == 210, "Margin rate correct");
- assert.ok(cur_frm.doc.items[0].base_rate_with_margin == cur_frm.doc.conversion_rate * 210, "Base margin rate correct");
- assert.ok(cur_frm.doc.total == 210, "Amount correct");
- },
-
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/item/tests/test_item.js b/erpnext/stock/doctype/item/tests/test_item.js
deleted file mode 100644
index 7f7e72d..0000000
--- a/erpnext/stock/doctype/item/tests/test_item.js
+++ /dev/null
@@ -1,121 +0,0 @@
-QUnit.module('stock');
-QUnit.test("test: item", function (assert) {
- assert.expect(6);
- let done = assert.async();
- let keyboard_cost = 800;
- let screen_cost = 4000;
- let CPU_cost = 15000;
- let scrap_cost = 100;
- let no_of_items_to_stock = 100;
- let is_stock_item = 1;
- frappe.run_serially([
- // test item creation
- () => frappe.set_route("List", "Item"),
-
- // Create a keyboard item
- () => frappe.tests.make(
- "Item", [
- {item_code: "Keyboard"},
- {item_group: "Products"},
- {is_stock_item: is_stock_item},
- {standard_rate: keyboard_cost},
- {opening_stock: no_of_items_to_stock},
- {default_warehouse: "Stores - FT"}
- ]
- ),
- () => {
- assert.ok(cur_frm.doc.item_name.includes('Keyboard'),
- 'Item Keyboard created correctly');
- assert.ok(cur_frm.doc.item_code.includes('Keyboard'),
- 'item_code for Keyboard set correctly');
- assert.ok(cur_frm.doc.item_group.includes('Products'),
- 'item_group for Keyboard set correctly');
- assert.equal(cur_frm.doc.is_stock_item, is_stock_item,
- 'is_stock_item for Keyboard set correctly');
- assert.equal(cur_frm.doc.standard_rate, keyboard_cost,
- 'standard_rate for Keyboard set correctly');
- assert.equal(cur_frm.doc.opening_stock, no_of_items_to_stock,
- 'opening_stock for Keyboard set correctly');
- },
-
- // Create a Screen item
- () => frappe.tests.make(
- "Item", [
- {item_code: "Screen"},
- {item_group: "Products"},
- {is_stock_item: is_stock_item},
- {standard_rate: screen_cost},
- {opening_stock: no_of_items_to_stock},
- {default_warehouse: "Stores - FT"}
- ]
- ),
-
- // Create a CPU item
- () => frappe.tests.make(
- "Item", [
- {item_code: "CPU"},
- {item_group: "Products"},
- {is_stock_item: is_stock_item},
- {standard_rate: CPU_cost},
- {opening_stock: no_of_items_to_stock},
- {default_warehouse: "Stores - FT"}
- ]
- ),
-
- // Create a laptop item
- () => frappe.tests.make(
- "Item", [
- {item_code: "Laptop"},
- {item_group: "Products"},
- {default_warehouse: "Stores - FT"}
- ]
- ),
- () => frappe.tests.make(
- "Item", [
- {item_code: "Computer"},
- {item_group: "Products"},
- {is_stock_item: 0},
- ]
- ),
-
- // Create a scrap item
- () => frappe.tests.make(
- "Item", [
- {item_code: "Scrap item"},
- {item_group: "Products"},
- {is_stock_item: is_stock_item},
- {standard_rate: scrap_cost},
- {opening_stock: no_of_items_to_stock},
- {default_warehouse: "Stores - FT"}
- ]
- ),
- () => frappe.tests.make(
- "Item", [
- {item_code: "Test Product 4"},
- {item_group: "Products"},
- {is_stock_item: 1},
- {has_batch_no: 1},
- {create_new_batch: 1},
- {uoms:
- [
- [
- {uom:"Unit"},
- {conversion_factor: 10},
- ]
- ]
- },
- {taxes:
- [
- [
- {tax_type:"SGST - "+frappe.get_abbr(frappe.defaults.get_default("Company"))},
- {tax_rate: 0},
- ]
- ]},
- {has_serial_no: 1},
- {standard_rate: 100},
- {opening_stock: 100},
- ]
- ),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/item_price/test_item_price.js b/erpnext/stock/doctype/item_price/test_item_price.js
deleted file mode 100644
index 49dbaa2..0000000
--- a/erpnext/stock/doctype/item_price/test_item_price.js
+++ /dev/null
@@ -1,22 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test item price", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Item Price', [
- {price_list:'Test-Selling-USD'},
- {item_code: 'Test Product 4'},
- {price_list_rate: 200}
- ]);
- },
- () => cur_frm.save(),
- () => {
- assert.ok(cur_frm.doc.item_name == 'Test Product 4', "Item name correct");
- assert.ok(cur_frm.doc.price_list_rate == 200, "Price list rate correct");
- },
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/material_request/tests/test_material_request.js b/erpnext/stock/doctype/material_request/tests/test_material_request.js
deleted file mode 100644
index a2cd03b..0000000
--- a/erpnext/stock/doctype/material_request/tests/test_material_request.js
+++ /dev/null
@@ -1,39 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test material request", function(assert) {
- assert.expect(5);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Material Request', [
- {items: [
- [
- {'schedule_date': frappe.datetime.add_days(frappe.datetime.nowdate(), 5)},
- {'qty': 5},
- {'item_code': 'Test Product 1'},
- ],
- [
- {'schedule_date': frappe.datetime.add_days(frappe.datetime.nowdate(), 6)},
- {'qty': 2},
- {'item_code': 'Test Product 2'},
- ]
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => {
- assert.ok(cur_frm.doc.schedule_date == frappe.datetime.add_days(frappe.datetime.now_date(), 5), "Schedule Date correct");
-
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- assert.ok(cur_frm.doc.items[0].schedule_date == frappe.datetime.add_days(frappe.datetime.now_date(), 5), "Schedule Date correct");
-
- assert.ok(cur_frm.doc.items[1].item_name=='Test Product 2', "Item name correct");
- assert.ok(cur_frm.doc.items[1].schedule_date == frappe.datetime.add_days(frappe.datetime.now_date(), 6), "Schedule Date correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/material_request/tests/test_material_request_from_bom.js b/erpnext/stock/doctype/material_request/tests/test_material_request_from_bom.js
deleted file mode 100644
index 6fb55ae..0000000
--- a/erpnext/stock/doctype/material_request/tests/test_material_request_from_bom.js
+++ /dev/null
@@ -1,27 +0,0 @@
-QUnit.module('manufacturing');
-
-QUnit.test("test material request get items from BOM", function(assert) {
- assert.expect(4);
- let done = assert.async();
- frappe.run_serially([
- () => frappe.set_route('Form', 'BOM'),
- () => frappe.timeout(3),
- () => frappe.click_button('Get Items from BOM'),
- () => frappe.timeout(3),
- () => {
- assert.ok(cur_dialog, 'dialog appeared');
- },
- () => cur_dialog.set_value('bom', 'Laptop'),
- () => cur_dialog.set_value('warehouse', 'Laptop Scrap Warehouse'),
- () => frappe.click_button('Get Items from BOM'),
- () => frappe.timeout(3),
- () => {
- assert.ok(cur_frm.doc.items[0].item_code, "First row is not empty");
- assert.ok(cur_frm.doc.items[0].item_name, "Item name is not empty");
- assert.equal(cur_frm.doc.items[0].item_name, "Laptop", cur_frm.doc.items[0].item_name);
- },
- () => cur_frm.doc.items[0].schedule_date = '2017-12-12',
- () => cur_frm.save(),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/material_request/tests/test_material_request_type_manufacture.js b/erpnext/stock/doctype/material_request/tests/test_material_request_type_manufacture.js
deleted file mode 100644
index 137079b..0000000
--- a/erpnext/stock/doctype/material_request/tests/test_material_request_type_manufacture.js
+++ /dev/null
@@ -1,29 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test material request", function(assert) {
- assert.expect(1);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Material Request', [
- {material_request_type:'Manufacture'},
- {items: [
- [
- {'schedule_date': frappe.datetime.add_days(frappe.datetime.nowdate(), 5)},
- {'qty': 5},
- {'item_code': 'Test Product 1'},
- ]
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/material_request/tests/test_material_request_type_material_issue.js b/erpnext/stock/doctype/material_request/tests/test_material_request_type_material_issue.js
deleted file mode 100644
index b03a854..0000000
--- a/erpnext/stock/doctype/material_request/tests/test_material_request_type_material_issue.js
+++ /dev/null
@@ -1,29 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test material request for issue", function(assert) {
- assert.expect(1);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Material Request', [
- {material_request_type:'Material Issue'},
- {items: [
- [
- {'schedule_date': frappe.datetime.add_days(frappe.datetime.nowdate(), 5)},
- {'qty': 5},
- {'item_code': 'Test Product 1'},
- ]
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/material_request/tests/test_material_request_type_material_transfer.js b/erpnext/stock/doctype/material_request/tests/test_material_request_type_material_transfer.js
deleted file mode 100644
index 7c62c2e..0000000
--- a/erpnext/stock/doctype/material_request/tests/test_material_request_type_material_transfer.js
+++ /dev/null
@@ -1,29 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test material request for transfer", function(assert) {
- assert.expect(1);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Material Request', [
- {material_request_type:'Manufacture'},
- {items: [
- [
- {'schedule_date': frappe.datetime.add_days(frappe.datetime.nowdate(), 5)},
- {'qty': 5},
- {'item_code': 'Test Product 1'},
- ]
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/price_list/test_price_list_uom.js b/erpnext/stock/doctype/price_list/test_price_list_uom.js
deleted file mode 100644
index 3896c0e..0000000
--- a/erpnext/stock/doctype/price_list/test_price_list_uom.js
+++ /dev/null
@@ -1,58 +0,0 @@
-QUnit.module('Price List');
-
-QUnit.test("test price list with uom dependancy", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
-
- () => frappe.set_route('Form', 'Price List', 'Standard Buying'),
- () => {
- cur_frm.set_value('price_not_uom_dependent','1');
- frappe.timeout(1);
- },
- () => cur_frm.save(),
-
- () => frappe.timeout(1),
-
- () => {
- return frappe.tests.make('Item Price', [
- {price_list:'Standard Buying'},
- {item_code: 'Test Product 3'},
- {price_list_rate: 200}
- ]);
- },
-
- () => cur_frm.save(),
-
- () => {
- return frappe.tests.make('Purchase Order', [
- {supplier: 'Test Supplier'},
- {currency: 'INR'},
- {buying_price_list: 'Standard Buying'},
- {items: [
- [
- {"item_code": 'Test Product 3'},
- {"schedule_date": frappe.datetime.add_days(frappe.datetime.now_date(), 2)},
- {"uom": 'Nos'},
- {"conversion_factor": 3}
- ]
- ]},
-
- ]);
- },
-
- () => cur_frm.save(),
- () => frappe.timeout(0.3),
-
- () => {
- assert.ok(cur_frm.doc.items[0].item_name == 'Test Product 3', "Item code correct");
- assert.ok(cur_frm.doc.items[0].price_list_rate == 200, "Price list rate correct");
- },
-
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(1),
-
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.js
deleted file mode 100644
index d1f4485..0000000
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.js
+++ /dev/null
@@ -1,42 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test Purchase Receipt", function(assert) {
- assert.expect(4);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Purchase Receipt', [
- {supplier: 'Test Supplier'},
- {items: [
- [
- {'received_qty': 5},
- {'qty': 4},
- {'item_code': 'Test Product 1'},
- {'uom': 'Nos'},
- {'warehouse':'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {'rejected_warehouse':'Work In Progress - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- ]
- ]},
- {taxes_and_charges: 'TEST In State GST - FT'},
- {tc_name: 'Test Term 1'},
- {terms: 'This is Test'}
- ]);
- },
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- // get tax details
- assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
- // get tax account head details
- assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
- // grand_total Calculated
- assert.ok(cur_frm.doc.grand_total==472, "Grad Total correct");
-
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.js b/erpnext/stock/doctype/quality_inspection/quality_inspection.js
index d08dc3e..eea2879 100644
--- a/erpnext/stock/doctype/quality_inspection/quality_inspection.js
+++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.js
@@ -59,7 +59,7 @@
},
item_code: function(frm) {
- if (frm.doc.item_code) {
+ if (frm.doc.item_code && !frm.doc.quality_inspection_template) {
return frm.call({
method: "get_quality_inspection_template",
doc: frm.doc,
diff --git a/erpnext/stock/doctype/quality_inspection/quality_inspection.py b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
index 913ee15..4e3b80a 100644
--- a/erpnext/stock/doctype/quality_inspection/quality_inspection.py
+++ b/erpnext/stock/doctype/quality_inspection/quality_inspection.py
@@ -18,6 +18,15 @@
if not self.readings and self.item_code:
self.get_item_specification_details()
+ if self.inspection_type=="In Process" and self.reference_type=="Job Card":
+ item_qi_template = frappe.db.get_value("Item", self.item_code, 'quality_inspection_template')
+ parameters = get_template_details(item_qi_template)
+ for reading in self.readings:
+ for d in parameters:
+ if reading.specification == d.specification:
+ reading.update(d)
+ reading.status = "Accepted"
+
if self.readings:
self.inspect_and_set_status()
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
index b2ad07f..fb3b355 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
@@ -46,7 +46,7 @@
self.db_set('status', self.status)
def on_submit(self):
- if not frappe.flags.in_test or self.flags.dont_run_in_test:
+ if not frappe.flags.in_test or self.flags.dont_run_in_test or frappe.flags.dont_execute_stock_reposts:
return
frappe.enqueue(repost, timeout=1800, queue='long',
@@ -97,7 +97,8 @@
return
doc.set_status('In Progress')
- frappe.db.commit()
+ if not frappe.flags.in_test:
+ frappe.db.commit()
repost_sl_entries(doc)
repost_gl_entries(doc)
diff --git a/erpnext/stock/doctype/shipment/test_shipment.py b/erpnext/stock/doctype/shipment/test_shipment.py
index 705b265..afe8218 100644
--- a/erpnext/stock/doctype/shipment/test_shipment.py
+++ b/erpnext/stock/doctype/shipment/test_shipment.py
@@ -39,9 +39,9 @@
"description": 'Test delivery note for shipment',
"qty": 5,
"uom": 'Nos',
- "warehouse": 'Stores - SC',
+ "warehouse": 'Stores - _TC',
"rate": item.standard_rate,
- "cost_center": 'Main - SC'
+ "cost_center": 'Main - _TC'
}
)
delivery_note.insert()
@@ -127,13 +127,7 @@
return create_shipment_address(address_title, company_name, 80331)
def get_shipment_company():
- company_name = 'Shipment Company'
- abbr = 'SC'
- companies = frappe.get_all("Company", fields=["name"], filters = {"company_name": company_name})
- if len(companies):
- return companies[0]
- else:
- return create_shipment_company(company_name, abbr)
+ return frappe.get_doc("Company", "_Test Company")
def get_shipment_item(company_name):
item_name = 'Testing Shipment item'
@@ -182,17 +176,6 @@
customer.insert()
return customer
-
-def create_shipment_company(company_name, abbr):
- company = frappe.new_doc("Company")
- company.company_name = company_name
- company.abbr = abbr
- company.default_currency = 'EUR'
- company.country = 'Germany'
- company.enable_perpetual_inventory = 0
- company.insert()
- return company
-
def create_shipment_customer(customer_name):
customer = frappe.new_doc("Customer")
customer.customer_name = customer_name
@@ -211,12 +194,12 @@
stock.posting_date = posting_date.strftime("%Y-%m-%d")
stock.append('items',
{
- "t_warehouse": 'Stores - SC',
+ "t_warehouse": 'Stores - _TC',
"item_code": item.name,
"qty": 5,
"uom": 'Nos',
"basic_rate": item.standard_rate,
- "cost_center": 'Main - SC'
+ "cost_center": 'Main - _TC'
}
)
stock.insert()
@@ -233,7 +216,7 @@
item.append('item_defaults',
{
"company": company_name,
- "default_warehouse": 'Stores - SC'
+ "default_warehouse": 'Stores - _TC'
}
)
item.insert()
diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js
deleted file mode 100644
index e51c90c..0000000
--- a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_manufacture.js
+++ /dev/null
@@ -1,26 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test manufacture from bom", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make("Stock Entry", [
- { purpose: "Manufacture" },
- { from_bom: 1 },
- { bom_no: "BOM-_Test Item - Non Whole UOM-001" },
- { fg_completed_qty: 2 }
- ]);
- },
- () => cur_frm.save(),
- () => frappe.click_button("Update Rate and Availability"),
- () => {
- assert.ok(cur_frm.doc.items[1] === 0.75, " Finished Item Qty correct");
- assert.ok(cur_frm.doc.items[2] === 0.25, " Process Loss Item Qty correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue.js
deleted file mode 100644
index a87a7fb..0000000
--- a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue.js
+++ /dev/null
@@ -1,30 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test material request", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Stock Entry', [
- {from_warehouse:'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {items: [
- [
- {'item_code': 'Test Product 1'},
- {'qty': 5},
- ]
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => frappe.click_button('Update Rate and Availability'),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- assert.ok(cur_frm.doc.total_outgoing_value==500, " Outgoing Value correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue_with_serialize_item.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue_with_serialize_item.js
deleted file mode 100644
index cae318d..0000000
--- a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_issue_with_serialize_item.js
+++ /dev/null
@@ -1,34 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test material issue", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Stock Entry', [
- {from_warehouse:'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {items: [
- [
- {'item_code': 'Test Product 4'},
- {'qty': 1},
- {'batch_no':'TEST-BATCH-001'},
- {'serial_no':'Test-Product-003'},
- {'basic_rate':100},
- ]
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => frappe.click_button('Close'),
- () => frappe.click_button('Update Rate and Availability'),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- assert.ok(cur_frm.doc.total_outgoing_value==100, " Outgoing Value correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt.js
deleted file mode 100644
index ef0286f..0000000
--- a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt.js
+++ /dev/null
@@ -1,31 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test material request", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Stock Entry', [
- {purpose:'Material Receipt'},
- {to_warehouse:'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {items: [
- [
- {'item_code': 'Test Product 1'},
- {'qty': 5},
- ]
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => frappe.click_button('Update Rate and Availability'),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- assert.ok(cur_frm.doc.total_incoming_value==500, " Incoming Value correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt_for_serialize_item.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt_for_serialize_item.js
deleted file mode 100644
index 54e1ac8..0000000
--- a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_receipt_for_serialize_item.js
+++ /dev/null
@@ -1,34 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test material receipt", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Stock Entry', [
- {purpose:'Material Receipt'},
- {to_warehouse:'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {items: [
- [
- {'item_code': 'Test Product 4'},
- {'qty': 5},
- {'batch_no':'TEST-BATCH-001'},
- {'serial_no':'Test-Product-001\nTest-Product-002\nTest-Product-003\nTest-Product-004\nTest-Product-005'},
- {'basic_rate':100},
- ]
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => frappe.click_button('Update Rate and Availability'),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
- assert.ok(cur_frm.doc.total_incoming_value==500, " Incoming Value correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer.js
deleted file mode 100644
index fac0b4b..0000000
--- a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer.js
+++ /dev/null
@@ -1,33 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test material request", function(assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Stock Entry', [
- {purpose:'Material Transfer'},
- {from_warehouse:'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {to_warehouse:'Work In Progress - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {items: [
- [
- {'item_code': 'Test Product 1'},
- {'qty': 5},
- ]
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => frappe.click_button('Update Rate and Availability'),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- assert.ok(cur_frm.doc.total_outgoing_value==500, " Outgoing Value correct");
- assert.ok(cur_frm.doc.total_incoming_value==500, " Incoming Value correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer_for_manufacture.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer_for_manufacture.js
deleted file mode 100644
index 9f85307..0000000
--- a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_material_transfer_for_manufacture.js
+++ /dev/null
@@ -1,33 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test material Transfer to manufacture", function(assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Stock Entry', [
- {purpose:'Material Transfer for Manufacture'},
- {from_warehouse:'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {to_warehouse:'Work In Progress - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {items: [
- [
- {'item_code': 'Test Product 1'},
- {'qty': 1},
- ]
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => frappe.click_button('Update Rate and Availability'),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- assert.ok(cur_frm.doc.total_outgoing_value==100, " Outgoing Value correct");
- assert.ok(cur_frm.doc.total_incoming_value==100, " Incoming Value correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_repack.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_repack.js
deleted file mode 100644
index 20f119a..0000000
--- a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_repack.js
+++ /dev/null
@@ -1,41 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test repack", function(assert) {
- assert.expect(2);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Stock Entry', [
- {purpose:'Repack'},
- {items: [
- [
- {'item_code': 'Test Product 1'},
- {'qty': 1},
- {'s_warehouse':'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- ],
- [
- {'item_code': 'Test Product 2'},
- {'qty': 1},
- {'s_warehouse':'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- ],
- [
- {'item_code': 'Test Product 3'},
- {'qty': 1},
- {'t_warehouse':'Work In Progress - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- ],
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => frappe.click_button('Update Rate and Availability'),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.total_outgoing_value==250, " Outgoing Value correct");
- assert.ok(cur_frm.doc.total_incoming_value==250, " Incoming Value correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js b/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js
deleted file mode 100644
index 8243426..0000000
--- a/erpnext/stock/doctype/stock_entry/tests/test_stock_entry_for_subcontract.js
+++ /dev/null
@@ -1,33 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test material Transfer to manufacture", function(assert) {
- assert.expect(3);
- let done = assert.async();
- frappe.run_serially([
- () => {
- return frappe.tests.make('Stock Entry', [
- {purpose:'Send to Subcontractor'},
- {from_warehouse:'Work In Progress - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {to_warehouse:'Finished Goods - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
- {items: [
- [
- {'item_code': 'Test Product 1'},
- {'qty': 1},
- ]
- ]},
- ]);
- },
- () => cur_frm.save(),
- () => frappe.click_button('Update Rate and Availability'),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
- assert.ok(cur_frm.doc.total_outgoing_value==100, " Outgoing Value correct");
- assert.ok(cur_frm.doc.total_incoming_value==100, " Incoming Value correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js
deleted file mode 100644
index 666d2c7..0000000
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.js
+++ /dev/null
@@ -1,31 +0,0 @@
-QUnit.module('Stock');
-
-QUnit.test("test Stock Reconciliation", function(assert) {
- assert.expect(1);
- let done = assert.async();
- frappe.run_serially([
- () => frappe.set_route('List', 'Stock Reconciliation'),
- () => frappe.timeout(1),
- () => frappe.click_button('New'),
- () => cur_frm.set_value('company','For Testing'),
- () => frappe.click_button('Items'),
- () => {cur_dialog.set_value('warehouse','Stores - FT'); },
- () => frappe.timeout(0.5),
- () => frappe.click_button('Update'),
- () => {
- cur_frm.doc.items[0].qty = 150;
- cur_frm.refresh_fields('items');},
- () => frappe.timeout(0.5),
- () => cur_frm.set_value('expense_account','Stock Adjustment - FT'),
- () => cur_frm.set_value('cost_center','Main - FT'),
- () => cur_frm.save(),
- () => {
- // get_item_details
- assert.ok(cur_frm.doc.expense_account=='Stock Adjustment - FT', "expense_account correct");
- },
- () => frappe.tests.click_button('Submit'),
- () => frappe.tests.click_button('Yes'),
- () => frappe.timeout(0.3),
- () => done()
- ]);
-});
diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
index 48e339a..c4ddc9e 100644
--- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
@@ -24,11 +24,15 @@
class TestStockReconciliation(ERPNextTestCase):
@classmethod
- def setUpClass(self):
+ def setUpClass(cls):
super().setUpClass()
create_batch_or_serial_no_items()
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
+ def tearDown(self):
+ frappe.flags.dont_execute_stock_reposts = None
+
+
def test_reco_for_fifo(self):
self._test_reco_sle_gle("FIFO")
@@ -392,6 +396,41 @@
repost_exists = bool(frappe.db.exists("Repost Item Valuation", {"voucher_no": sr.name}))
self.assertFalse(repost_exists, msg="Negative stock validation not working on reco cancellation")
+ def test_intermediate_sr_bin_update(self):
+ """Bin should show correct qty even for backdated entries.
+
+ -------------------------------------------
+ | creation | Var | Doc | Qty | balance qty
+ -------------------------------------------
+ | 1 | SR | Reco | 10 | 10 (posting date: today+10)
+ | 3 | SR2 | Reco | 11 | 11 (posting date: today+11)
+ | 2 | DN | DN | 5 | 6 <-- assert in BIN (posting date: today+12)
+ """
+ from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
+
+ # repost will make this test useless, qty should update in realtime without reposts
+ frappe.flags.dont_execute_stock_reposts = True
+ frappe.db.rollback()
+
+ item_code = "Backdated-Reco-Cancellation-Item"
+ warehouse = "_Test Warehouse - _TC"
+ create_item(item_code)
+
+ sr = create_stock_reconciliation(item_code=item_code, warehouse=warehouse, qty=10, rate=100,
+ posting_date=add_days(nowdate(), 10))
+
+ dn = create_delivery_note(item_code=item_code, warehouse=warehouse, qty=5, rate=120,
+ posting_date=add_days(nowdate(), 12))
+ old_bin_qty = frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "actual_qty")
+
+ sr2 = create_stock_reconciliation(item_code=item_code, warehouse=warehouse, qty=11, rate=100,
+ posting_date=add_days(nowdate(), 11))
+ new_bin_qty = frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "actual_qty")
+
+ self.assertEqual(old_bin_qty + 1, new_bin_qty)
+ frappe.db.rollback()
+
+
def test_valid_batch(self):
create_batch_item_with_batch("Testing Batch Item 1", "001")
create_batch_item_with_batch("Testing Batch Item 2", "002")
diff --git a/erpnext/stock/doctype/warehouse/test_warehouse.js b/erpnext/stock/doctype/warehouse/test_warehouse.js
deleted file mode 100644
index 850da1e..0000000
--- a/erpnext/stock/doctype/warehouse/test_warehouse.js
+++ /dev/null
@@ -1,19 +0,0 @@
-QUnit.test("test: warehouse", function (assert) {
- assert.expect(0);
- let done = assert.async();
-
- frappe.run_serially([
- // test warehouse creation
- () => frappe.set_route("List", "Warehouse"),
-
- // Create a Laptop Scrap Warehouse
- () => frappe.tests.make(
- "Warehouse", [
- {warehouse_name: "Laptop Scrap Warehouse"},
- {company: "For Testing"}
- ]
- ),
-
- () => done()
- ]);
-});
diff --git a/erpnext/stock/form_tour/item/item.json b/erpnext/stock/form_tour/item/item.json
index 821e91b..5369366 100644
--- a/erpnext/stock/form_tour/item/item.json
+++ b/erpnext/stock/form_tour/item/item.json
@@ -2,15 +2,17 @@
"creation": "2021-08-24 17:56:40.754909",
"docstatus": 0,
"doctype": "Form Tour",
+ "first_document": 0,
"idx": 0,
+ "include_name_field": 0,
"is_standard": 1,
- "modified": "2021-08-24 18:04:50.928431",
+ "modified": "2021-11-24 17:59:44.559001",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",
"owner": "Administrator",
"reference_doctype": "Item",
- "save_on_complete": 0,
+ "save_on_complete": 1,
"steps": [
{
"description": "Enter code for Asset Item",
@@ -37,13 +39,26 @@
"title": "Asset Item Name"
},
{
+ "description": "Select an Item Group",
+ "field": "",
+ "fieldname": "item_group",
+ "fieldtype": "Link",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Item Group",
+ "parent_field": "",
+ "position": "Right",
+ "title": "Item Group"
+ },
+ {
"description": "Check this field to make this an Asset Item",
"field": "",
"fieldname": "is_fixed_asset",
"fieldtype": "Check",
- "has_next_condition": 0,
+ "has_next_condition": 1,
"is_table_field": 0,
"label": "Is Fixed Asset",
+ "next_step_condition": "eval:doc.is_fixed_asset",
"parent_field": "",
"position": "Bottom",
"title": "Is this a Fixed Asset?"
@@ -53,9 +68,10 @@
"field": "",
"fieldname": "auto_create_assets",
"fieldtype": "Check",
- "has_next_condition": 0,
+ "has_next_condition": 1,
"is_table_field": 0,
"label": "Auto Create Assets on Purchase",
+ "next_step_condition": "eval:doc.auto_create_assets",
"parent_field": "",
"position": "Bottom",
"title": "Auto Create Asset on Purchase"
@@ -69,7 +85,7 @@
"is_table_field": 0,
"label": "Asset Category",
"parent_field": "",
- "position": "Bottom",
+ "position": "Left",
"title": "Asset Category"
},
{
@@ -81,9 +97,9 @@
"is_table_field": 0,
"label": "Asset Naming Series",
"parent_field": "",
- "position": "Bottom",
+ "position": "Left",
"title": "Asset Naming Series"
}
],
"title": "Item"
-}
+}
\ No newline at end of file
diff --git a/erpnext/stock/form_tour/item_general/item_general.json b/erpnext/stock/form_tour/item_general/item_general.json
new file mode 100644
index 0000000..b468d27
--- /dev/null
+++ b/erpnext/stock/form_tour/item_general/item_general.json
@@ -0,0 +1,79 @@
+{
+ "creation": "2021-12-02 10:37:55.433087",
+ "docstatus": 0,
+ "doctype": "Form Tour",
+ "first_document": 0,
+ "idx": 0,
+ "include_name_field": 0,
+ "is_standard": 1,
+ "modified": "2021-12-02 10:37:55.433087",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Item General",
+ "owner": "Administrator",
+ "reference_doctype": "Item",
+ "save_on_complete": 1,
+ "steps": [
+ {
+ "description": "Enter code for the Item",
+ "field": "",
+ "fieldname": "item_code",
+ "fieldtype": "Data",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Item Code",
+ "parent_field": "",
+ "position": "Right",
+ "title": "Item Code"
+ },
+ {
+ "description": "Enter name for the Item",
+ "field": "",
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Item Name",
+ "parent_field": "",
+ "position": "Right",
+ "title": "Item Name"
+ },
+ {
+ "description": "Select an Item Group",
+ "field": "",
+ "fieldname": "item_group",
+ "fieldtype": "Link",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Item Group",
+ "parent_field": "",
+ "position": "Right",
+ "title": "Item Group"
+ },
+ {
+ "description": "This is the default measuring unit that you will use for your product. It could be Nos, Kgs, Meters, etc.",
+ "field": "",
+ "fieldname": "stock_uom",
+ "fieldtype": "Link",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Default Unit of Measure",
+ "parent_field": "",
+ "position": "Right",
+ "title": "Default Unit of Measurement"
+ },
+ {
+ "description": "When creating an Item, entering a value for this field will automatically create an Item Price at the backend. Entering a value after the Item has been saved will not work. In this case, the Item Price is created from any transactions with the Item.",
+ "field": "",
+ "fieldname": "standard_rate",
+ "fieldtype": "Currency",
+ "has_next_condition": 0,
+ "is_table_field": 0,
+ "label": "Standard Selling Rate",
+ "parent_field": "",
+ "position": "Left",
+ "title": "Standard Selling Rate"
+ }
+ ],
+ "title": "Item General"
+}
\ No newline at end of file
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index c0b89fd..3c7b26b 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -167,7 +167,7 @@
sle.company, sle.voucher_type, sle.qty_after_transaction, sle.stock_value_difference,
sle.item_code as name, sle.voucher_no, sle.stock_value, sle.batch_no
from
- `tabStock Ledger Entry` sle force index (posting_sort_index)
+ `tabStock Ledger Entry` sle
where sle.docstatus < 2 %s %s
and is_cancelled = 0
order by sle.posting_date, sle.posting_time, sle.creation, sle.actual_qty""" % #nosec
diff --git a/erpnext/stock/report/stock_ledger_invariant_check/__init__.py b/erpnext/stock/report/stock_ledger_invariant_check/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/report/stock_ledger_invariant_check/__init__.py
diff --git a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js
new file mode 100644
index 0000000..c484516
--- /dev/null
+++ b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.js
@@ -0,0 +1,43 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+const DIFFERNCE_FIELD_NAMES = [
+ "difference_in_qty",
+ "fifo_qty_diff",
+ "fifo_value_diff",
+ "fifo_valuation_diff",
+ "valuation_diff",
+ "fifo_difference_diff"
+];
+
+frappe.query_reports["Stock Ledger Invariant Check"] = {
+ "filters": [
+ {
+ "fieldname": "item_code",
+ "fieldtype": "Link",
+ "label": "Item",
+ "mandatory": 1,
+ "options": "Item",
+ get_query: function() {
+ return {
+ filters: {is_stock_item: 1, has_serial_no: 0}
+ }
+ }
+ },
+ {
+ "fieldname": "warehouse",
+ "fieldtype": "Link",
+ "label": "Warehouse",
+ "mandatory": 1,
+ "options": "Warehouse",
+ }
+ ],
+ formatter (value, row, column, data, default_formatter) {
+ value = default_formatter(value, row, column, data);
+ if (DIFFERNCE_FIELD_NAMES.includes(column.fieldname) && Math.abs(data[column.fieldname]) > 0.001) {
+ value = "<span style='color:red'>" + value + "</span>";
+ }
+ return value;
+ },
+};
diff --git a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.json b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.json
new file mode 100644
index 0000000..d28fe0f
--- /dev/null
+++ b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.json
@@ -0,0 +1,26 @@
+{
+ "add_total_row": 0,
+ "columns": [],
+ "creation": "2021-12-16 06:31:23.290916",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2021-12-16 09:55:58.341764",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Stock Ledger Invariant Check",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Stock Ledger Entry",
+ "report_name": "Stock Ledger Invariant Check",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py
new file mode 100644
index 0000000..ca47a1e
--- /dev/null
+++ b/erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py
@@ -0,0 +1,236 @@
+# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
+# License: GNU GPL v3. See LICENSE
+
+import json
+
+import frappe
+
+SLE_FIELDS = (
+ "name",
+ "posting_date",
+ "posting_time",
+ "creation",
+ "voucher_type",
+ "voucher_no",
+ "actual_qty",
+ "qty_after_transaction",
+ "incoming_rate",
+ "outgoing_rate",
+ "stock_queue",
+ "batch_no",
+ "stock_value",
+ "stock_value_difference",
+ "valuation_rate",
+)
+
+
+def execute(filters=None):
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data
+
+
+def get_data(filters):
+ sles = get_stock_ledger_entries(filters)
+ return add_invariant_check_fields(sles)
+
+
+def get_stock_ledger_entries(filters):
+ return frappe.get_all(
+ "Stock Ledger Entry",
+ fields=SLE_FIELDS,
+ filters={
+ "item_code": filters.item_code,
+ "warehouse": filters.warehouse,
+ "is_cancelled": 0
+ },
+ order_by="timestamp(posting_date, posting_time), creation",
+ )
+
+
+def add_invariant_check_fields(sles):
+ balance_qty = 0.0
+ for idx, sle in enumerate(sles):
+ queue = json.loads(sle.stock_queue)
+
+ fifo_qty = 0.0
+ fifo_value = 0.0
+ for qty, rate in queue:
+ fifo_qty += qty
+ fifo_value += qty * rate
+
+ balance_qty += sle.actual_qty
+ if sle.voucher_type == "Stock Reconciliation" and not sle.batch_no:
+ balance_qty = sle.qty_after_transaction
+
+ sle.fifo_queue_qty = fifo_qty
+ sle.fifo_stock_value = fifo_value
+ sle.fifo_valuation_rate = fifo_value / fifo_qty if fifo_qty else None
+ sle.balance_value_by_qty = (
+ sle.stock_value / sle.qty_after_transaction if sle.qty_after_transaction else None
+ )
+ sle.expected_qty_after_transaction = balance_qty
+
+ # set difference fields
+ sle.difference_in_qty = sle.qty_after_transaction - sle.expected_qty_after_transaction
+ sle.fifo_qty_diff = sle.qty_after_transaction - fifo_qty
+ sle.fifo_value_diff = sle.stock_value - fifo_value
+ sle.fifo_valuation_diff = (
+ sle.valuation_rate - sle.fifo_valuation_rate if sle.fifo_valuation_rate else None
+ )
+ sle.valuation_diff = (
+ sle.valuation_rate - sle.balance_value_by_qty if sle.balance_value_by_qty else None
+ )
+
+ if idx > 0:
+ sle.fifo_stock_diff = sle.fifo_stock_value - sles[idx - 1].fifo_stock_value
+ sle.fifo_difference_diff = sle.fifo_stock_diff - sle.stock_value_difference
+
+ return sles
+
+
+def get_columns():
+ return [
+ {
+ "fieldname": "name",
+ "fieldtype": "Link",
+ "label": "Stock Ledger Entry",
+ "options": "Stock Ledger Entry",
+ },
+ {
+ "fieldname": "posting_date",
+ "fieldtype": "Date",
+ "label": "Posting Date",
+ },
+ {
+ "fieldname": "posting_time",
+ "fieldtype": "Time",
+ "label": "Posting Time",
+ },
+ {
+ "fieldname": "creation",
+ "fieldtype": "Datetime",
+ "label": "Creation",
+ },
+ {
+ "fieldname": "voucher_type",
+ "fieldtype": "Link",
+ "label": "Voucher Type",
+ "options": "DocType",
+ },
+ {
+ "fieldname": "voucher_no",
+ "fieldtype": "Dynamic Link",
+ "label": "Voucher No",
+ "options": "voucher_type",
+ },
+ {
+ "fieldname": "batch_no",
+ "fieldtype": "Link",
+ "label": "Batch",
+ "options": "Batch",
+ },
+ {
+ "fieldname": "actual_qty",
+ "fieldtype": "Float",
+ "label": "Qty Change",
+ },
+ {
+ "fieldname": "incoming_rate",
+ "fieldtype": "Float",
+ "label": "Incoming Rate",
+ },
+ {
+ "fieldname": "outgoing_rate",
+ "fieldtype": "Float",
+ "label": "Outgoing Rate",
+ },
+ {
+ "fieldname": "qty_after_transaction",
+ "fieldtype": "Float",
+ "label": "(A) Qty After Transaction",
+ },
+ {
+ "fieldname": "expected_qty_after_transaction",
+ "fieldtype": "Float",
+ "label": "(B) Expected Qty After Transaction",
+ },
+ {
+ "fieldname": "difference_in_qty",
+ "fieldtype": "Float",
+ "label": "A - B",
+ },
+ {
+ "fieldname": "stock_queue",
+ "fieldtype": "Data",
+ "label": "FIFO Queue",
+ },
+
+ {
+ "fieldname": "fifo_queue_qty",
+ "fieldtype": "Float",
+ "label": "(C) Total qty in queue",
+ },
+ {
+ "fieldname": "fifo_qty_diff",
+ "fieldtype": "Float",
+ "label": "A - C",
+ },
+ {
+ "fieldname": "stock_value",
+ "fieldtype": "Float",
+ "label": "(D) Balance Stock Value",
+ },
+ {
+ "fieldname": "fifo_stock_value",
+ "fieldtype": "Float",
+ "label": "(E) Balance Stock Value in Queue",
+ },
+ {
+ "fieldname": "fifo_value_diff",
+ "fieldtype": "Float",
+ "label": "D - E",
+ },
+
+ {
+ "fieldname": "stock_value_difference",
+ "fieldtype": "Float",
+ "label": "(F) Stock Value Difference",
+ },
+ {
+ "fieldname": "fifo_stock_diff",
+ "fieldtype": "Float",
+ "label": "(G) Stock Value difference (FIFO queue)",
+ },
+ {
+ "fieldname": "fifo_difference_diff",
+ "fieldtype": "Float",
+ "label": "F - G",
+ },
+ {
+ "fieldname": "valuation_rate",
+ "fieldtype": "Float",
+ "label": "(H) Valuation Rate",
+ },
+ {
+ "fieldname": "fifo_valuation_rate",
+ "fieldtype": "Float",
+ "label": "(I) Valuation Rate as per FIFO",
+ },
+
+ {
+ "fieldname": "fifo_valuation_diff",
+ "fieldtype": "Float",
+ "label": "H - I",
+ },
+ {
+ "fieldname": "balance_value_by_qty",
+ "fieldtype": "Float",
+ "label": "(J) Valuation = Value (D) ÷ Qty (A)",
+ },
+ {
+ "fieldname": "valuation_diff",
+ "fieldtype": "Float",
+ "label": "H - J",
+ },
+ ]
diff --git a/erpnext/stock/report/test_reports.py b/erpnext/stock/report/test_reports.py
index d7fb5b2..1dcf863 100644
--- a/erpnext/stock/report/test_reports.py
+++ b/erpnext/stock/report/test_reports.py
@@ -41,6 +41,12 @@
("Total Stock Summary", {"group_by": "warehouse",}),
("Batch Item Expiry Status", {}),
("Stock Ageing", {"range1": 30, "range2": 60, "range3": 90, "_optional": True}),
+ ("Stock Ledger Invariant Check",
+ {
+ "warehouse": "_Test Warehouse - _TC",
+ "item": "_Test Item"
+ }
+ ),
]
OPTIONAL_FILTERS = {
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index e95c0fc..107bb23 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -16,6 +16,7 @@
get_or_make_bin,
get_valuation_method,
)
+from erpnext.stock.valuation import FIFOValuation
class NegativeStockError(frappe.ValidationError): pass
@@ -64,8 +65,8 @@
is_stock_item = frappe.get_cached_value('Item', args.get("item_code"), 'is_stock_item')
if is_stock_item:
bin_name = get_or_make_bin(args.get("item_code"), args.get("warehouse"))
- update_bin_qty(bin_name, args)
repost_current_voucher(args, allow_negative_stock, via_landed_cost_voucher)
+ update_bin_qty(bin_name, args)
else:
frappe.msgprint(_("Item {0} ignored since it is not a stock item").format(args.get("item_code")))
@@ -456,9 +457,8 @@
self.wh_data.qty_after_transaction += flt(sle.actual_qty)
self.wh_data.stock_value = flt(self.wh_data.qty_after_transaction) * flt(self.wh_data.valuation_rate)
else:
- self.get_fifo_values(sle)
+ self.update_fifo_values(sle)
self.wh_data.qty_after_transaction += flt(sle.actual_qty)
- self.wh_data.stock_value = sum(flt(batch[0]) * flt(batch[1]) for batch in self.wh_data.stock_queue)
# rounding as per precision
self.wh_data.stock_value = flt(self.wh_data.stock_value, self.precision)
@@ -696,87 +696,39 @@
sle.voucher_type, sle.voucher_no, self.allow_zero_rate,
currency=erpnext.get_company_currency(sle.company), company=sle.company)
- def get_fifo_values(self, sle):
+ def update_fifo_values(self, sle):
incoming_rate = flt(sle.incoming_rate)
actual_qty = flt(sle.actual_qty)
outgoing_rate = flt(sle.outgoing_rate)
+ fifo_queue = FIFOValuation(self.wh_data.stock_queue)
if actual_qty > 0:
- if not self.wh_data.stock_queue:
- self.wh_data.stock_queue.append([0, 0])
-
- # last row has the same rate, just updated the qty
- if self.wh_data.stock_queue[-1][1]==incoming_rate:
- self.wh_data.stock_queue[-1][0] += actual_qty
- else:
- # Item has a positive balance qty, add new entry
- if self.wh_data.stock_queue[-1][0] > 0:
- self.wh_data.stock_queue.append([actual_qty, incoming_rate])
- else: # negative balance qty
- qty = self.wh_data.stock_queue[-1][0] + actual_qty
- if qty > 0: # new balance qty is positive
- self.wh_data.stock_queue[-1] = [qty, incoming_rate]
- else: # new balance qty is still negative, maintain same rate
- self.wh_data.stock_queue[-1][0] = qty
+ fifo_queue.add_stock(qty=actual_qty, rate=incoming_rate)
else:
- qty_to_pop = abs(actual_qty)
- while qty_to_pop:
- if not self.wh_data.stock_queue:
- # Get valuation rate from last sle if exists or from valuation rate field in item master
- allow_zero_valuation_rate = self.check_if_allow_zero_valuation_rate(sle.voucher_type, sle.voucher_detail_no)
- if not allow_zero_valuation_rate:
- _rate = get_valuation_rate(sle.item_code, sle.warehouse,
- sle.voucher_type, sle.voucher_no, self.allow_zero_rate,
- currency=erpnext.get_company_currency(sle.company), company=sle.company)
- else:
- _rate = 0
-
- self.wh_data.stock_queue.append([0, _rate])
-
- index = None
- if outgoing_rate > 0:
- # Find the entry where rate matched with outgoing rate
- for i, v in enumerate(self.wh_data.stock_queue):
- if v[1] == outgoing_rate:
- index = i
- break
-
- # If no entry found with outgoing rate, collapse stack
- if index is None: # nosemgrep
- new_stock_value = sum(d[0]*d[1] for d in self.wh_data.stock_queue) - qty_to_pop*outgoing_rate
- new_stock_qty = sum(d[0] for d in self.wh_data.stock_queue) - qty_to_pop
- self.wh_data.stock_queue = [[new_stock_qty, new_stock_value/new_stock_qty if new_stock_qty > 0 else outgoing_rate]]
- break
+ def rate_generator() -> float:
+ allow_zero_valuation_rate = self.check_if_allow_zero_valuation_rate(sle.voucher_type, sle.voucher_detail_no)
+ if not allow_zero_valuation_rate:
+ return get_valuation_rate(sle.item_code, sle.warehouse,
+ sle.voucher_type, sle.voucher_no, self.allow_zero_rate,
+ currency=erpnext.get_company_currency(sle.company), company=sle.company)
else:
- index = 0
+ return 0.0
- # select first batch or the batch with same rate
- batch = self.wh_data.stock_queue[index]
- if qty_to_pop >= batch[0]:
- # consume current batch
- qty_to_pop = _round_off_if_near_zero(qty_to_pop - batch[0])
- self.wh_data.stock_queue.pop(index)
- if not self.wh_data.stock_queue and qty_to_pop:
- # stock finished, qty still remains to be withdrawn
- # negative stock, keep in as a negative batch
- self.wh_data.stock_queue.append([-qty_to_pop, outgoing_rate or batch[1]])
- break
+ fifo_queue.remove_stock(qty=abs(actual_qty), outgoing_rate=outgoing_rate, rate_generator=rate_generator)
- else:
- # qty found in current batch
- # consume it and exit
- batch[0] = batch[0] - qty_to_pop
- qty_to_pop = 0
+ stock_qty, stock_value = fifo_queue.get_total_stock_and_value()
- stock_value = _round_off_if_near_zero(sum(flt(batch[0]) * flt(batch[1]) for batch in self.wh_data.stock_queue))
- stock_qty = _round_off_if_near_zero(sum(flt(batch[0]) for batch in self.wh_data.stock_queue))
-
+ self.wh_data.stock_queue = fifo_queue.get_state()
+ self.wh_data.stock_value = stock_value
if stock_qty:
- self.wh_data.valuation_rate = stock_value / flt(stock_qty)
+ self.wh_data.valuation_rate = stock_value / stock_qty
+
if not self.wh_data.stock_queue:
self.wh_data.stock_queue.append([0, sle.incoming_rate or sle.outgoing_rate or self.wh_data.valuation_rate])
+
+
def check_if_allow_zero_valuation_rate(self, voucher_type, voucher_detail_no):
ref_item_dt = ""
@@ -1158,13 +1110,3 @@
and timestamp(posting_date, posting_time) >= timestamp(%(posting_date)s, %(posting_time)s)
limit 1
""", args, as_dict=1)
-
-
-def _round_off_if_near_zero(number: float, precision: int = 6) -> float:
- """ Rounds off the number to zero only if number is close to zero for decimal
- specified in precision. Precision defaults to 6.
- """
- if flt(number) < (1.0 / (10**precision)):
- return 0
-
- return flt(number)
diff --git a/erpnext/stock/tests/test_valuation.py b/erpnext/stock/tests/test_valuation.py
new file mode 100644
index 0000000..85788ba
--- /dev/null
+++ b/erpnext/stock/tests/test_valuation.py
@@ -0,0 +1,166 @@
+import unittest
+
+from hypothesis import given
+from hypothesis import strategies as st
+
+from erpnext.stock.valuation import FIFOValuation, _round_off_if_near_zero
+
+qty_gen = st.floats(min_value=-1e6, max_value=1e6)
+value_gen = st.floats(min_value=1, max_value=1e6)
+stock_queue_generator = st.lists(st.tuples(qty_gen, value_gen), min_size=10)
+
+
+class TestFifoValuation(unittest.TestCase):
+
+ def setUp(self):
+ self.queue = FIFOValuation([])
+
+ def tearDown(self):
+ qty, value = self.queue.get_total_stock_and_value()
+ self.assertTotalQty(qty)
+ self.assertTotalValue(value)
+
+ def assertTotalQty(self, qty):
+ self.assertAlmostEqual(sum(q for q, _ in self.queue), qty, msg=f"queue: {self.queue}", places=4)
+
+ def assertTotalValue(self, value):
+ self.assertAlmostEqual(sum(q * r for q, r in self.queue), value, msg=f"queue: {self.queue}", places=2)
+
+ def test_simple_addition(self):
+ self.queue.add_stock(1, 10)
+ self.assertTotalQty(1)
+
+ def test_simple_removal(self):
+ self.queue.add_stock(1, 10)
+ self.queue.remove_stock(1)
+ self.assertTotalQty(0)
+
+ def test_merge_new_stock(self):
+ self.queue.add_stock(1, 10)
+ self.queue.add_stock(1, 10)
+ self.assertEqual(self.queue, [[2, 10]])
+
+ def test_adding_negative_stock_keeps_rate(self):
+ self.queue = FIFOValuation([[-5.0, 100]])
+ self.queue.add_stock(1, 10)
+ self.assertEqual(self.queue, [[-4, 100]])
+
+ def test_adding_negative_stock_updates_rate(self):
+ self.queue = FIFOValuation([[-5.0, 100]])
+ self.queue.add_stock(6, 10)
+ self.assertEqual(self.queue, [[1, 10]])
+
+
+ def test_negative_stock(self):
+ self.queue.remove_stock(1, 5)
+ self.assertEqual(self.queue, [[-1, 5]])
+
+ # XXX
+ self.queue.remove_stock(1, 10)
+ self.assertTotalQty(-2)
+
+ self.queue.add_stock(2, 10)
+ self.assertTotalQty(0)
+ self.assertTotalValue(0)
+
+ def test_removing_specified_rate(self):
+ self.queue.add_stock(1, 10)
+ self.queue.add_stock(1, 20)
+
+ self.queue.remove_stock(1, 20)
+ self.assertEqual(self.queue, [[1, 10]])
+
+
+ def test_remove_multiple_bins(self):
+ self.queue.add_stock(1, 10)
+ self.queue.add_stock(2, 20)
+ self.queue.add_stock(1, 20)
+ self.queue.add_stock(5, 20)
+
+ self.queue.remove_stock(4)
+ self.assertEqual(self.queue, [[5, 20]])
+
+
+ def test_remove_multiple_bins_with_rate(self):
+ self.queue.add_stock(1, 10)
+ self.queue.add_stock(2, 20)
+ self.queue.add_stock(1, 20)
+ self.queue.add_stock(5, 20)
+
+ self.queue.remove_stock(3, 20)
+ self.assertEqual(self.queue, [[1, 10], [5, 20]])
+
+ def test_collapsing_of_queue(self):
+ self.queue.add_stock(1, 1)
+ self.queue.add_stock(1, 2)
+ self.queue.add_stock(1, 3)
+ self.queue.add_stock(1, 4)
+
+ self.assertTotalValue(10)
+
+ self.queue.remove_stock(3, 1)
+ # XXX
+ self.assertEqual(self.queue, [[1, 7]])
+
+ def test_rounding_off(self):
+ self.queue.add_stock(1.0, 1.0)
+ self.queue.remove_stock(1.0 - 1e-9)
+ self.assertTotalQty(0)
+
+ def test_rounding_off_near_zero(self):
+ self.assertEqual(_round_off_if_near_zero(0), 0)
+ self.assertEqual(_round_off_if_near_zero(1), 1)
+ self.assertEqual(_round_off_if_near_zero(-1), -1)
+ self.assertEqual(_round_off_if_near_zero(-1e-8), 0)
+ self.assertEqual(_round_off_if_near_zero(1e-8), 0)
+
+ def test_totals(self):
+ self.queue.add_stock(1, 10)
+ self.queue.add_stock(2, 13)
+ self.queue.add_stock(1, 17)
+ self.queue.remove_stock(1)
+ self.queue.remove_stock(1)
+ self.queue.remove_stock(1)
+ self.queue.add_stock(5, 17)
+ self.queue.add_stock(8, 11)
+
+ @given(stock_queue_generator)
+ def test_fifo_qty_hypothesis(self, stock_queue):
+ self.queue = FIFOValuation([])
+ total_qty = 0
+
+ for qty, rate in stock_queue:
+ if qty == 0:
+ continue
+ if qty > 0:
+ self.queue.add_stock(qty, rate)
+ total_qty += qty
+ else:
+ qty = abs(qty)
+ consumed = self.queue.remove_stock(qty)
+ self.assertAlmostEqual(qty, sum(q for q, _ in consumed), msg=f"incorrect consumption {consumed}")
+ total_qty -= qty
+ self.assertTotalQty(total_qty)
+
+ @given(stock_queue_generator)
+ def test_fifo_qty_value_nonneg_hypothesis(self, stock_queue):
+ self.queue = FIFOValuation([])
+ total_qty = 0.0
+ total_value = 0.0
+
+ for qty, rate in stock_queue:
+ # don't allow negative stock
+ if qty == 0 or total_qty + qty < 0 or abs(qty) < 0.1:
+ continue
+ if qty > 0:
+ self.queue.add_stock(qty, rate)
+ total_qty += qty
+ total_value += qty * rate
+ else:
+ qty = abs(qty)
+ consumed = self.queue.remove_stock(qty)
+ self.assertAlmostEqual(qty, sum(q for q, _ in consumed), msg=f"incorrect consumption {consumed}")
+ total_qty -= qty
+ total_value -= sum(q * r for q, r in consumed)
+ self.assertTotalQty(total_qty)
+ self.assertTotalValue(total_value)
diff --git a/erpnext/stock/valuation.py b/erpnext/stock/valuation.py
new file mode 100644
index 0000000..45c5083
--- /dev/null
+++ b/erpnext/stock/valuation.py
@@ -0,0 +1,146 @@
+from typing import Callable, List, NewType, Optional, Tuple
+
+from frappe.utils import flt
+
+FifoBin = NewType("FifoBin", List[float])
+
+# Indexes of values inside FIFO bin 2-tuple
+QTY = 0
+RATE = 1
+
+
+class FIFOValuation:
+ """Valuation method where a queue of all the incoming stock is maintained.
+
+ New stock is added at end of the queue.
+ Qty consumption happens on First In First Out basis.
+
+ Queue is implemented using "bins" of [qty, rate].
+
+ ref: https://en.wikipedia.org/wiki/FIFO_and_LIFO_accounting
+ """
+
+ # specifying the attributes to save resources
+ # ref: https://docs.python.org/3/reference/datamodel.html#slots
+ __slots__ = ["queue",]
+
+ def __init__(self, state: Optional[List[FifoBin]]):
+ self.queue: List[FifoBin] = state if state is not None else []
+
+ def __repr__(self):
+ return str(self.queue)
+
+ def __iter__(self):
+ return iter(self.queue)
+
+ def __eq__(self, other):
+ if isinstance(other, list):
+ return self.queue == other
+ return self.queue == other.queue
+
+ def get_state(self) -> List[FifoBin]:
+ """Get current state of queue."""
+ return self.queue
+
+ def get_total_stock_and_value(self) -> Tuple[float, float]:
+ total_qty = 0.0
+ total_value = 0.0
+
+ for qty, rate in self.queue:
+ total_qty += flt(qty)
+ total_value += flt(qty) * flt(rate)
+
+ return _round_off_if_near_zero(total_qty), _round_off_if_near_zero(total_value)
+
+ def add_stock(self, qty: float, rate: float) -> None:
+ """Update fifo queue with new stock.
+
+ args:
+ qty: new quantity to add
+ rate: incoming rate of new quantity"""
+
+ if not len(self.queue):
+ self.queue.append([0, 0])
+
+ # last row has the same rate, merge new bin.
+ if self.queue[-1][RATE] == rate:
+ self.queue[-1][QTY] += qty
+ else:
+ # Item has a positive balance qty, add new entry
+ if self.queue[-1][QTY] > 0:
+ self.queue.append([qty, rate])
+ else: # negative balance qty
+ qty = self.queue[-1][QTY] + qty
+ if qty > 0: # new balance qty is positive
+ self.queue[-1] = [qty, rate]
+ else: # new balance qty is still negative, maintain same rate
+ self.queue[-1][QTY] = qty
+
+ def remove_stock(
+ self, qty: float, outgoing_rate: float = 0.0, rate_generator: Callable[[], float] = None
+ ) -> List[FifoBin]:
+ """Remove stock from the queue and return popped bins.
+
+ args:
+ qty: quantity to remove
+ rate: outgoing rate
+ rate_generator: function to be called if queue is not found and rate is required.
+ """
+ if not rate_generator:
+ rate_generator = lambda : 0.0 # noqa
+
+ consumed_bins = []
+ while qty:
+ if not len(self.queue):
+ # rely on rate generator.
+ self.queue.append([0, rate_generator()])
+
+ index = None
+ if outgoing_rate > 0:
+ # Find the entry where rate matched with outgoing rate
+ for idx, fifo_bin in enumerate(self.queue):
+ if fifo_bin[RATE] == outgoing_rate:
+ index = idx
+ break
+
+ # If no entry found with outgoing rate, collapse queue
+ if index is None: # nosemgrep
+ new_stock_value = sum(d[QTY] * d[RATE] for d in self.queue) - qty * outgoing_rate
+ new_stock_qty = sum(d[QTY] for d in self.queue) - qty
+ self.queue = [[new_stock_qty, new_stock_value / new_stock_qty if new_stock_qty > 0 else outgoing_rate]]
+ consumed_bins.append([qty, outgoing_rate])
+ break
+ else:
+ index = 0
+
+ # select first bin or the bin with same rate
+ fifo_bin = self.queue[index]
+ if qty >= fifo_bin[QTY]:
+ # consume current bin
+ qty = _round_off_if_near_zero(qty - fifo_bin[QTY])
+ to_consume = self.queue.pop(index)
+ consumed_bins.append(list(to_consume))
+
+ if not self.queue and qty:
+ # stock finished, qty still remains to be withdrawn
+ # negative stock, keep in as a negative bin
+ self.queue.append([-qty, outgoing_rate or fifo_bin[RATE]])
+ consumed_bins.append([qty, outgoing_rate or fifo_bin[RATE]])
+ break
+ else:
+ # qty found in current bin consume it and exit
+ fifo_bin[QTY] = _round_off_if_near_zero(fifo_bin[QTY] - qty)
+ consumed_bins.append([qty, fifo_bin[RATE]])
+ qty = 0
+
+ return consumed_bins
+
+
+def _round_off_if_near_zero(number: float, precision: int = 7) -> float:
+ """Rounds off the number to zero only if number is close to zero for decimal
+ specified in precision. Precision defaults to 7.
+ """
+ if abs(0.0 - flt(number)) < (1.0 / (10 ** precision)):
+ return 0.0
+
+ return flt(number)
diff --git a/erpnext/tests/test_init.py b/erpnext/tests/test_init.py
index 36a9bf5..6184972 100644
--- a/erpnext/tests/test_init.py
+++ b/erpnext/tests/test_init.py
@@ -8,13 +8,8 @@
class TestInit(unittest.TestCase):
def test_encode_company_abbr(self):
- company = frappe.new_doc("Company")
- company.company_name = "New from Existing Company For Test"
- company.abbr = "NFECT"
- company.default_currency = "INR"
- company.save()
- abbr = company.abbr
+ abbr = "NFECT"
names = [
"Warehouse Name", "ERPNext Foundation India", "Gold - Member - {a}".format(a=abbr),
@@ -32,7 +27,7 @@
]
for i in range(len(names)):
- enc_name = encode_company_abbr(names[i], company.name)
+ enc_name = encode_company_abbr(names[i], abbr=abbr)
self.assertTrue(
enc_name == expected_names[i],
"{enc} is not same as {exp}".format(enc=enc_name, exp=expected_names[i])