Compare commits

..

23 Commits

Author SHA1 Message Date
Nabin Hait
4702cc0368 Merge branch 'hotfix' 2018-01-05 13:16:59 +05:30
Nabin Hait
c98cfbdab4 bumped to version 10.0.6 2018-01-05 13:46:59 +06:00
Nabin Hait
28d0230e56 Multiple small fixes 2018-01-05 13:14:25 +05:30
Saurabh
eac2e369cf [fix] setup alias for ifnull condition (#12327) 2018-01-05 12:48:08 +05:30
Manas Solanki
a521efc990 fix for the non stock items for the shopping cart (#12294) 2018-01-05 12:47:20 +05:30
Manas Solanki
171157f1b3 Fix + Enhancement in Program Enrollment Tool (#12291)
* Fix + Enhancement in Program Enrollment Tool

* updated the docs
2018-01-05 12:42:39 +05:30
rohitwaghchaure
bc2c83ee3c Companywise default tax template (#12290)
* Companywise default tax template

* Fix test cases
2018-01-05 12:42:02 +05:30
rohitwaghchaure
3f784a7a49 [minor] POS profile mandatory, to set as default (#12307) 2018-01-05 12:26:33 +05:30
rohitwaghchaure
1f39feb12f [Fix] PO -> PI non default taxes not fetched (#12313) 2018-01-05 12:25:45 +05:30
rohitwaghchaure
c5c6f82623 [Hotfix] Tax rate not showing in the report (#12324) 2018-01-05 12:16:16 +05:30
Nabin Hait
42688f0636 Minor fix 2018-01-04 18:12:21 +05:30
Nabin Hait
941d0af13a Fixed organization lead error 2018-01-03 14:12:56 +05:30
Nabin Hait
76625b359e Removed naming series from set_only_once in pos profile 2018-01-03 14:03:53 +05:30
Saurabh
e9b37abfca Merge branch 'hotfix' 2018-01-02 12:09:25 +05:30
Saurabh
abf5fa6bbb bumped to version 10.0.5 2018-01-02 12:39:25 +06:00
tundebabzy
650a1eeede recalculate terms when document date changed (#12288)
* recalculate terms when document date changed

* clean up
2018-01-02 12:02:30 +05:30
Nabin Hait
96b264b314 Minor fixes 2018-01-02 11:50:29 +05:30
Saurabh
2ac1835f7d [fix] if is_root is true make parent account empty (#12255) 2018-01-01 16:17:43 +05:30
Saurabh
15d53c7912 [fix] key error (#12257) 2018-01-01 16:17:14 +05:30
Saurabh
9579645ae1 [fix] if item code exists then only call get_item_details (#12258) 2018-01-01 16:17:02 +05:30
Saurabh
a6b41e855b [fix] check if null for mode of payments (#12264) 2018-01-01 16:16:50 +05:30
rohitwaghchaure
526b0bc4e9 [minor] Code cleanup (#12278) 2018-01-01 16:16:16 +05:30
rohitwaghchaure
2640c7eec5 [Fix] Validation issue for online POS profile (#12276) 2018-01-01 16:15:41 +05:30
52 changed files with 544 additions and 172 deletions

View File

@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '10.0.4'
__version__ = '10.0.6'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -53,14 +53,12 @@ class Account(NestedSet):
def set_root_and_report_type(self):
if self.parent_account:
par = frappe.db.get_value("Account", self.parent_account,
["report_type", "root_type", "account_type"], as_dict=1)
["report_type", "root_type"], as_dict=1)
if par.report_type:
self.report_type = par.report_type
if par.root_type:
self.root_type = par.root_type
if par.account_type and not self.account_type:
self.account_type = par.account_type
if self.is_group:
db_value = frappe.db.get_value("Account", self.name, ["report_type", "root_type"], as_dict=1)

View File

@@ -130,7 +130,7 @@
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 1,
"set_only_once": 0,
"unique": 0
},
{
@@ -1476,7 +1476,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-12-11 17:30:45.198147",
"modified": "2018-01-03 17:30:45.198147",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Profile",

View File

@@ -63,7 +63,11 @@ class POSProfile(Document):
if len(default_mode_of_payment) > 1:
frappe.throw(_("Multiple default mode of payment is not allowed"))
def validate_customer_territory_group(self):
if not frappe.db.get_single_value('POS Settings', 'use_pos_in_offline_mode'):
return
if not self.territory:
frappe.throw(_("Territory is Required in POS Profile"), title="Mandatory Field")
@@ -103,7 +107,7 @@ def get_item_groups(pos_profile):
if pos_profile.get('item_groups'):
# Get items based on the item groups defined in the POS profile
for data in pos_profile.get('item_groups'):
item_groups.extend(["'%s'"%d.name for d in get_child_nodes('Item Group', data.item_group)])
item_groups.extend(["'%s'" % frappe.db.escape(d.name) for d in get_child_nodes('Item Group', data.item_group)])
return list(set(item_groups))

View File

@@ -18,7 +18,7 @@ QUnit.test("test purchase invoice", function(assert) {
{update_stock:1},
{supplier_address: 'Test1-Billing'},
{contact_person: 'Contact 3-Test Supplier'},
{taxes_and_charges: 'TEST In State GST'},
{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'}
@@ -29,7 +29,7 @@ QUnit.test("test purchase invoice", function(assert) {
// 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', "Tax details correct");
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

View File

@@ -3,6 +3,7 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from erpnext.accounts.doctype.sales_taxes_and_charges_template.sales_taxes_and_charges_template \
import valdiate_taxes_and_charges_template
@@ -10,3 +11,8 @@ from erpnext.accounts.doctype.sales_taxes_and_charges_template.sales_taxes_and_c
class PurchaseTaxesandChargesTemplate(Document):
def validate(self):
valdiate_taxes_and_charges_template(self)
def autoname(self):
if self.company and self.title:
abbr = frappe.db.get_value('Company', self.company, 'abbr')
self.name = '{0} - {1}'.format(self.title, abbr)

View File

@@ -1,7 +1,7 @@
QUnit.module('Sales Taxes and Charges Template');
QUnit.test("test sales taxes and charges template", function(assert) {
assert.expect(1);
assert.expect(2);
let done = assert.async();
frappe.run_serially([
() => {
@@ -19,7 +19,10 @@ QUnit.test("test sales taxes and charges template", function(assert) {
]}
]);
},
() => {assert.ok(cur_frm.doc.title=='TEST In State GST');},
() => {
assert.ok(cur_frm.doc.title=='TEST In State GST');
assert.ok(cur_frm.doc.name=='TEST In State GST - FT');
},
() => done()
]);
});

View File

@@ -17,7 +17,7 @@ QUnit.test("test sales Invoice", function(assert) {
{customer_address: 'Test1-Billing'},
{shipping_address_name: 'Test1-Shipping'},
{contact_person: 'Contact 1-Test Customer 1'},
{taxes_and_charges: 'TEST In State GST'},
{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'}
@@ -28,7 +28,7 @@ QUnit.test("test sales Invoice", function(assert) {
// 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', "Tax details correct");
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

View File

@@ -17,7 +17,7 @@ QUnit.test("test sales Invoice", function(assert) {
{customer_address: 'Test1-Billing'},
{shipping_address_name: 'Test1-Shipping'},
{contact_person: 'Contact 1-Test Customer 1'},
{taxes_and_charges: 'TEST In State GST'},
{taxes_and_charges: 'TEST In State GST - FT'},
{tc_name: 'Test Term 1'},
{terms: 'This is Test'}
]);
@@ -27,7 +27,7 @@ QUnit.test("test sales Invoice", function(assert) {
// 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', "Tax details correct");
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

View File

@@ -17,7 +17,7 @@ QUnit.test("test sales Invoice with payment", function(assert) {
{customer_address: 'Test1-Billing'},
{shipping_address_name: 'Test1-Shipping'},
{contact_person: 'Contact 1-Test Customer 1'},
{taxes_and_charges: 'TEST In State GST'},
{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'}
@@ -28,7 +28,7 @@ QUnit.test("test sales Invoice with payment", function(assert) {
// 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', "Tax details correct");
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");

View File

@@ -17,7 +17,7 @@ QUnit.test("test sales Invoice with payment request", function(assert) {
{customer_address: 'Test1-Billing'},
{shipping_address_name: 'Test1-Shipping'},
{contact_person: 'Contact 1-Test Customer 1'},
{taxes_and_charges: 'TEST In State GST'},
{taxes_and_charges: 'TEST In State GST - FT'},
{tc_name: 'Test Term 1'},
{terms: 'This is Test'}
]);
@@ -27,7 +27,7 @@ QUnit.test("test sales Invoice with payment request", function(assert) {
// 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', "Tax details correct");
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");

View File

@@ -17,7 +17,7 @@ QUnit.test("test sales Invoice with serialize item", function(assert) {
{customer_address: 'Test1-Billing'},
{shipping_address_name: 'Test1-Shipping'},
{contact_person: 'Contact 1-Test Customer 1'},
{taxes_and_charges: 'TEST In State GST'},
{taxes_and_charges: 'TEST In State GST - FT'},
{tc_name: 'Test Term 1'},
{terms: 'This is Test'}
]);
@@ -27,7 +27,7 @@ QUnit.test("test sales Invoice with serialize item", function(assert) {
// 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', "Tax details correct");
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

View File

@@ -11,7 +11,12 @@ from erpnext.controllers.accounts_controller import validate_taxes_and_charges,
class SalesTaxesandChargesTemplate(Document):
def validate(self):
valdiate_taxes_and_charges_template(self)
def autoname(self):
if self.company and self.title:
abbr = frappe.db.get_value('Company', self.company, 'abbr')
self.name = '{0} - {1}'.format(self.title, abbr)
def set_missing_values(self):
for data in self.taxes:
if data.charge_type == 'On Net Total' and flt(data.rate) == 0.0:

View File

@@ -1,7 +1,7 @@
QUnit.module('Sales Taxes and Charges Template');
QUnit.test("test sales taxes and charges template", function(assert) {
assert.expect(1);
assert.expect(2);
let done = assert.async();
frappe.run_serially([
() => {
@@ -19,7 +19,10 @@ QUnit.test("test sales taxes and charges template", function(assert) {
]}
]);
},
() => {assert.ok(cur_frm.doc.title=='TEST In State GST');},
() => {
assert.ok(cur_frm.doc.title=='TEST In State GST');
assert.ok(cur_frm.doc.name=='TEST In State GST - FT');
},
() => done()
]);
});

View File

@@ -2,7 +2,7 @@
{
"doctype": "Tax Rule",
"tax_type" : "Sales",
"sales_tax_template": "_Test Tax 1",
"sales_tax_template": "_Test Tax 1 - _TC",
"use_for_shopping_cart": 1,
"billing_city": "_Test City",
"billing_state": "Test State",
@@ -15,7 +15,7 @@
{
"doctype": "Tax Rule",
"tax_type" : "Sales",
"sales_tax_template": "_Test Tax 2",
"sales_tax_template": "_Test Tax 2 - _TC",
"use_for_shopping_cart": 0,
"billing_city": "_Test City",
"billing_country": "India",

View File

@@ -18,40 +18,40 @@ class TestTaxRule(unittest.TestCase):
def test_conflict(self):
tax_rule1 = make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1)
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1)
tax_rule1.save()
tax_rule2 = make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1)
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1)
self.assertRaises(ConflictingTaxRule, tax_rule2.save)
def test_conflict_with_non_overlapping_dates(self):
tax_rule1 = make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01")
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1, from_date = "2015-01-01")
tax_rule1.save()
tax_rule2 = make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, to_date = "2013-01-01")
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1, to_date = "2013-01-01")
tax_rule2.save()
self.assertTrue(tax_rule2.name)
def test_for_parent_customer_group(self):
tax_rule1 = make_tax_rule(customer_group= "All Customer Groups",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01")
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1, from_date = "2015-01-01")
tax_rule1.save()
self.assertEquals(get_tax_template("2015-01-01", {"customer_group" : "Commercial", "use_for_shopping_cart":0}),
"_Test Sales Taxes and Charges Template")
"_Test Sales Taxes and Charges Template - _TC")
def test_conflict_with_overlapping_dates(self):
tax_rule1 = make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01", to_date = "2015-01-05")
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1, from_date = "2015-01-01", to_date = "2015-01-05")
tax_rule1.save()
tax_rule2 = make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-03", to_date = "2015-01-09")
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1, from_date = "2015-01-03", to_date = "2015-01-09")
self.assertRaises(ConflictingTaxRule, tax_rule2.save)
@@ -62,66 +62,66 @@ class TestTaxRule(unittest.TestCase):
def test_select_tax_rule_based_on_customer(self):
make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)
make_tax_rule(customer= "_Test Customer 1",
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template 1 - _TC", save=1)
make_tax_rule(customer= "_Test Customer 2",
sales_tax_template = "_Test Sales Taxes and Charges Template 2", save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template 2 - _TC", save=1)
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer 2"}),
"_Test Sales Taxes and Charges Template 2")
"_Test Sales Taxes and Charges Template 2 - _TC")
def test_select_tax_rule_based_on_better_match(self):
make_tax_rule(customer= "_Test Customer", billing_city = "Test City", billing_state = "Test State",
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)
make_tax_rule(customer= "_Test Customer", billing_city = "Test City1", billing_state = "Test State",
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template 1 - _TC", save=1)
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City", "billing_state": "Test State"}),
"_Test Sales Taxes and Charges Template")
"_Test Sales Taxes and Charges Template - _TC")
def test_select_tax_rule_based_on_state_match(self):
make_tax_rule(customer= "_Test Customer", shipping_state = "Test State",
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)
make_tax_rule(customer= "_Test Customer", shipping_state = "Test State12",
sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template 1 - _TC", priority=2, save=1)
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "shipping_state": "Test State"}),
"_Test Sales Taxes and Charges Template")
"_Test Sales Taxes and Charges Template - _TC")
def test_select_tax_rule_based_on_better_priority(self):
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority=1, save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority=1, save=1)
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template 1 - _TC", priority=2, save=1)
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City"}),
"_Test Sales Taxes and Charges Template 1")
"_Test Sales Taxes and Charges Template 1 - _TC")
def test_select_tax_rule_based_cross_matching_keys(self):
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)
make_tax_rule(customer= "_Test Customer 1", billing_city = "Test City 1",
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template 1 - _TC", save=1)
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
None)
def test_select_tax_rule_based_cross_partially_keys(self):
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)
make_tax_rule(billing_city = "Test City 1",
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
sales_tax_template = "_Test Sales Taxes and Charges Template 1 - _TC", save=1)
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
"_Test Sales Taxes and Charges Template 1")
"_Test Sales Taxes and Charges Template 1 - _TC")
def make_tax_rule(**args):

View File

@@ -6,6 +6,7 @@ import frappe, erpnext
from frappe import _
from frappe.utils import flt
from frappe.model.meta import get_field_precision
from frappe.utils.xlsxutils import handle_html
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
def execute(filters=None):
@@ -188,10 +189,10 @@ def get_tax_accounts(item_list, columns, company_currency,
tuple([doctype] + invoice_item_row.keys()))
for parent, description, item_wise_tax_detail, charge_type, tax_amount in tax_details:
description = handle_html(description)
if description not in tax_columns and tax_amount:
# as description is text editor earlier and markup can break the column convention in reports
from frappe.utils.xlsxutils import handle_html
tax_columns.append(handle_html(description))
tax_columns.append(description)
if item_wise_tax_detail:
try:

View File

@@ -66,12 +66,12 @@ def get_mode_of_payments(filters):
invoice_list = get_invoices(filters)
invoice_list_names = ",".join(['"' + invoice['name'] + '"' for invoice in invoice_list])
if invoice_list:
inv_mop = frappe.db.sql("""select a.owner,a.posting_date,b.mode_of_payment
inv_mop = frappe.db.sql("""select a.owner,a.posting_date, ifnull(b.mode_of_payment, '') as mode_of_payment
from `tabSales Invoice` a, `tabSales Invoice Payment` b
where a.name = b.parent
and a.name in ({invoice_list_names})
union
select a.owner,a.posting_date,b.mode_of_payment
select a.owner,a.posting_date, ifnull(b.mode_of_payment, '') as mode_of_payment
from `tabSales Invoice` a, `tabPayment Entry` b,`tabPayment Entry Reference` c
where a.name = c.reference_name
and b.name = c.parent

View File

@@ -252,6 +252,9 @@ def add_ac(args=None):
if not ac.parent_account:
ac.parent_account = args.get("parent")
if ac.is_root:
ac.parent_account=''
ac.old_parent = ""
ac.freeze_account = "No"
if cint(ac.get("is_root")):

View File

@@ -25,7 +25,7 @@ erpnext.crop.update_item_rate_uom = function(frm, cdt, cdn) {
let material_list = ['materials_required', 'produce', 'byproducts'];
material_list.forEach((material) => {
frm.doc[material].forEach((item, index) => {
if (item.name == cdn){
if (item.name == cdn && item.item_code){
frappe.call({
method:'erpnext.agriculture.doctype.crop.crop.get_item_details',
args: {

View File

@@ -24,7 +24,7 @@ QUnit.test("test: purchase order with taxes and charges", function(assert) {
]
]},
{taxes_and_charges: 'TEST In State GST'}
{taxes_and_charges: 'TEST In State GST - FT'}
]);
},

View File

@@ -17,7 +17,7 @@ QUnit.test("test: supplier quotation with taxes and charges", function(assert) {
{"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
]
]},
{taxes_and_charges:'TEST In State GST'},
{taxes_and_charges:'TEST In State GST - FT'},
]);
},
() => {supplier_quotation_name = cur_frm.doc.name;},

View File

@@ -431,7 +431,7 @@ class BuyingController(StockController):
d.schedule_date = self.schedule_date
if d.schedule_date and getdate(d.schedule_date) < getdate(self.transaction_date):
frappe.throw(_("Expected Date cannot be before Transaction Date"))
frappe.throw(_("Row #{0}: Reqd by Date cannot be before Transaction Date").format(d.idx))
else:
frappe.throw(_("Please enter Schedule Date"))
frappe.throw(_("Please enter Reqd by Date"))

View File

@@ -101,7 +101,7 @@ class Lead(SellingController):
def set_lead_name(self):
if not self.lead_name:
frappe.db.set_value("Lead", self.name, "lead_name", self.organization_name)
frappe.db.set_value("Lead", self.name, "lead_name", self.company_name)
@frappe.whitelist()
def make_customer(source_name, target_doc=None):

View File

@@ -29,7 +29,7 @@
"email_id": "test_lead4@example.com",
"organization_lead": 1,
"lead_name": "_Test Lead 4",
"organization_name": "_Test Lead 4",
"company_name": "_Test Lead 4",
"status": "Open"
}
]

View File

@@ -1,16 +1,21 @@
# Program Enrollment Tool
The Program Enrollment tool allows the bulk enrollment of the **Student Applicants** in a Program.
The Program Enrollment tool allows the bulk enrollment of the new and old students in a Program. If you are enrolling a new student, you can fetch the students from the **Student Applicant** or if you are promoting the older students you can fetch them from the **Program Enrollment** itself
> Note: Academic Term is optional in the Program Enrollment Tool
You can create the the Program Enrollment for :
You can create the Program Enrollment for :
1. **Student Applicants** >> List of Student Applicants will be fetched for the selected **Program** and **Academic year**.
1. **Student Applicants**: List of Student Applicants will be fetched for the selected **Program**, **Academic year** and **Academic Term** (if provided).
<img class="screenshot" alt="Student Applicant Enrollment" src="/docs/assets/img/education/admission/program-enrollment-tool.gif">
2. **Program Enrollment** >> You can bulk update the **Program** for the students from one academic year to another in the same **Program** or a new **Program**.
2. **Program Enrollment**: List of students already enrolled in selected **Program** for the given **Academic Year**, **Academic Term** (if provided) and **Student Batch** will be fetched and can be used to enroll students from one academic year/term to another in the same **Program** or a new **Program**.
<img class="screenshot" alt="Student Applicant Enrollment" src="/docs/assets/img/education/admission/program-enrollment-tool01.gif">
**New Student Batch**: This can be selected for the entire students fetched in the table. Priority will be given to the Batch selected in the table (for individual students).
For promoting the students, the new academic year, academic term and program can also be selected for the enrollment of the fetched students list.
{next}

View File

@@ -1,11 +1,19 @@
// Copyright (c) 2016, Frappe and contributors
// For license information, please see license.txt
cur_frm.add_fetch("student", "title", "student_name");
cur_frm.add_fetch("student_applicant", "title", "student_name");
frappe.ui.form.on("Program Enrollment Tool", {
setup: function(frm) {
frm.add_fetch("student", "title", "student_name");
frm.add_fetch("student_applicant", "title", "student_name");
},
"refresh": function(frm) {
frm.disable_save();
frm.fields_dict.enroll_students.$input.addClass(' btn btn-primary');
frappe.realtime.on("program_enrollment_tool", function(data) {
frappe.hide_msgprint(true);
frappe.show_progress(__("Enrolling students"), data.progress[0], data.progress[1]);
});
},
"get_students": function(frm) {
@@ -18,7 +26,7 @@ frappe.ui.form.on("Program Enrollment Tool", {
frm.set_value("students", r.message);
}
}
})
});
},
"enroll_students": function(frm) {
@@ -27,7 +35,8 @@ frappe.ui.form.on("Program Enrollment Tool", {
doc:frm.doc,
callback: function(r) {
frm.set_value("students", []);
frappe.hide_msgprint(true);
}
})
});
}
});

View File

@@ -29,7 +29,7 @@
"label": "Get Students From",
"length": 0,
"no_copy": 0,
"options": "\nStudent Applicants\nProgram Enrollments",
"options": "\nStudent Applicant\nProgram Enrollment",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -73,6 +73,67 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.get_students_from==\"Program Enrollment\"",
"fieldname": "student_batch",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Student Batch",
"length": 0,
"no_copy": 0,
"options": "Student Batch Name",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@@ -110,8 +171,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "get_students",
"fieldtype": "Button",
"fieldname": "academic_term",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -119,9 +180,10 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Get Students",
"label": "Academic Term",
"length": 0,
"no_copy": 0,
"options": "Academic Term",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -163,6 +225,36 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "get_students",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Get Students",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@@ -209,6 +301,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Enrollment Details",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -229,7 +322,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.get_students_from==\"Program Enrollments\"",
"depends_on": "eval:doc.get_students_from==\"Program Enrollment\"",
"fieldname": "new_program",
"fieldtype": "Link",
"hidden": 0,
@@ -261,8 +354,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.get_students_from==\"Program Enrollments\"",
"fieldname": "new_academic_year",
"fieldname": "new_student_batch",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -271,10 +363,10 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "New Academic Year",
"label": "New Student Batch",
"length": 0,
"no_copy": 0,
"options": "Academic Year",
"options": "Student Batch Name",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -316,6 +408,99 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_12",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.get_students_from==\"Program Enrollment\"",
"fieldname": "new_academic_year",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "New Academic Year",
"length": 0,
"no_copy": 0,
"options": "Academic Year",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.get_students_from==\"Program Enrollment\"",
"fieldname": "new_academic_term",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "New Academic Term",
"length": 0,
"no_copy": 0,
"options": "Academic Term",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
@@ -328,7 +513,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2017-12-27 09:35:45.002469",
"modified": "2018-01-02 11:59:40.230689",
"modified_by": "Administrator",
"module": "Education",
"name": "Program Enrollment Tool",

View File

@@ -17,21 +17,26 @@ class ProgramEnrollmentTool(Document):
elif not self.academic_year:
frappe.throw(_("Mandatory field - Academic Year"))
else:
if self.get_students_from == "Student Applicants":
students = frappe.db.sql("select name as student_applicant, title as student_name from \
`tabStudent Applicant` where program = %s and academic_year = %s",(self.program, self.academic_year), as_dict=1)
else:
students = frappe.db.sql("select student, student_name, student_batch_name from \
`tabProgram Enrollment` where program = %s and academic_year = %s",(self.program, self.academic_year), as_dict=1)
condition = 'and academic_term=%(academic_term)s' if self.academic_term else " "
if self.get_students_from == "Student Applicant":
students = frappe.db.sql('''select name as student_applicant, title as student_name from `tabStudent Applicant`
where application_status="Approved" and program=%(program)s and academic_year=%(academic_year)s {0}'''
.format(condition), self.as_dict(), as_dict=1)
elif self.get_students_from == "Program Enrollment":
condition2 = 'and student_batch_name=%(student_batch)s' if self.student_batch else " "
students = frappe.db.sql('''select student, student_name, student_batch_name from `tabProgram Enrollment`
where program=%(program)s and academic_year=%(academic_year)s {0} {1}'''
.format(condition, condition2), self.as_dict(), as_dict=1)
student_list = [d.student for d in students]
if student_list:
inactive_students = frappe.db.sql('''
select name as student, title as student_name from `tabStudent` where name in (%s) and enabled = 0''' %
', '.join(['%s']*len(student_list)), tuple(student_list), as_dict=1)
inactive_students = frappe.db.sql('''
select name as student, title as student_name from `tabStudent` where name in (%s) and enabled = 0''' %
', '.join(['%s']*len(student_list)), tuple(student_list), as_dict=1)
for student in students:
if student.student in [d.student for d in inactive_students]:
students.remove(student)
for student in students:
if student.student in [d.student for d in inactive_students]:
students.remove(student)
if students:
return students
@@ -39,18 +44,22 @@ class ProgramEnrollmentTool(Document):
frappe.throw(_("No students Found"))
def enroll_students(self):
for stud in self.students:
total = len(self.students)
for i, stud in enumerate(self.students):
frappe.publish_realtime("program_enrollment_tool", dict(progress=[i+1, total]), user=frappe.session.user)
if stud.student:
prog_enrollment = frappe.new_doc("Program Enrollment")
prog_enrollment.student = stud.student
prog_enrollment.student_name = stud.student_name
prog_enrollment.student_batch_name = stud.student_batch_name
prog_enrollment.program = self.new_program
prog_enrollment.academic_year = self.new_academic_year
prog_enrollment.academic_term = self.new_academic_term
prog_enrollment.student_batch_name = stud.student_batch_name if stud.student_batch_name else self.new_student_batch
prog_enrollment.save()
elif stud.student_applicant:
prog_enrollment = enroll_student(stud.student_applicant)
prog_enrollment.academic_year = self.academic_year
prog_enrollment.academic_term = self.academic_term
prog_enrollment.student_batch_name = stud.student_batch_name if stud.student_batch_name else self.new_student_batch
prog_enrollment.save()
frappe.msgprint("Students have been enrolled.")
frappe.msgprint("{0} Students have been enrolled.".format(total))

View File

@@ -133,6 +133,37 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "student_batch_name",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Student Batch Name",
"length": 0,
"no_copy": 0,
"options": "Student Batch Name",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
@@ -145,7 +176,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-11-10 19:09:59.530615",
"modified": "2018-01-02 12:03:53.890741",
"modified_by": "Administrator",
"module": "Education",
"name": "Program Enrollment Tool Student",

View File

@@ -320,6 +320,37 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "academic_term",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Academic Term",
"length": 0,
"no_copy": 0,
"options": "Academic Term",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@@ -1058,7 +1089,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2017-11-10 19:08:55.049625",
"modified": "2018-01-02 11:47:14.944338",
"modified_by": "Administrator",
"module": "Education",
"name": "Student Applicant",

View File

@@ -262,27 +262,30 @@ frappe.ui.form.on("Expense Claim", {
},
get_advances: function(frm) {
return frappe.call({
method: "erpnext.hr.doctype.expense_claim.expense_claim.get_advances",
args: {
employee: frm.doc.employee
},
callback: function(r, rt) {
frappe.model.clear_table(frm.doc, "advances");
if(r.message) {
$.each(r.message, function(i, d) {
var row = frappe.model.add_child(frm.doc, "Expense Claim Advance", "advances");
row.employee_advance = d.name;
row.posting_date = d.posting_date;
row.advance_account = d.advance_account;
row.advance_paid = d.paid_amount;
row.unclaimed_amount = flt(d.paid_amount) - flt(d.claimed_amount);
row.allocated_amount = flt(d.paid_amount) - flt(d.claimed_amount);
});
refresh_field("advances");
frappe.model.clear_table(frm.doc, "advances");
if (frm.doc.employee) {
return frappe.call({
method: "erpnext.hr.doctype.expense_claim.expense_claim.get_advances",
args: {
employee: frm.doc.employee
},
callback: function(r, rt) {
if(r.message) {
$.each(r.message, function(i, d) {
var row = frappe.model.add_child(frm.doc, "Expense Claim Advance", "advances");
row.employee_advance = d.name;
row.posting_date = d.posting_date;
row.advance_account = d.advance_account;
row.advance_paid = d.paid_amount;
row.unclaimed_amount = flt(d.paid_amount) - flt(d.claimed_amount);
row.allocated_amount = flt(d.paid_amount) - flt(d.claimed_amount);
});
refresh_field("advances");
}
}
}
});
});
}
}
});

View File

@@ -591,7 +591,7 @@ def validate_bom_no(item, bom_no):
frappe.throw(_("BOM {0} does not belong to Item {1}").format(bom_no, item))
@frappe.whitelist()
def get_children(doctype, parent=None, is_tree=False):
def get_children(doctype, parent=None, is_root=False, **filters):
if not parent:
frappe.msgprint(_('Please select a BOM'))
return

View File

@@ -236,7 +236,11 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
var taxes_and_charges_field = frappe.meta.get_docfield(me.frm.doc.doctype, "taxes_and_charges",
me.frm.doc.name);
if(taxes_and_charges_field) {
if (!this.frm.doc.taxes_and_charges && this.frm.doc.taxes) {
return;
}
if (taxes_and_charges_field) {
return frappe.call({
method: "erpnext.controllers.accounts_controller.get_default_taxes_and_charges",
args: {
@@ -521,6 +525,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
if(r.message) {
me.frm.set_value("due_date", r.message);
frappe.ui.form.trigger(me.frm.doc.doctype, "currency");
me.recalculate_terms();
}
}
})
@@ -530,6 +535,29 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
},
recalculate_terms: function() {
const doc = this.frm.doc;
if (doc.payment_terms_template) {
this.payment_terms_template();
} else if (doc.payment_schedule) {
const me = this;
doc.payment_schedule.forEach(
function(term) {
if (term.payment_term) {
me.payment_term(doc, term.doctype, term.name);
} else {
frappe.model.set_value(
term.doctype, term.name, 'due_date',
doc.posting_date || doc.transaction_date
);
}
}
);
}
},
get_company_currency: function() {
return erpnext.get_currency(this.frm.doc.company);
},

View File

@@ -7,7 +7,9 @@ def update_itemised_tax_data(doc):
itemised_tax = get_itemised_tax(doc.taxes)
for row in doc.items:
tax_rate = sum([tax.get('tax_rate', 0) for d, tax in itemised_tax.get(row.item_code).items()])
tax_rate = 0.0
if itemised_tax.get(row.item_code):
tax_rate = sum([tax.get('tax_rate', 0) for d, tax in itemised_tax.get(row.item_code).items()])
row.tax_rate = flt(tax_rate, row.precision("tax_rate"))
row.tax_amount = flt((row.net_amount * tax_rate) / 100, row.precision("net_amount"))

View File

@@ -17,7 +17,7 @@ QUnit.test("test quotation with taxes and charges", function(assert) {
{customer_address: 'Test1-Billing'},
{shipping_address_name: 'Test1-Shipping'},
{contact_person: 'Contact 1-Test Customer 1'},
{taxes_and_charges: 'TEST In State GST'},
{taxes_and_charges: 'TEST In State GST - FT'},
{tc_name: 'Test Term 1'},
{terms: 'This is Test'}
]);
@@ -27,7 +27,7 @@ QUnit.test("test quotation with taxes and charges", function(assert) {
// 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', "Tax details correct");
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");

View File

@@ -17,7 +17,7 @@ QUnit.test("test sales order", function(assert) {
{customer_address: 'Test1-Billing'},
{shipping_address_name: 'Test1-Shipping'},
{contact_person: 'Contact 1-Test Customer 1'},
{taxes_and_charges: 'TEST In State GST'},
{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'}
@@ -34,7 +34,7 @@ QUnit.test("test sales order", function(assert) {
// 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', "Tax details correct");
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");
},

View File

@@ -17,7 +17,7 @@ QUnit.test("test sales order with taxes and charges", function(assert) {
{customer_address: 'Test1-Billing'},
{shipping_address_name: 'Test1-Shipping'},
{contact_person: 'Contact 1-Test Customer 1'},
{taxes_and_charges: 'TEST In State GST'},
{taxes_and_charges: 'TEST In State GST - FT'},
{tc_name: 'Test Term 1'},
{terms: 'This is Test'}
]);
@@ -27,7 +27,7 @@ QUnit.test("test sales order with taxes and charges", function(assert) {
// 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', "Tax details correct");
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");

View File

@@ -360,6 +360,7 @@ erpnext.pos.PointOfSale = class PointOfSale {
fieldtype: 'Link',
label: __('POS Profile'),
options: 'POS Profile',
reqd: 1,
get_query: () => {
return {
query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query',
@@ -1211,6 +1212,7 @@ class POSItems {
return new Promise(res => {
frappe.call({
method: "erpnext.selling.page.point_of_sale.point_of_sale.get_items",
freeze: true,
args: {
start,
page_length,

View File

@@ -34,24 +34,52 @@ frappe.ui.form.on("Company", {
frm.add_custom_button(__('Cost Centers'), function() {
frappe.set_route('Tree', 'Cost Center', {'company': frm.doc.name})
})
}, __("View"));
frm.add_custom_button(__('Chart of Accounts'), function() {
frappe.set_route('Tree', 'Account', {'company': frm.doc.name})
})
}, __("View"));
frm.add_custom_button(__('Sales Tax Template'), function() {
frappe.set_route('List', 'Sales Taxes and Charges Template', {'company': frm.doc.name});
}, __("View"));
frm.add_custom_button(__('Purchase Tax Template'), function() {
frappe.set_route('List', 'Purchase Taxes and Charges Template', {'company': frm.doc.name});
}, __("View"));
frm.add_custom_button(__('Default Tax Template'), function() {
frm.trigger("make_default_tax_template");
}, __("Make"));
frm.page.set_inner_btn_group_as_primary(__("View"));
frm.page.set_inner_btn_group_as_primary(__("Make"));
}
erpnext.company.set_chart_of_accounts_options(frm.doc);
},
make_default_tax_template: function(frm) {
frm.call({
method: "create_default_tax_template",
doc: frm.doc,
freeze: true,
callback: function() {
frappe.msgprint(__("Default tax templates for sales and purchase are created."));
}
})
},
onload_post_render: function(frm) {
if(frm.get_field("delete_company_transactions").$input)
frm.get_field("delete_company_transactions").$input.addClass("btn-danger");
},
country: function(frm) {
erpnext.company.set_chart_of_accounts_options(frm.doc);
},
delete_company_transactions: function(frm) {
frappe.verify_password(function() {
var d = frappe.prompt({

View File

@@ -50,6 +50,13 @@ class Company(Document):
if frappe.db.sql("select abbr from tabCompany where name!=%s and abbr=%s", (self.name, self.abbr)):
frappe.throw(_("Abbreviation already used for another company"))
def create_default_tax_template(self):
from erpnext.setup.setup_wizard.operations.taxes_setup import create_sales_tax
create_sales_tax({
'country': self.country,
'company_name': self.name
})
def validate_default_accounts(self):
for field in ["default_bank_account", "default_cash_account",
"default_receivable_account", "default_payable_account",

View File

@@ -82,7 +82,7 @@ def get_product_list_for_group(product_group=None, start=0, limit=10, search=Non
# base query
query = """select I.name, I.item_name, I.item_code, I.route, I.image, I.website_image, I.thumbnail, I.item_group,
I.description, I.web_long_description as website_description,
I.description, I.web_long_description as website_description, I.is_stock_item,
case when (S.actual_qty - S.reserved_qty) > 0 then 1 else 0 end as in_stock
from `tabItem` I
left join tabBin S on I.item_code = S.item_code and I.website_warehouse = S.warehouse

View File

@@ -16,38 +16,44 @@ def create_sales_tax(args):
tax_data.get('tax_rate'), sales_tax)
def make_tax_account_and_template(company, account_name, tax_rate, template_name=None):
if not isinstance(account_name, (list, tuple)):
account_name = [account_name]
tax_rate = [tax_rate]
accounts = []
for i, name in enumerate(account_name):
tax_account = make_tax_account(company, account_name[i], tax_rate[i])
if tax_account:
accounts.append(tax_account)
try:
if not isinstance(account_name, (list, tuple)):
account_name = [account_name]
tax_rate = [tax_rate]
accounts = []
for i, name in enumerate(account_name):
tax_account = make_tax_account(company, account_name[i], tax_rate[i])
if tax_account:
accounts.append(tax_account)
if accounts:
make_sales_and_purchase_tax_templates(accounts, template_name)
except frappe.NameError:
pass
frappe.message_log.pop()
except RootNotEditable:
pass
def make_tax_account(company, account_name, tax_rate):
tax_group = get_tax_account_group(company)
if tax_group:
return frappe.get_doc({
"doctype":"Account",
"company": company,
"parent_account": tax_group,
"account_name": account_name,
"is_group": 0,
"report_type": "Balance Sheet",
"root_type": "Liability",
"account_type": "Tax",
"tax_rate": flt(tax_rate) if tax_rate else None
}).insert(ignore_permissions=True, ignore_mandatory=True)
try:
return frappe.get_doc({
"doctype":"Account",
"company": company,
"parent_account": tax_group,
"account_name": account_name,
"is_group": 0,
"report_type": "Balance Sheet",
"root_type": "Liability",
"account_type": "Tax",
"tax_rate": flt(tax_rate) if tax_rate else None
}).insert(ignore_permissions=True, ignore_mandatory=True)
except frappe.NameError:
frappe.message_log.pop()
abbr = frappe.db.get_value('Company', company, 'abbr')
account = '{0} - {1}'.format(account_name, abbr)
return frappe.get_doc('Account', account)
def make_sales_and_purchase_tax_templates(accounts, template_name=None):
if not template_name:
@@ -62,7 +68,7 @@ def make_sales_and_purchase_tax_templates(accounts, template_name=None):
for account in accounts:
sales_tax_template['taxes'].append({
"category": "Valuation and Total",
"category": "Total",
"charge_type": "On Net Total",
"account_head": account.name,
"description": "{0} @ {1}".format(account.account_name, account.tax_rate),

View File

@@ -30,10 +30,10 @@ def get_product_info_for_website(item_code):
product_info = {
"price": price,
"stock_qty": stock_status.stock_qty,
"in_stock": stock_status.in_stock,
"in_stock": stock_status.in_stock if stock_status.is_stock_item else 1,
"qty": 0,
"uom": frappe.db.get_value("Item", item_code, "stock_uom"),
"show_stock_qty": show_quantity_in_website()
"show_stock_qty": show_quantity_in_website() if stock_status.is_stock_item else 0
}
if product_info["price"]:

View File

@@ -128,7 +128,7 @@ class TestShoppingCart(unittest.TestCase):
"contact_email": frappe.session.user,
"selling_price_list": "_Test Price List Rest of the World",
"currency": "USD",
"taxes_and_charges" : "_Test Tax 1",
"taxes_and_charges" : "_Test Tax 1 - _TC",
"conversion_rate":1,
"transaction_date" : nowdate(),
"valid_till" : add_months(nowdate(), 1),
@@ -136,7 +136,7 @@ class TestShoppingCart(unittest.TestCase):
"item_code": "_Test Item",
"qty": 1
}],
"taxes": frappe.get_doc("Sales Taxes and Charges Template", "_Test Tax 1").taxes,
"taxes": frappe.get_doc("Sales Taxes and Charges Template", "_Test Tax 1 - _TC").taxes,
"company": "_Test Company"
}

View File

@@ -15,7 +15,7 @@ QUnit.test("test delivery note", function(assert) {
]},
{shipping_address_name: 'Test1-Shipping'},
{contact_person: 'Contact 1-Test Customer 1'},
{taxes_and_charges: 'TEST In State GST'},
{taxes_and_charges: 'TEST In State GST - FT'},
{tc_name: 'Test Term 1'},
{transporter_name:'TEST TRANSPORT'},
{lr_no:'MH-04-FG 1111'}

View File

@@ -137,10 +137,10 @@ class PackingSlip(Document):
for d in self.get("items"):
res = frappe.db.get_value("Item", d.item_code,
["net_weight", "weight_uom"], as_dict=True)
["weight_per_unit", "weight_uom"], as_dict=True)
if res and len(res)>0:
d.net_weight = res["net_weight"]
d.net_weight = res["weight_per_unit"]
d.weight_uom = res["weight_uom"]
def get_recommended_case_no(self):

View File

@@ -17,7 +17,7 @@ QUnit.test("test Purchase Receipt", function(assert) {
{'rejected_warehouse':'Work In Progress - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
]
]},
{taxes_and_charges: 'TEST In State GST'},
{taxes_and_charges: 'TEST In State GST - FT'},
{tc_name: 'Test Term 1'},
{terms: 'This is Test'}
]);
@@ -27,7 +27,7 @@ QUnit.test("test Purchase Receipt", function(assert) {
// 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', "Tax details correct");
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

View File

@@ -37,9 +37,10 @@ def get_item_price_qty_data(filters):
from `tabItem Price` a left join `tabBin` b
ON a.item_code = b.item_code
{conditions}"""
.format(conditions=conditions),filters,as_dict=1)
.format(conditions=conditions), filters, as_dict=1)
price_list_names = ",".join(['"' + item['price_list_name'] + '"' for item in item_results])
price_list_names = ",".join(['"' + frappe.db.escape(item['price_list_name']) + '"'
for item in item_results])
buying_price_map = get_buying_price_map(price_list_names)
selling_price_map = get_selling_price_map(price_list_names)
@@ -66,7 +67,8 @@ def get_buying_price_map(price_list_names):
`tabItem Price`
where
name in ({price_list_names}) and buying=1
""".format(price_list_names=price_list_names),as_dict=1)
""".format(price_list_names=price_list_names), as_dict=1)
buying_price_map = {}
for d in buying_price:
name = d["name"]
@@ -84,7 +86,8 @@ def get_selling_price_map(price_list_names):
`tabItem Price`
where
name in ({price_list_names}) and selling=1
""".format(price_list_names=price_list_names),as_dict=1)
""".format(price_list_names=price_list_names), as_dict=1)
selling_price_map = {}
for d in selling_price:
name = d["name"]

View File

@@ -64,7 +64,7 @@ frappe.ready(function() {
// then chose the closest available one
var attribute = $(this).attr("data-attribute");
var attribute_value = $(this).val()
var attribute_value = $(this).val();
var item_code = find_closest_match(attribute, attribute_value);
if (!item_code) {

View File

@@ -5,7 +5,7 @@
<div class="product-image-img">
{{ product_image_square(thumbnail or website_image) }}
<div class="product-text" itemprop="name">{{ item_name }}</div>
{% if in_stock %}
{% if in_stock or not is_stock_item %}
<div style='color: green'> <i class='fa fa-check'></i> {{ _("In stock") }}</div>
{% else %}
<div style='color: red'> <i class='fa fa-close'></i> {{ _("Not in stock") }}</div>

View File

@@ -9,7 +9,7 @@ from erpnext.accounts.doctype.pricing_rule.pricing_rule import get_pricing_rule_
def get_qty_in_stock(item_code, item_warehouse_field):
in_stock, stock_qty = 0, ''
template_item_code = frappe.db.get_value("Item", item_code, "variant_of")
template_item_code, is_stock_item = frappe.db.get_value("Item", item_code, ["variant_of", "is_stock_item"])
warehouse = frappe.db.get_value("Item", item_code, item_warehouse_field)
if not warehouse and template_item_code and template_item_code != item_code:
@@ -21,7 +21,7 @@ def get_qty_in_stock(item_code, item_warehouse_field):
if stock_qty:
in_stock = stock_qty[0][0] > 0 and 1 or 0
return frappe._dict({"in_stock": in_stock, "stock_qty": stock_qty})
return frappe._dict({"in_stock": in_stock, "stock_qty": stock_qty, "is_stock_item": is_stock_item})
def get_price(item_code, price_list, customer_group, company, qty=1):
template_item_code = frappe.db.get_value("Item", item_code, "variant_of")