Merge branch 'develop' into company-issue

This commit is contained in:
Marica 2020-10-12 17:25:12 +05:30 committed by GitHub
commit 6d935d4e48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
161 changed files with 103590 additions and 17201 deletions

View File

@ -53,7 +53,7 @@
{
"hidden": 0,
"label": "Goods and Services Tax (GST India)",
"links": "[\n {\n \"label\": \"GST Settings\",\n \"name\": \"GST Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"GST HSN Code\",\n \"name\": \"GST HSN Code\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-1\",\n \"name\": \"GSTR-1\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-2\",\n \"name\": \"GSTR-2\",\n \"type\": \"report\"\n },\n {\n \"label\": \"GSTR 3B Report\",\n \"name\": \"GSTR 3B Report\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Sales Register\",\n \"name\": \"GST Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Purchase Register\",\n \"name\": \"GST Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Sales Register\",\n \"name\": \"GST Itemised Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Purchase Register\",\n \"name\": \"GST Itemised Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"country\": \"India\",\n \"description\": \"C-Form records\",\n \"label\": \"C-Form\",\n \"name\": \"C-Form\",\n \"type\": \"doctype\"\n }\n]"
"links": "[\n {\n \"label\": \"GST Settings\",\n \"name\": \"GST Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"GST HSN Code\",\n \"name\": \"GST HSN Code\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-1\",\n \"name\": \"GSTR-1\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-2\",\n \"name\": \"GSTR-2\",\n \"type\": \"report\"\n },\n {\n \"label\": \"GSTR 3B Report\",\n \"name\": \"GSTR 3B Report\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Sales Register\",\n \"name\": \"GST Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Purchase Register\",\n \"name\": \"GST Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Sales Register\",\n \"name\": \"GST Itemised Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Purchase Register\",\n \"name\": \"GST Itemised Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"country\": \"India\",\n \"description\": \"C-Form records\",\n \"label\": \"C-Form\",\n \"name\": \"C-Form\",\n \"type\": \"doctype\"\n },\n {\n \"country\": \"India\",\n \"label\": \"Lower Deduction Certificate\",\n \"name\": \"Lower Deduction Certificate\",\n \"type\": \"doctype\"\n }\n]"
},
{
"hidden": 0,
@ -98,7 +98,7 @@
"idx": 0,
"is_standard": 1,
"label": "Accounting",
"modified": "2020-09-09 11:45:33.766400",
"modified": "2020-10-08 20:31:46.022470",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting",

View File

@ -117,7 +117,9 @@ class Account(NestedSet):
for d in frappe.db.get_values('Account', filters=filters, fieldname=["company", "name"], as_dict=True):
parent_acc_name_map[d["company"]] = d["name"]
if not parent_acc_name_map: return
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
def validate_group_or_ledger(self):
@ -289,10 +291,30 @@ def validate_account_number(name, account_number, company):
.format(account_number, account_with_same_number))
@frappe.whitelist()
def update_account_number(name, account_name, account_number=None):
def update_account_number(name, account_name, account_number=None, from_descendant=False):
account = frappe.db.get_value("Account", name, "company", as_dict=True)
if not account: return
old_acc_name, old_acc_number = frappe.db.get_value('Account', name, \
["account_name", "account_number"])
# check if account exists in parent company
ancestors = get_ancestors_of("Company", account.company)
allow_independent_account_creation = frappe.get_value("Company", account.company, "allow_account_creation_against_child_company")
if ancestors and not allow_independent_account_creation:
for ancestor in ancestors:
if frappe.db.get_value("Account", {'account_name': old_acc_name, 'company': ancestor}, 'name'):
# same account in parent company exists
allow_child_account_creation = _("Allow Account Creation Against Child Company")
message = _("Account {0} exists in parent company {1}.").format(frappe.bold(old_acc_name), frappe.bold(ancestor))
message += "<br>" + _("Renaming it is only allowed via parent company {0}, \
to avoid mismatch.").format(frappe.bold(ancestor)) + "<br><br>"
message += _("To overrule this, enable '{0}' in company {1}").format(allow_child_account_creation, frappe.bold(account.company))
frappe.throw(message, title=_("Rename Not Allowed"))
validate_account_number(name, account_number, account.company)
if account_number:
frappe.db.set_value("Account", name, "account_number", account_number.strip())
@ -300,6 +322,12 @@ def update_account_number(name, account_name, account_number=None):
frappe.db.set_value("Account", name, "account_number", "")
frappe.db.set_value("Account", name, "account_name", account_name.strip())
if not from_descendant:
# Update and rename in child company accounts as well
descendants = get_descendants_of('Company', account.company)
if descendants:
sync_update_account_number_in_child(descendants, old_acc_name, account_name, account_number, old_acc_number)
new_name = get_account_autoname(account_number, account_name, account.company)
if name != new_name:
frappe.rename_doc("Account", name, new_name, force=1)
@ -330,3 +358,14 @@ def get_root_company(company):
# return the topmost company in the hierarchy
ancestors = get_ancestors_of('Company', company, "lft asc")
return [ancestors[0]] if ancestors else []
def sync_update_account_number_in_child(descendants, old_acc_name, account_name, account_number=None, old_acc_number=None):
filters = {
"company": ["in", descendants],
"account_name": old_acc_name,
}
if old_acc_number:
filters["account_number"] = old_acc_number
for d in frappe.db.get_values('Account', filters=filters, fieldname=["company", "name"], as_dict=True):
update_account_number(d["name"], account_name, account_number, from_descendant=True)

View File

@ -5,8 +5,7 @@ from __future__ import unicode_literals
import unittest
import frappe
from erpnext.stock import get_warehouse_account, get_company_default_inventory_account
from erpnext.accounts.doctype.account.account import update_account_number
from erpnext.accounts.doctype.account.account import merge_account
from erpnext.accounts.doctype.account.account import update_account_number, merge_account
class TestAccount(unittest.TestCase):
def test_rename_account(self):
@ -99,7 +98,8 @@ class TestAccount(unittest.TestCase):
"Softwares - _TC", doc.is_group, doc.root_type, doc.company)
def test_account_sync(self):
del frappe.local.flags["ignore_root_company_validation"]
frappe.local.flags.pop("ignore_root_company_validation", None)
acc = frappe.new_doc("Account")
acc.account_name = "Test Sync Account"
acc.parent_account = "Temporary Accounts - _TC3"
@ -111,6 +111,55 @@ class TestAccount(unittest.TestCase):
self.assertEqual(acc_tc_4, "Test Sync Account - _TC4")
self.assertEqual(acc_tc_5, "Test Sync Account - _TC5")
def test_account_rename_sync(self):
frappe.local.flags.pop("ignore_root_company_validation", None)
acc = frappe.new_doc("Account")
acc.account_name = "Test Rename Account"
acc.parent_account = "Temporary Accounts - _TC3"
acc.company = "_Test Company 3"
acc.insert()
# Rename account in parent company
update_account_number(acc.name, "Test Rename Sync Account", "1234")
# Check if renamed in children
self.assertTrue(frappe.db.exists("Account", {'account_name': "Test Rename Sync Account", "company": "_Test Company 4", "account_number": "1234"}))
self.assertTrue(frappe.db.exists("Account", {'account_name': "Test Rename Sync Account", "company": "_Test Company 5", "account_number": "1234"}))
frappe.delete_doc("Account", "1234 - Test Rename Sync Account - _TC3")
frappe.delete_doc("Account", "1234 - Test Rename Sync Account - _TC4")
frappe.delete_doc("Account", "1234 - Test Rename Sync Account - _TC5")
def test_child_company_account_rename_sync(self):
frappe.local.flags.pop("ignore_root_company_validation", None)
acc = frappe.new_doc("Account")
acc.account_name = "Test Group Account"
acc.parent_account = "Temporary Accounts - _TC3"
acc.is_group = 1
acc.company = "_Test Company 3"
acc.insert()
self.assertTrue(frappe.db.exists("Account", {'account_name': "Test Group Account", "company": "_Test Company 4"}))
self.assertTrue(frappe.db.exists("Account", {'account_name': "Test Group Account", "company": "_Test Company 5"}))
# Try renaming child company account
acc_tc_5 = frappe.db.get_value('Account', {'account_name': "Test Group Account", "company": "_Test Company 5"})
self.assertRaises(frappe.ValidationError, update_account_number, acc_tc_5, "Test Modified Account")
# Rename child company account with allow_account_creation_against_child_company enabled
frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 1)
update_account_number(acc_tc_5, "Test Modified Account")
self.assertTrue(frappe.db.exists("Account", {'name': "Test Modified Account - _TC5", "company": "_Test Company 5"}))
frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 0)
to_delete = ["Test Group Account - _TC3", "Test Group Account - _TC4", "Test Modified Account - _TC5"]
for doc in to_delete:
frappe.delete_doc("Account", doc)
def _make_test_records(verbose):
from frappe.test_runner import make_test_objects

View File

@ -104,7 +104,7 @@
"default": "1",
"fieldname": "unlink_advance_payment_on_cancelation_of_order",
"fieldtype": "Check",
"label": "Unlink Advance Payment on Cancelation of Order"
"label": "Unlink Advance Payment on Cancellation of Order"
},
{
"default": "1",
@ -223,9 +223,10 @@
],
"icon": "icon-cog",
"idx": 1,
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2020-08-03 20:13:26.043092",
"modified": "2020-10-07 14:58:50.325577",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

File diff suppressed because it is too large Load Diff

View File

@ -22,8 +22,12 @@ class JournalEntry(AccountsController):
return self.voucher_type
def validate(self):
if self.voucher_type == 'Opening Entry':
self.is_opening = 'Yes'
if not self.is_opening:
self.is_opening='No'
self.clearance_date = None
self.validate_party()

View File

@ -1,12 +1,14 @@
frappe.listview_settings['Payment Entry'] = {
onload: function(listview) {
listview.page.fields_dict.party_type.get_query = function() {
return {
"filters": {
"name": ["in", Object.keys(frappe.boot.party_account_types)],
}
if (listview.page.fields_dict.party_type) {
listview.page.fields_dict.party_type.get_query = function() {
return {
"filters": {
"name": ["in", Object.keys(frappe.boot.party_account_types)],
}
};
};
};
}
}
};

View File

@ -285,6 +285,71 @@ class TestPOSInvoice(unittest.TestCase):
after_redeem_lp_details = get_loyalty_program_details_with_points(inv.customer, company=inv.company, loyalty_program=inv.loyalty_program)
self.assertEqual(after_redeem_lp_details.loyalty_points, 9)
def test_merging_into_sales_invoice_with_discount(self):
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import merge_pos_invoices
frappe.db.sql("delete from `tabPOS Invoice`")
test_user, pos_profile = init_user_and_profile()
pos_inv = create_pos_invoice(rate=300, additional_discount_percentage=10, do_not_submit=1)
pos_inv.append('payments', {
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300
})
pos_inv.submit()
pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1)
pos_inv2.append('payments', {
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3200
})
pos_inv2.submit()
merge_pos_invoices()
pos_inv.load_from_db()
sales_invoice = frappe.get_doc("Sales Invoice", pos_inv.consolidated_invoice)
self.assertEqual(sales_invoice.grand_total, 3500)
def test_merging_into_sales_invoice_with_discount_and_inclusive_tax(self):
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import merge_pos_invoices
frappe.db.sql("delete from `tabPOS Invoice`")
test_user, pos_profile = init_user_and_profile()
pos_inv = create_pos_invoice(rate=300, do_not_submit=1)
pos_inv.append('payments', {
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300
})
pos_inv.append('taxes', {
"charge_type": "On Net Total",
"account_head": "_Test Account Service Tax - _TC",
"cost_center": "_Test Cost Center - _TC",
"description": "Service Tax",
"rate": 14,
'included_in_print_rate': 1
})
pos_inv.submit()
pos_inv2 = create_pos_invoice(rate=300, qty=2, do_not_submit=1)
pos_inv2.additional_discount_percentage = 10
pos_inv2.append('payments', {
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 540
})
pos_inv2.append('taxes', {
"charge_type": "On Net Total",
"account_head": "_Test Account Service Tax - _TC",
"cost_center": "_Test Cost Center - _TC",
"description": "Service Tax",
"rate": 14,
'included_in_print_rate': 1
})
pos_inv2.submit()
merge_pos_invoices()
pos_inv.load_from_db()
sales_invoice = frappe.get_doc("Sales Invoice", pos_inv.consolidated_invoice)
self.assertEqual(sales_invoice.rounded_total, 840)
def create_pos_invoice(**args):
args = frappe._dict(args)
@ -294,6 +359,7 @@ def create_pos_invoice(**args):
pos_profile.save()
pos_inv = frappe.new_doc("POS Invoice")
pos_inv.update(args)
pos_inv.update_stock = 1
pos_inv.is_pos = 1
pos_inv.pos_profile = args.pos_profile or pos_profile.name

View File

@ -96,17 +96,28 @@ class POSInvoiceMergeLog(Document):
loyalty_amount_sum += doc.loyalty_amount
for item in doc.get('items'):
items.append(item)
found = False
for i in items:
if (i.item_code == item.item_code and not i.serial_no and not i.batch_no and
i.uom == item.uom and i.net_rate == item.net_rate):
found = True
i.qty = i.qty + item.qty
if not found:
item.rate = item.net_rate
items.append(item)
for tax in doc.get('taxes'):
found = False
for t in taxes:
if t.account_head == tax.account_head and t.cost_center == tax.cost_center and t.rate == tax.rate:
t.tax_amount = flt(t.tax_amount) + flt(tax.tax_amount)
t.base_tax_amount = flt(t.base_tax_amount) + flt(tax.base_tax_amount)
if t.account_head == tax.account_head and t.cost_center == tax.cost_center:
t.tax_amount = flt(t.tax_amount) + flt(tax.tax_amount_after_discount_amount)
t.base_tax_amount = flt(t.base_tax_amount) + flt(tax.base_tax_amount_after_discount_amount)
found = True
if not found:
tax.charge_type = 'Actual'
tax.included_in_print_rate = 0
tax.tax_amount = tax.tax_amount_after_discount_amount
tax.base_tax_amount = tax.base_tax_amount_after_discount_amount
taxes.append(tax)
for payment in doc.get('payments'):
@ -127,6 +138,8 @@ class POSInvoiceMergeLog(Document):
invoice.set('items', items)
invoice.set('payments', payments)
invoice.set('taxes', taxes)
invoice.additional_discount_percentage = 0
invoice.discount_amount = 0.0
return invoice

View File

@ -15,15 +15,6 @@ frappe.ui.form.on("POS Profile", "onload", function(frm) {
erpnext.queries.setup_queries(frm, "Warehouse", function() {
return erpnext.queries.warehouse(frm.doc);
});
frm.call({
method: "erpnext.accounts.doctype.pos_profile.pos_profile.get_series",
callback: function(r) {
if(!r.exc) {
set_field_options("naming_series", r.message);
}
}
});
});
frappe.ui.form.on('POS Profile', {

View File

@ -8,7 +8,6 @@
"field_order": [
"disabled",
"section_break_2",
"naming_series",
"customer",
"company",
"country",
@ -59,17 +58,6 @@
"fieldname": "section_break_2",
"fieldtype": "Section Break"
},
{
"fieldname": "naming_series",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
"options": "[Select]",
"reqd": 1
},
{
"fieldname": "customer",
"fieldtype": "Link",
@ -323,7 +311,7 @@
"icon": "icon-cog",
"idx": 1,
"links": [],
"modified": "2020-06-29 12:20:30.977272",
"modified": "2020-10-01 17:29:27.759088",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Profile",
@ -350,4 +338,4 @@
],
"sort_field": "modified",
"sort_order": "DESC"
}
}

View File

@ -109,10 +109,6 @@ def get_child_nodes(group_type, root):
return frappe.db.sql(""" Select name, lft, rgt from `tab{tab}` where
lft >= {lft} and rgt <= {rgt} order by lft""".format(tab=group_type, lft=lft, rgt=rgt), as_dict=1)
@frappe.whitelist()
def get_series():
return frappe.get_meta("POS Invoice").get_field("naming_series").options or "s"
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):

View File

@ -1,4 +1,5 @@
{
"actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:title",
@ -71,6 +72,7 @@
"section_break_13",
"threshold_percentage",
"priority",
"condition",
"column_break_66",
"apply_multiple_pricing_rules",
"apply_discount_on_rate",
@ -550,11 +552,18 @@
"fieldtype": "Link",
"label": "Promotional Scheme",
"options": "Promotional Scheme"
},
{
"description": "Simple Python Expression, Example: territory != 'All Territories'",
"fieldname": "condition",
"fieldtype": "Code",
"label": "Condition"
}
],
"icon": "fa fa-gift",
"idx": 1,
"modified": "2019-12-18 17:29:22.957077",
"links": [],
"modified": "2020-08-26 12:24:44.740734",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Pricing Rule",

View File

@ -6,9 +6,10 @@ from __future__ import unicode_literals
import frappe
import json
import copy
import re
from frappe import throw, _
from frappe.utils import flt, cint, getdate
from frappe.model.document import Document
from six import string_types
@ -30,6 +31,7 @@ class PricingRule(Document):
self.validate_max_discount()
self.validate_price_list_with_currency()
self.validate_dates()
self.validate_condition()
if not self.margin_type: self.margin_rate_or_amount = 0.0
@ -140,6 +142,10 @@ class PricingRule(Document):
if self.valid_from and self.valid_upto and getdate(self.valid_from) > getdate(self.valid_upto):
frappe.throw(_("Valid from date must be less than valid upto date"))
def validate_condition(self):
if self.condition and ("=" in self.condition) and re.match("""[\w\.:_]+\s*={1}\s*[\w\.@'"]+""", self.condition):
frappe.throw(_("Invalid condition expression"))
#--------------------------------------------------------------------------------
@frappe.whitelist()

View File

@ -429,7 +429,34 @@ class TestPricingRule(unittest.TestCase):
details = get_item_details(args)
self.assertTrue(details)
def test_pricing_rule_for_condition(self):
frappe.delete_doc_if_exists("Pricing Rule", "_Test Pricing Rule")
make_pricing_rule(selling=1, margin_type="Percentage", \
condition="customer=='_Test Customer 1' and is_return==0", discount_percentage=10)
# Incorrect Customer and Correct is_return value
si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 2", is_return=0)
si.items[0].price_list_rate = 1000
si.submit()
item = si.items[0]
self.assertEquals(item.rate, 100)
# Correct Customer and Incorrect is_return value
si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 1", is_return=1, qty=-1)
si.items[0].price_list_rate = 1000
si.submit()
item = si.items[0]
self.assertEquals(item.rate, 100)
# Correct Customer and correct is_return value
si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 1", is_return=0)
si.items[0].price_list_rate = 1000
si.submit()
item = si.items[0]
self.assertEquals(item.rate, 900)
def make_pricing_rule(**args):
args = frappe._dict(args)
@ -448,7 +475,8 @@ def make_pricing_rule(**args):
"discount_percentage": args.discount_percentage or 0.0,
"rate": args.rate or 0.0,
"margin_type": args.margin_type,
"margin_rate_or_amount": args.margin_rate_or_amount or 0.0
"margin_rate_or_amount": args.margin_rate_or_amount or 0.0,
"condition": args.condition or ''
})
apply_on = doc.apply_on.replace(' ', '_').lower()

View File

@ -37,6 +37,8 @@ def get_pricing_rules(args, doc=None):
rules = []
pricing_rules = filter_pricing_rule_based_on_condition(pricing_rules, doc)
if not pricing_rules: return []
if apply_multiple_pricing_rules(pricing_rules):
@ -51,6 +53,23 @@ def get_pricing_rules(args, doc=None):
return rules
def filter_pricing_rule_based_on_condition(pricing_rules, doc=None):
filtered_pricing_rules = []
if doc:
for pricing_rule in pricing_rules:
if pricing_rule.condition:
try:
if frappe.safe_eval(pricing_rule.condition, None, doc.as_dict()):
filtered_pricing_rules.append(pricing_rule)
except:
pass
else:
filtered_pricing_rules.append(pricing_rule)
else:
filtered_pricing_rules = pricing_rules
return filtered_pricing_rules
def _get_pricing_rules(apply_on, args, values):
apply_on_field = frappe.scrub(apply_on)

View File

@ -711,7 +711,8 @@ class PurchaseInvoice(BuyingController):
item.item_tax_amount / self.conversion_rate)
}, item=item))
else:
cwip_account = get_asset_account("capital_work_in_progress_account", company = self.company)
cwip_account = get_asset_account("capital_work_in_progress_account",
asset_category=item.asset_category,company=self.company)
cwip_account_currency = get_account_currency(cwip_account)
gl_entries.append(self.get_gl_dict({

View File

@ -1002,7 +1002,8 @@ def make_purchase_invoice(**args):
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"project": args.project,
"rejected_warehouse": args.rejected_warehouse or "",
"rejected_serial_no": args.rejected_serial_no or ""
"rejected_serial_no": args.rejected_serial_no or "",
"asset_location": args.location or ""
})
if args.get_taxes_and_charges:

View File

@ -1825,7 +1825,7 @@
"fieldtype": "Table",
"hide_days": 1,
"hide_seconds": 1,
"label": "Sales Team1",
"label": "Sales Contributions and Incentives",
"oldfieldname": "sales_team",
"oldfieldtype": "Table",
"options": "Sales Team",
@ -1926,6 +1926,7 @@
},
{
"default": "0",
"depends_on": "eval:(doc.is_pos && doc.is_consolidated)",
"fieldname": "is_consolidated",
"fieldtype": "Check",
"label": "Is Consolidated",
@ -1946,7 +1947,7 @@
"idx": 181,
"is_submittable": 1,
"links": [],
"modified": "2020-08-27 01:56:28.532140",
"modified": "2020-10-09 15:59:57.544736",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@ -428,7 +428,7 @@ class SalesInvoice(SellingController):
if pos.get('account_for_change_amount'):
self.account_for_change_amount = pos.get('account_for_change_amount')
for fieldname in ('naming_series', 'currency', 'letter_head', 'tc_name',
for fieldname in ('currency', 'letter_head', 'tc_name',
'company', 'select_print_heading', 'write_off_account', 'taxes_and_charges',
'write_off_cost_center', 'apply_discount_on', 'cost_center'):
if (not for_validate) or (for_validate and not self.get(fieldname)):

View File

@ -13,8 +13,7 @@ def get_data():
'Auto Repeat': 'reference_document',
},
'internal_links': {
'Sales Order': ['items', 'sales_order'],
'Delivery Note': ['items', 'delivery_note']
'Sales Order': ['items', 'sales_order']
},
'transactions': [
{

View File

@ -6,6 +6,8 @@ from __future__ import unicode_literals
import frappe
import unittest
from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup, IncorrectSupplierType, ConflictingTaxRule, get_tax_template
from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity
from erpnext.crm.doctype.opportunity.opportunity import make_quotation
test_records = frappe.get_test_records('Tax Rule')
@ -144,6 +146,23 @@ class TestTaxRule(unittest.TestCase):
self.assertEqual(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
"_Test Sales Taxes and Charges Template 1 - _TC")
def test_taxes_fetch_via_tax_rule(self):
make_tax_rule(customer= "_Test Customer", billing_city = "_Test City",
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)
# create opportunity for customer
opportunity = make_opportunity(with_items=1)
# make quotation from opportunity
quotation = make_quotation(opportunity.name)
quotation.save()
self.assertEqual(quotation.taxes_and_charges, "_Test Sales Taxes and Charges Template - _TC")
# Check if accounts heads and rate fetched are also fetched from tax template or not
self.assertTrue(len(quotation.taxes) > 0)
def make_tax_rule(**args):
args = frappe._dict(args)

View File

@ -106,6 +106,7 @@ def get_tds_amount(suppliers, net_total, company, tax_details, fiscal_year_detai
from `tabGL Entry`
where company = %s and
party in %s and fiscal_year=%s and credit > 0
and is_opening = 'No'
""", (company, tuple(suppliers), fiscal_year), as_dict=1)
vouchers = [d.voucher_no for d in entries]
@ -192,6 +193,7 @@ def get_advance_vouchers(suppliers, fiscal_year=None, company=None, from_date=No
select distinct voucher_no
from `tabGL Entry`
where party in %s and %s and debit > 0
and is_opening = 'No'
""", (tuple(suppliers), condition)) or []
def get_debit_note_amount(suppliers, year_start_date, year_end_date, company=None):

View File

@ -0,0 +1,76 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */
frappe.query_reports["POS Register"] = {
"filters": [
{
"fieldname":"company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("Company"),
"reqd": 1
},
{
"fieldname":"from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
"reqd": 1,
"width": "60px"
},
{
"fieldname":"to_date",
"label": __("To Date"),
"fieldtype": "Date",
"default": frappe.datetime.get_today(),
"reqd": 1,
"width": "60px"
},
{
"fieldname":"pos_profile",
"label": __("POS Profile"),
"fieldtype": "Link",
"options": "POS Profile"
},
{
"fieldname":"cashier",
"label": __("Cashier"),
"fieldtype": "Link",
"options": "User"
},
{
"fieldname":"customer",
"label": __("Customer"),
"fieldtype": "Link",
"options": "Customer"
},
{
"fieldname":"mode_of_payment",
"label": __("Payment Method"),
"fieldtype": "Link",
"options": "Mode of Payment"
},
{
"fieldname":"group_by",
"label": __("Group by"),
"fieldtype": "Select",
"options": ["", "POS Profile", "Cashier", "Payment Method", "Customer"],
"default": "POS Profile"
},
{
"fieldname":"is_return",
"label": __("Is Return"),
"fieldtype": "Check"
},
],
"formatter": function(value, row, column, data, default_formatter) {
value = default_formatter(value, row, column, data);
if (data && data.bold) {
value = value.bold();
}
return value;
}
};

View File

@ -0,0 +1,30 @@
{
"add_total_row": 0,
"columns": [],
"creation": "2020-09-10 19:25:03.766871",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 0,
"is_standard": "Yes",
"json": "{}",
"modified": "2020-09-10 19:25:15.851331",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Register",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "POS Invoice",
"report_name": "POS Register",
"report_type": "Script Report",
"roles": [
{
"role": "Accounts Manager"
},
{
"role": "Accounts User"
}
]
}

View File

@ -0,0 +1,222 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _, _dict
from erpnext import get_company_currency, get_default_company
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
def execute(filters=None):
if not filters:
return [], []
validate_filters(filters)
columns = get_columns(filters)
group_by_field = get_group_by_field(filters.get("group_by"))
pos_entries = get_pos_entries(filters, group_by_field)
if group_by_field != "mode_of_payment":
concat_mode_of_payments(pos_entries)
# return only entries if group by is unselected
if not group_by_field:
return columns, pos_entries
# handle grouping
invoice_map, grouped_data = {}, []
for d in pos_entries:
invoice_map.setdefault(d[group_by_field], []).append(d)
for key in invoice_map:
invoices = invoice_map[key]
grouped_data += invoices
add_subtotal_row(grouped_data, invoices, group_by_field, key)
# move group by column to first position
column_index = next((index for (index, d) in enumerate(columns) if d["fieldname"] == group_by_field), None)
columns.insert(0, columns.pop(column_index))
return columns, grouped_data
def get_pos_entries(filters, group_by_field):
conditions = get_conditions(filters)
order_by = "p.posting_date"
select_mop_field, from_sales_invoice_payment, group_by_mop_condition = "", "", ""
if group_by_field == "mode_of_payment":
select_mop_field = ", sip.mode_of_payment"
from_sales_invoice_payment = ", `tabSales Invoice Payment` sip"
group_by_mop_condition = "sip.parent = p.name AND ifnull(sip.base_amount, 0) != 0 AND"
order_by += ", sip.mode_of_payment"
elif group_by_field:
order_by += ", p.{}".format(group_by_field)
return frappe.db.sql(
"""
SELECT
p.posting_date, p.name as pos_invoice, p.pos_profile,
p.owner, p.base_grand_total as grand_total, p.base_paid_amount as paid_amount,
p.customer, p.is_return {select_mop_field}
FROM
`tabPOS Invoice` p {from_sales_invoice_payment}
WHERE
{group_by_mop_condition}
{conditions}
ORDER BY
{order_by}
""".format(
select_mop_field=select_mop_field,
from_sales_invoice_payment=from_sales_invoice_payment,
group_by_mop_condition=group_by_mop_condition,
conditions=conditions,
order_by=order_by
), filters, as_dict=1)
def concat_mode_of_payments(pos_entries):
mode_of_payments = get_mode_of_payments(set([d.pos_invoice for d in pos_entries]))
for entry in pos_entries:
if mode_of_payments.get(entry.pos_invoice):
entry.mode_of_payment = ", ".join(mode_of_payments.get(entry.pos_invoice, []))
def add_subtotal_row(data, group_invoices, group_by_field, group_by_value):
grand_total = sum([d.grand_total for d in group_invoices])
paid_amount = sum([d.paid_amount for d in group_invoices])
data.append({
group_by_field: group_by_value,
"grand_total": grand_total,
"paid_amount": paid_amount,
"bold": 1
})
data.append({})
def validate_filters(filters):
if not filters.get("company"):
frappe.throw(_("{0} is mandatory").format(_("Company")))
if not filters.get("from_date") and not filters.get("to_date"):
frappe.throw(_("{0} and {1} are mandatory").format(frappe.bold(_("From Date")), frappe.bold(_("To Date"))))
if filters.from_date > filters.to_date:
frappe.throw(_("From Date must be before To Date"))
if (filters.get("pos_profile") and filters.get("group_by") == _('POS Profile')):
frappe.throw(_("Can not filter based on POS Profile, if grouped by POS Profile"))
if (filters.get("customer") and filters.get("group_by") == _('Customer')):
frappe.throw(_("Can not filter based on Customer, if grouped by Customer"))
if (filters.get("owner") and filters.get("group_by") == _('Cashier')):
frappe.throw(_("Can not filter based on Cashier, if grouped by Cashier"))
if (filters.get("mode_of_payment") and filters.get("group_by") == _('Payment Method')):
frappe.throw(_("Can not filter based on Payment Method, if grouped by Payment Method"))
def get_conditions(filters):
conditions = "company = %(company)s AND posting_date >= %(from_date)s AND posting_date <= %(to_date)s".format(
company=filters.get("company"),
from_date=filters.get("from_date"),
to_date=filters.get("to_date"))
if filters.get("pos_profile"):
conditions += " AND pos_profile = %(pos_profile)s".format(pos_profile=filters.get("pos_profile"))
if filters.get("owner"):
conditions += " AND owner = %(owner)s".format(owner=filters.get("owner"))
if filters.get("customer"):
conditions += " AND customer = %(customer)s".format(customer=filters.get("customer"))
if filters.get("is_return"):
conditions += " AND is_return = %(is_return)s".format(is_return=filters.get("is_return"))
if filters.get("mode_of_payment"):
conditions += """
AND EXISTS(
SELECT name FROM `tabSales Invoice Payment` sip
WHERE parent=p.name AND ifnull(sip.mode_of_payment, '') = %(mode_of_payment)s
)"""
return conditions
def get_group_by_field(group_by):
group_by_field = ""
if group_by == "POS Profile":
group_by_field = "pos_profile"
elif group_by == "Cashier":
group_by_field = "owner"
elif group_by == "Customer":
group_by_field = "customer"
elif group_by == "Payment Method":
group_by_field = "mode_of_payment"
return group_by_field
def get_columns(filters):
columns = [
{
"label": _("Posting Date"),
"fieldname": "posting_date",
"fieldtype": "Date",
"width": 90
},
{
"label": _("POS Invoice"),
"fieldname": "pos_invoice",
"fieldtype": "Link",
"options": "POS Invoice",
"width": 120
},
{
"label": _("Customer"),
"fieldname": "customer",
"fieldtype": "Link",
"options": "Customer",
"width": 120
},
{
"label": _("POS Profile"),
"fieldname": "pos_profile",
"fieldtype": "Link",
"options": "POS Profile",
"width": 160
},
{
"label": _("Cashier"),
"fieldname": "owner",
"fieldtype": "Link",
"options": "User",
"width": 140
},
{
"label": _("Grand Total"),
"fieldname": "grand_total",
"fieldtype": "Currency",
"options": "company:currency",
"width": 120
},
{
"label": _("Paid Amount"),
"fieldname": "paid_amount",
"fieldtype": "Currency",
"options": "company:currency",
"width": 120
},
{
"label": _("Payment Method"),
"fieldname": "mode_of_payment",
"fieldtype": "Data",
"width": 150
},
{
"label": _("Is Return"),
"fieldname": "is_return",
"fieldtype": "Data",
"width": 80
},
]
return columns

View File

@ -32,12 +32,12 @@ def execute(filters=None):
chart = get_chart_data(filters, columns, income, expense, net_profit_loss)
default_currency = frappe.get_cached_value('Company', filters.company, "default_currency")
report_summary = get_report_summary(period_list, filters.periodicity, income, expense, net_profit_loss, default_currency)
currency = filters.presentation_currency or frappe.get_cached_value('Company', filters.company, "default_currency")
report_summary = get_report_summary(period_list, filters.periodicity, income, expense, net_profit_loss, currency)
return columns, data, None, chart, report_summary
def get_report_summary(period_list, periodicity, income, expense, net_profit_loss, default_currency, consolidated=False):
def get_report_summary(period_list, periodicity, income, expense, net_profit_loss, currency, consolidated=False):
net_income, net_expense, net_profit = 0.0, 0.0, 0.0
for period in period_list:
@ -64,19 +64,19 @@ def get_report_summary(period_list, periodicity, income, expense, net_profit_los
"indicator": "Green" if net_profit > 0 else "Red",
"label": profit_label,
"datatype": "Currency",
"currency": net_profit_loss.get("currency") if net_profit_loss else default_currency
"currency": currency
},
{
"value": net_income,
"label": income_label,
"datatype": "Currency",
"currency": income[-1].get('currency') if income else default_currency
"currency": currency
},
{
"value": net_expense,
"label": expense_label,
"datatype": "Currency",
"currency": expense[-1].get('currency') if expense else default_currency
"currency": currency
}
]
@ -143,4 +143,4 @@ def get_chart_data(filters, columns, income, expense, net_profit_loss):
chart["fieldtype"] = "Currency"
return chart
return chart

View File

@ -72,6 +72,12 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"fieldtype": "Link",
"options": "Finance Book",
},
{
"fieldname": "presentation_currency",
"label": __("Currency"),
"fieldtype": "Select",
"options": erpnext.get_presentation_currency_list()
},
{
"fieldname": "with_period_closing_entry",
"label": __("Period Closing Entry"),

View File

@ -56,7 +56,7 @@ def get_data(filters):
accounts = frappe.db.sql("""select name, account_number, parent_account, account_name, root_type, report_type, lft, rgt
from `tabAccount` where company=%s order by lft""", filters.company, as_dict=True)
company_currency = erpnext.get_company_currency(filters.company)
company_currency = filters.presentation_currency or erpnext.get_company_currency(filters.company)
if not accounts:
return None

View File

@ -683,6 +683,7 @@ def get_outstanding_invoices(party_type, party, account, condition=None, filters
where
party_type = %(party_type)s and party = %(party)s
and account = %(account)s and {dr_or_cr} > 0
and is_cancelled=0
{condition}
and ((voucher_type = 'Journal Entry'
and (against_voucher = '' or against_voucher is null))
@ -705,6 +706,7 @@ def get_outstanding_invoices(party_type, party, account, condition=None, filters
and account = %(account)s
and {payment_dr_or_cr} > 0
and against_voucher is not null and against_voucher != ''
and is_cancelled=0
group by against_voucher_type, against_voucher
""".format(payment_dr_or_cr=payment_dr_or_cr), {
"party_type": party_type,

View File

@ -131,7 +131,7 @@ class Asset(AccountsController):
def validate_gross_and_purchase_amount(self):
if self.is_existing_asset: return
if self.gross_purchase_amount and self.gross_purchase_amount != self.purchase_receipt_amount:
frappe.throw(_("Gross Purchase Amount should be {} to purchase amount of one single Asset. {}\
Please do not book expense of multiple assets against one single Asset.")
@ -466,50 +466,63 @@ class Asset(AccountsController):
def validate_make_gl_entry(self):
purchase_document = self.get_purchase_document()
asset_bought_with_invoice = purchase_document == self.purchase_invoice
fixed_asset_account, cwip_account = self.get_asset_accounts()
cwip_enabled = is_cwip_accounting_enabled(self.asset_category)
# check if expense already has been booked in case of cwip was enabled after purchasing asset
expense_booked = False
cwip_booked = False
if asset_bought_with_invoice:
expense_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""",
(purchase_document, fixed_asset_account), as_dict=1)
else:
cwip_booked = frappe.db.sql("""SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s""",
(purchase_document, cwip_account), as_dict=1)
if cwip_enabled and (expense_booked or not cwip_booked):
# if expense has already booked from invoice or cwip is booked from receipt
if not purchase_document:
return False
elif not cwip_enabled and (not expense_booked or cwip_booked):
# if cwip is disabled but expense hasn't been booked yet
return True
elif cwip_enabled:
# default condition
return True
asset_bought_with_invoice = (purchase_document == self.purchase_invoice)
fixed_asset_account = self.get_fixed_asset_account()
cwip_enabled = is_cwip_accounting_enabled(self.asset_category)
cwip_account = self.get_cwip_account(cwip_enabled=cwip_enabled)
query = """SELECT name FROM `tabGL Entry` WHERE voucher_no = %s and account = %s"""
if asset_bought_with_invoice:
# with invoice purchase either expense or cwip has been booked
expense_booked = frappe.db.sql(query, (purchase_document, fixed_asset_account), as_dict=1)
if expense_booked:
# if expense is already booked from invoice then do not make gl entries regardless of cwip enabled/disabled
return False
cwip_booked = frappe.db.sql(query, (purchase_document, cwip_account), as_dict=1)
if cwip_booked:
# if cwip is booked from invoice then make gl entries regardless of cwip enabled/disabled
return True
else:
# with receipt purchase either cwip has been booked or no entries have been made
if not cwip_account:
# if cwip account isn't available do not make gl entries
return False
cwip_booked = frappe.db.sql(query, (purchase_document, cwip_account), as_dict=1)
# if cwip is not booked from receipt then do not make gl entries
# if cwip is booked from receipt then make gl entries
return cwip_booked
def get_purchase_document(self):
asset_bought_with_invoice = self.purchase_invoice and frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')
purchase_document = self.purchase_invoice if asset_bought_with_invoice else self.purchase_receipt
return purchase_document
def get_fixed_asset_account(self):
return get_asset_category_account('fixed_asset_account', None, self.name, None, self.asset_category, self.company)
def get_cwip_account(self, cwip_enabled=False):
cwip_account = None
try:
cwip_account = get_asset_account("capital_work_in_progress_account", self.name, self.asset_category, self.company)
except:
# if no cwip account found in category or company and "cwip is enabled" then raise else silently pass
if cwip_enabled:
raise
def get_asset_accounts(self):
fixed_asset_account = get_asset_category_account('fixed_asset_account', asset=self.name,
asset_category = self.asset_category, company = self.company)
cwip_account = get_asset_account("capital_work_in_progress_account",
self.name, self.asset_category, self.company)
return fixed_asset_account, cwip_account
return cwip_account
def make_gl_entries(self):
gl_entries = []
purchase_document = self.get_purchase_document()
fixed_asset_account, cwip_account = self.get_asset_accounts()
fixed_asset_account, cwip_account = self.get_fixed_asset_account(), self.get_cwip_account()
if (purchase_document and self.purchase_receipt_amount and self.available_for_use_date <= nowdate()):
@ -561,14 +574,18 @@ class Asset(AccountsController):
return 100 * (1 - flt(depreciation_rate, float_precision))
def update_maintenance_status():
assets = frappe.get_all('Asset', filters = {'docstatus': 1, 'maintenance_required': 1})
assets = frappe.get_all(
"Asset", filters={"docstatus": 1, "maintenance_required": 1}
)
for asset in assets:
asset = frappe.get_doc("Asset", asset.name)
if frappe.db.exists('Asset Maintenance Task', {'parent': asset.name, 'next_due_date': today()}):
asset.set_status('In Maintenance')
if frappe.db.exists('Asset Repair', {'asset_name': asset.name, 'repair_status': 'Pending'}):
asset.set_status('Out of Order')
if frappe.db.exists("Asset Repair", {"asset_name": asset.name, "repair_status": "Pending"}):
asset.set_status("Out of Order")
elif frappe.db.exists("Asset Maintenance Task", {"parent": asset.name, "next_due_date": today()}):
asset.set_status("In Maintenance")
else:
asset.set_status()
def make_post_gl_entry():

View File

@ -9,6 +9,7 @@ from frappe.utils import cstr, nowdate, getdate, flt, get_last_day, add_days, ad
from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset
from erpnext.assets.doctype.asset.asset import make_sales_invoice
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice as make_invoice
class TestAsset(unittest.TestCase):
@ -558,81 +559,6 @@ class TestAsset(unittest.TestCase):
self.assertEqual(gle, expected_gle)
def test_gle_with_cwip_toggling(self):
# TEST: purchase an asset with cwip enabled and then disable cwip and try submitting the asset
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
pr = make_purchase_receipt(item_code="Macbook Pro",
qty=1, rate=5000, do_not_submit=True, location="Test Location")
pr.set('taxes', [{
'category': 'Total',
'add_deduct_tax': 'Add',
'charge_type': 'On Net Total',
'account_head': '_Test Account Service Tax - _TC',
'description': '_Test Account Service Tax',
'cost_center': 'Main - _TC',
'rate': 5.0
}, {
'category': 'Valuation and Total',
'add_deduct_tax': 'Add',
'charge_type': 'On Net Total',
'account_head': '_Test Account Shipping Charges - _TC',
'description': '_Test Account Shipping Charges',
'cost_center': 'Main - _TC',
'rate': 5.0
}])
pr.submit()
expected_gle = (
("Asset Received But Not Billed - _TC", 0.0, 5250.0),
("CWIP Account - _TC", 5250.0, 0.0)
)
pr_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
where voucher_type='Purchase Receipt' and voucher_no = %s
order by account""", pr.name)
self.assertEqual(pr_gle, expected_gle)
pi = make_invoice(pr.name)
pi.submit()
expected_gle = (
("_Test Account Service Tax - _TC", 250.0, 0.0),
("_Test Account Shipping Charges - _TC", 250.0, 0.0),
("Asset Received But Not Billed - _TC", 5250.0, 0.0),
("Creditors - _TC", 0.0, 5500.0),
("Expenses Included In Asset Valuation - _TC", 0.0, 250.0),
)
pi_gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
where voucher_type='Purchase Invoice' and voucher_no = %s
order by account""", pi.name)
self.assertEqual(pi_gle, expected_gle)
asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
asset_doc = frappe.get_doc('Asset', asset)
month_end_date = get_last_day(nowdate())
asset_doc.available_for_use_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15)
self.assertEqual(asset_doc.gross_purchase_amount, 5250.0)
asset_doc.append("finance_books", {
"expected_value_after_useful_life": 200,
"depreciation_method": "Straight Line",
"total_number_of_depreciations": 3,
"frequency_of_depreciation": 10,
"depreciation_start_date": month_end_date
})
# disable cwip and try submitting
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
asset_doc.submit()
# asset should have gl entries even if cwip is disabled
expected_gle = (
("_Test Fixed Asset - _TC", 5250.0, 0.0),
("CWIP Account - _TC", 0.0, 5250.0)
)
gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry`
where voucher_type='Asset' and voucher_no = %s
order by account""", asset_doc.name)
self.assertEqual(gle, expected_gle)
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
def test_expense_head(self):
pr = make_purchase_receipt(item_code="Macbook Pro",
qty=2, rate=200000.0, location="Test Location")
@ -640,6 +566,74 @@ class TestAsset(unittest.TestCase):
doc = make_invoice(pr.name)
self.assertEquals('Asset Received But Not Billed - _TC', doc.items[0].expense_account)
def test_asset_cwip_toggling_cases(self):
cwip = frappe.db.get_value("Asset Category", "Computers", "enable_cwip_accounting")
name = frappe.db.get_value("Asset Category Account", filters={"parent": "Computers"}, fieldname=["name"])
cwip_acc = "CWIP Account - _TC"
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", "")
frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", "")
# case 0 -- PI with cwip disable, Asset with cwip disabled, No cwip account set
pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
asset_doc = frappe.get_doc('Asset', asset)
asset_doc.available_for_use_date = nowdate()
asset_doc.calculate_depreciation = 0
asset_doc.submit()
gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
self.assertFalse(gle)
# case 1 -- PR with cwip disabled, Asset with cwip enabled
pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location")
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc)
asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
asset_doc = frappe.get_doc('Asset', asset)
asset_doc.available_for_use_date = nowdate()
asset_doc.calculate_depreciation = 0
asset_doc.submit()
gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
self.assertFalse(gle)
# case 2 -- PR with cwip enabled, Asset with cwip disabled
pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location")
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name, 'docstatus': 0}, 'name')
asset_doc = frappe.get_doc('Asset', asset)
asset_doc.available_for_use_date = nowdate()
asset_doc.calculate_depreciation = 0
asset_doc.submit()
gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
self.assertTrue(gle)
# case 3 -- PI with cwip disabled, Asset with cwip enabled
pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 1)
asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
asset_doc = frappe.get_doc('Asset', asset)
asset_doc.available_for_use_date = nowdate()
asset_doc.calculate_depreciation = 0
asset_doc.submit()
gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
self.assertFalse(gle)
# case 4 -- PI with cwip enabled, Asset with cwip disabled
pi = make_purchase_invoice(item_code="Macbook Pro", qty=1, rate=200000.0, location="Test Location", update_stock=1)
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", 0)
asset = frappe.db.get_value('Asset', {'purchase_invoice': pi.name, 'docstatus': 0}, 'name')
asset_doc = frappe.get_doc('Asset', asset)
asset_doc.available_for_use_date = nowdate()
asset_doc.calculate_depreciation = 0
asset_doc.submit()
gle = frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Asset' and voucher_no = %s""", asset_doc.name)
self.assertTrue(gle)
frappe.db.set_value("Asset Category", "Computers", "enable_cwip_accounting", cwip)
frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc)
frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", cwip_acc)
def create_asset_data():
if not frappe.db.exists("Asset Category", "Computers"):

View File

@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import cint
from frappe.utils import cint, get_link_to_form
from frappe.model.document import Document
class AssetCategory(Document):
@ -13,6 +13,7 @@ class AssetCategory(Document):
self.validate_finance_books()
self.validate_account_types()
self.validate_account_currency()
self.valide_cwip_account()
def validate_finance_books(self):
for d in self.finance_books:
@ -58,6 +59,21 @@ class AssetCategory(Document):
frappe.throw(_("Row #{}: {} of {} should be {}. Please modify the account or select a different account.")
.format(d.idx, frappe.unscrub(key_to_match), frappe.bold(selected_account), frappe.bold(expected_key_type)),
title=_("Invalid Account"))
def valide_cwip_account(self):
if self.enable_cwip_accounting:
missing_cwip_accounts_for_company = []
for d in self.accounts:
if (not d.capital_work_in_progress_account and
not frappe.db.get_value("Company", d.company_name, "capital_work_in_progress_account")):
missing_cwip_accounts_for_company.append(get_link_to_form("Company", d.company_name))
if missing_cwip_accounts_for_company:
msg = _("""To enable Capital Work in Progress Accounting, """)
msg += _("""you must select Capital Work in Progress Account in accounts table""")
msg += "<br><br>"
msg += _("You can also set default CWIP account in Company {}").format(", ".join(missing_cwip_accounts_for_company))
frappe.throw(msg, title=_("Missing Account"))
@frappe.whitelist()

View File

@ -26,4 +26,22 @@ class TestAssetCategory(unittest.TestCase):
asset_category.insert()
except frappe.DuplicateEntryError:
pass
def test_cwip_accounting(self):
company_cwip_acc = frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account")
frappe.db.set_value("Company", "_Test Company", "capital_work_in_progress_account", "")
asset_category = frappe.new_doc("Asset Category")
asset_category.asset_category_name = "Computers"
asset_category.enable_cwip_accounting = 1
asset_category.total_number_of_depreciations = 3
asset_category.frequency_of_depreciation = 3
asset_category.append("accounts", {
"company_name": "_Test Company",
"fixed_asset_account": "_Test Fixed Asset - _TC",
"accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
"depreciation_expense_account": "_Test Depreciations - _TC"
})
self.assertRaises(frappe.ValidationError, asset_category.insert)

View File

@ -1084,7 +1084,7 @@
"idx": 105,
"is_submittable": 1,
"links": [],
"modified": "2020-09-14 14:36:12.418690",
"modified": "2020-10-07 14:31:57.661221",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
@ -1130,11 +1130,11 @@
"write": 1
}
],
"search_fields": "status, transaction_date, supplier,grand_total",
"search_fields": "status, transaction_date, supplier, grand_total",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "supplier",
"title_field": "supplier",
"title_field": "supplier_name",
"track_changes": 1
}

View File

@ -179,7 +179,7 @@ frappe.ui.form.on("Request for Quotation",{
dialog.hide();
return frappe.call({
type: "GET",
method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.make_supplier_quotation",
method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.make_supplier_quotation_from_rfq",
args: {
"source_name": doc.name,
"for_supplier": args.supplier

View File

@ -214,14 +214,14 @@ def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters):
and `tabDynamic Link`.link_name like %(txt)s) and `tabContact`.name = `tabDynamic Link`.parent
limit %(start)s, %(page_len)s""", {"start": start, "page_len":page_len, "txt": "%%%s%%" % txt, "name": filters.get('supplier')})
# This method is used to make supplier quotation from material request form.
@frappe.whitelist()
def make_supplier_quotation(source_name, for_supplier, target_doc=None):
def make_supplier_quotation_from_rfq(source_name, target_doc=None, for_supplier=None):
def postprocess(source, target_doc):
target_doc.supplier = for_supplier
args = get_party_details(for_supplier, party_type="Supplier", ignore_permissions=True)
target_doc.currency = args.currency or get_party_account_currency('Supplier', for_supplier, source.company)
target_doc.buying_price_list = args.buying_price_list or frappe.db.get_value('Buying Settings', None, 'buying_price_list')
if for_supplier:
target_doc.supplier = for_supplier
args = get_party_details(for_supplier, party_type="Supplier", ignore_permissions=True)
target_doc.currency = args.currency or get_party_account_currency('Supplier', for_supplier, source.company)
target_doc.buying_price_list = args.buying_price_list or frappe.db.get_value('Buying Settings', None, 'buying_price_list')
set_missing_values(source, target_doc)
doclist = get_mapped_doc("Request for Quotation", source_name, {
@ -354,3 +354,32 @@ def get_supplier_tag():
frappe.cache().hset("Supplier", "Tags", tags)
return frappe.cache().hget("Supplier", "Tags")
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_rfq_containing_supplier(doctype, txt, searchfield, start, page_len, filters):
conditions = ""
if txt:
conditions += "and rfq.name like '%%"+txt+"%%' "
if filters.get("transaction_date"):
conditions += "and rfq.transaction_date = '{0}'".format(filters.get("transaction_date"))
rfq_data = frappe.db.sql("""
select
distinct rfq.name, rfq.transaction_date,
rfq.company
from
`tabRequest for Quotation` rfq, `tabRequest for Quotation Supplier` rfq_supplier
where
rfq.name = rfq_supplier.parent
and rfq_supplier.supplier = '{0}'
and rfq.docstatus = 1
and rfq.company = '{1}'
{2}
order by rfq.transaction_date ASC
limit %(page_len)s offset %(start)s """ \
.format(filters.get("supplier"), filters.get("company"), conditions),
{"page_len": page_len, "start": start}, as_dict=1)
return rfq_data

View File

@ -8,8 +8,7 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext
setup: function() {
this.frm.custom_make_buttons = {
'Purchase Order': 'Purchase Order',
'Quotation': 'Quotation',
'Subscription': 'Subscription'
'Quotation': 'Quotation'
}
this._super();
@ -28,12 +27,6 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext
cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
cur_frm.add_custom_button(__("Quotation"), this.make_quotation,
__('Create'));
if(!this.frm.doc.auto_repeat) {
cur_frm.add_custom_button(__('Subscription'), function() {
erpnext.utils.make_subscription(me.frm.doc.doctype, me.frm.doc.name)
}, __('Create'))
}
}
else if (this.frm.doc.docstatus===0) {
@ -54,6 +47,27 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext
}
})
}, __("Get items from"));
this.frm.add_custom_button(__("Request for Quotation"),
function() {
if (!me.frm.doc.supplier) {
frappe.throw({message:__("Please select a Supplier"), title:__("Mandatory")})
}
erpnext.utils.map_current_doc({
method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.make_supplier_quotation_from_rfq",
source_doctype: "Request for Quotation",
target: me.frm,
setters: {
company: me.frm.doc.company,
transaction_date: null
},
get_query_filters: {
supplier: me.frm.doc.supplier
},
get_query_method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.get_rfq_containing_supplier"
})
}, __("Get items from"));
}
},

View File

@ -159,6 +159,7 @@
"default": "Today",
"fieldname": "transaction_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Date",
"oldfieldname": "transaction_date",
"oldfieldtype": "Date",
@ -798,6 +799,7 @@
{
"fieldname": "valid_till",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Valid Till"
}
],
@ -805,7 +807,7 @@
"idx": 29,
"is_submittable": 1,
"links": [],
"modified": "2020-07-18 05:10:45.556792",
"modified": "2020-10-01 20:56:17.932007",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",

View File

@ -12,6 +12,8 @@
"item_name",
"column_break_3",
"lead_time_days",
"expected_delivery_date",
"is_free_item",
"section_break_5",
"description",
"item_group",
@ -19,20 +21,18 @@
"col_break1",
"image",
"image_view",
"manufacture_details",
"manufacturer",
"column_break_15",
"manufacturer_part_no",
"quantity_and_rate",
"qty",
"stock_uom",
"price_list_rate",
"discount_percentage",
"discount_amount",
"col_break2",
"uom",
"conversion_factor",
"stock_qty",
"sec_break_price_list",
"price_list_rate",
"discount_percentage",
"discount_amount",
"col_break_price_list",
"base_price_list_rate",
"sec_break1",
"rate",
@ -42,7 +42,6 @@
"base_rate",
"base_amount",
"pricing_rules",
"is_free_item",
"section_break_24",
"net_rate",
"net_amount",
@ -56,7 +55,6 @@
"weight_uom",
"warehouse_and_reference",
"warehouse",
"project",
"prevdoc_doctype",
"material_request",
"sales_order",
@ -65,13 +63,19 @@
"material_request_item",
"request_for_quotation_item",
"item_tax_rate",
"manufacture_details",
"manufacturer",
"column_break_15",
"manufacturer_part_no",
"ad_sec_break",
"project",
"section_break_44",
"page_break"
],
"fields": [
{
"bold": 1,
"columns": 4,
"columns": 2,
"fieldname": "item_code",
"fieldtype": "Link",
"in_list_view": 1,
@ -107,7 +111,7 @@
{
"fieldname": "lead_time_days",
"fieldtype": "Int",
"label": "Lead Time in days"
"label": "Supplier Lead Time (days)"
},
{
"collapsible": 1,
@ -162,7 +166,6 @@
{
"fieldname": "stock_uom",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Stock UOM",
"options": "UOM",
"print_hide": 1,
@ -196,6 +199,7 @@
{
"fieldname": "uom",
"fieldtype": "Link",
"in_list_view": 1,
"label": "UOM",
"options": "UOM",
"print_hide": 1,
@ -289,14 +293,6 @@
"print_hide": 1,
"read_only": 1
},
{
"default": "0",
"fieldname": "is_free_item",
"fieldtype": "Check",
"label": "Is Free Item",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "section_break_24",
"fieldtype": "Section Break"
@ -528,12 +524,43 @@
{
"fieldname": "column_break_15",
"fieldtype": "Column Break"
},
{
"fieldname": "sec_break_price_list",
"fieldtype": "Section Break"
},
{
"fieldname": "col_break_price_list",
"fieldtype": "Column Break"
},
{
"collapsible": 1,
"fieldname": "ad_sec_break",
"fieldtype": "Section Break",
"label": "Accounting Dimensions"
},
{
"default": "0",
"depends_on": "is_free_item",
"fieldname": "is_free_item",
"fieldtype": "Check",
"label": "Is Free Item",
"print_hide": 1,
"read_only": 1
},
{
"allow_on_submit": 1,
"bold": 1,
"fieldname": "expected_delivery_date",
"fieldtype": "Date",
"label": "Expected Delivery Date"
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-04-07 18:35:51.175947",
"modified": "2020-10-01 16:34:39.703033",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation Item",

View File

@ -1242,7 +1242,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
try:
doc.check_permission(perm_type)
except frappe.PermissionError:
actions = { 'create': 'add', 'write': 'update', 'cancel': 'remove' }
actions = { 'create': 'add', 'write': 'update'}
frappe.throw(_("You do not have permissions to {} items in a {}.")
.format(actions[perm_type], parent_doctype), title=_("Insufficient Permissions"))
@ -1285,7 +1285,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
sales_doctypes = ['Sales Order', 'Sales Invoice', 'Delivery Note', 'Quotation']
parent = frappe.get_doc(parent_doctype, parent_doctype_name)
check_doc_permissions(parent, 'cancel')
check_doc_permissions(parent, 'write')
validate_and_delete_children(parent, data)
for d in data:
@ -1319,24 +1319,26 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
validate_quantity(child_item, d)
child_item.qty = flt(d.get("qty"))
precision = child_item.precision("rate") or 2
rate_precision = child_item.precision("rate") or 2
conv_fac_precision = child_item.precision("conversion_factor") or 2
qty_precision = child_item.precision("qty") or 2
if flt(child_item.billed_amt, precision) > flt(flt(d.get("rate")) * flt(d.get("qty")), precision):
if flt(child_item.billed_amt, rate_precision) > flt(flt(d.get("rate"), rate_precision) * flt(d.get("qty"), qty_precision), rate_precision):
frappe.throw(_("Row #{0}: Cannot set Rate if amount is greater than billed amount for Item {1}.")
.format(child_item.idx, child_item.item_code))
else:
child_item.rate = flt(d.get("rate"))
child_item.rate = flt(d.get("rate"), rate_precision)
if d.get("conversion_factor"):
if child_item.stock_uom == child_item.uom:
child_item.conversion_factor = 1
else:
child_item.conversion_factor = flt(d.get('conversion_factor'))
child_item.conversion_factor = flt(d.get('conversion_factor'), conv_fac_precision)
if d.get("uom"):
child_item.uom = d.get("uom")
conversion_factor = flt(get_conversion_factor(child_item.item_code, child_item.uom).get("conversion_factor"))
child_item.conversion_factor = flt(d.get('conversion_factor')) or conversion_factor
child_item.conversion_factor = flt(d.get('conversion_factor'), conv_fac_precision) or conversion_factor
if d.get("delivery_date") and parent_doctype == 'Sales Order':
child_item.delivery_date = d.get('delivery_date')

View File

@ -847,6 +847,7 @@ def get_items_from_bom(item_code, bom, exploded_item=1):
where
t2.parent = t1.name and t1.item = %s
and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
and t2.sourced_by_supplier = 0
and t2.item_code = t3.name""".format(doctype),
(item_code, bom), as_dict=1)

View File

@ -368,13 +368,17 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
searchfields = meta.get_search_fields()
search_columns = ''
search_cond = ''
if searchfields:
search_columns = ", " + ", ".join(searchfields)
search_cond = " or " + " or ".join([field + " like %(txt)s" for field in searchfields])
if args.get('warehouse'):
searchfields = ['batch.' + field for field in searchfields]
if searchfields:
search_columns = ", " + ", ".join(searchfields)
search_cond = " or " + " or ".join([field + " like %(txt)s" for field in searchfields])
batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom,
concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date)
@ -387,7 +391,8 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
and sle.warehouse = %(warehouse)s
and (sle.batch_no like %(txt)s
or batch.expiry_date like %(txt)s
or batch.manufacturing_date like %(txt)s)
or batch.manufacturing_date like %(txt)s
{search_cond})
and batch.docstatus < 2
{cond}
{match_conditions}
@ -397,7 +402,8 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
search_columns = search_columns,
cond=cond,
match_conditions=get_match_cond(doctype),
having_clause = having_clause
having_clause = having_clause,
search_cond = search_cond
), args)
return batch_nos
@ -409,12 +415,15 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
and item = %(item_code)s
and (name like %(txt)s
or expiry_date like %(txt)s
or manufacturing_date like %(txt)s)
or manufacturing_date like %(txt)s
{search_cond})
and docstatus < 2
{0}
{match_conditions}
order by expiry_date, name desc
limit %(start)s, %(page_len)s""".format(cond, search_columns = search_columns, match_conditions=get_match_cond(doctype)), args)
limit %(start)s, %(page_len)s""".format(cond, search_columns = search_columns,
search_cond = search_cond, match_conditions=get_match_cond(doctype)), args)
@frappe.whitelist()

View File

@ -10,6 +10,7 @@ from erpnext.stock.utils import get_incoming_rate
from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.stock.doctype.item.item import set_item_default
from frappe.contacts.doctype.address.address import get_address_display
from erpnext.controllers.accounts_controller import get_taxes_and_charges
from erpnext.controllers.stock_controller import StockController
@ -53,10 +54,10 @@ class SellingController(StockController):
super(SellingController, self).set_missing_values(for_validate)
# set contact and address details for customer, if they are not mentioned
self.set_missing_lead_customer_details()
self.set_missing_lead_customer_details(for_validate=for_validate)
self.set_price_list_and_item_details(for_validate=for_validate)
def set_missing_lead_customer_details(self):
def set_missing_lead_customer_details(self, for_validate=False):
customer, lead = None, None
if getattr(self, "customer", None):
customer = self.customer
@ -94,6 +95,11 @@ class SellingController(StockController):
posting_date=self.get('transaction_date') or self.get('posting_date'),
company=self.company))
if self.get('taxes_and_charges') and not self.get('taxes') and not for_validate:
taxes = get_taxes_and_charges('Sales Taxes and Charges Template', self.taxes_and_charges)
for tax in taxes:
self.append('taxes', tax)
def set_price_list_and_item_details(self, for_validate=False):
self.set_price_list_currency("Selling")
self.set_missing_item_details(for_validate=for_validate)

View File

@ -25,7 +25,7 @@ def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_p
if not filters: filters = []
if doctype in ['Supplier Quotation', 'Purchase Invoice']:
if doctype in ['Supplier Quotation', 'Purchase Invoice', 'Quotation']:
filters.append((doctype, 'docstatus', '<', 2))
else:
filters.append((doctype, 'docstatus', '=', 1))

View File

@ -365,3 +365,8 @@ def get_lead_with_phone_number(number):
lead = leads[0].name if leads else None
return lead
def daily_open_lead():
leads = frappe.get_all("Lead", filters = [["contact_date", "Between", [nowdate(), nowdate()]]])
for lead in leads:
frappe.db.set_value("Lead", lead.name, "status", "Open")

View File

@ -8,6 +8,7 @@
"allow_print": 0,
"amount": 0.0,
"amount_based_on_field": 0,
"apply_document_permissions": 0,
"creation": "2016-09-22 13:10:10.792735",
"doc_type": "Student Applicant",
"docstatus": 0,
@ -16,7 +17,7 @@
"is_standard": 1,
"login_required": 1,
"max_attachment_size": 0,
"modified": "2020-06-11 22:53:45.875310",
"modified": "2020-10-07 23:13:07.814941",
"modified_by": "Administrator",
"module": "Education",
"name": "student-applicant",
@ -157,7 +158,7 @@
},
{
"allow_read_on_all_link_options": 0,
"default": "INDIAN",
"default": "",
"fieldname": "nationality",
"fieldtype": "Data",
"hidden": 0,

View File

@ -23,7 +23,6 @@ web_include_css = "assets/css/erpnext-web.css"
doctype_js = {
"Communication": "public/js/communication.js",
"Event": "public/js/event.js",
"Website Theme": "public/js/website_theme.js",
"Newsletter": "public/js/newsletter.js"
}
@ -336,7 +335,8 @@ scheduler_events = {
"erpnext.hr.doctype.leave_ledger_entry.leave_ledger_entry.process_expired_allocation",
"erpnext.hr.utils.generate_leave_encashment",
"erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall.create_process_loan_security_shortfall",
"erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual_for_term_loans"
"erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual.process_loan_interest_accrual_for_term_loans",
"erpnext.crm.doctype.lead.lead.daily_open_lead"
],
"monthly_long": [
"erpnext.accounts.deferred_revenue.process_deferred_accounting",

View File

@ -10,13 +10,13 @@ frappe.ui.form.on('Appraisal', {
};
},
onload: function(frm) {
onload: function(frm) {
if(!frm.doc.status) {
frm.set_value('status', 'Draft');
}
},
kra_template: function(frm) {
kra_template: function(frm) {
frm.doc.goals = [];
erpnext.utils.map_current_doc({
method: "erpnext.hr.doctype.appraisal.appraisal.fetch_appraisal_template",
@ -24,31 +24,56 @@ frappe.ui.form.on('Appraisal', {
frm: frm
});
},
calculate_total: function(frm) {
let goals = frm.doc.goals || [];
let total =0;
for(let i = 0; i<goals.length; i++){
calculate_total: function(frm) {
let goals = frm.doc.goals || [];
let total = 0;
if (goals == []) {
frm.set_value('total_score', 0);
return;
}
for (let i = 0; i<goals.length; i++) {
total = flt(total)+flt(goals[i].score_earned)
}
frm.set_value('total_score', total);
if (!isNaN(total)) {
frm.set_value('total_score', total);
frm.refresh_field('calculate_total');
}
},
set_score_earned: function(frm) {
let goals = frm.doc.goals || [];
for (let i = 0; i<goals.length; i++) {
var d = locals[goals[i].doctype][goals[i].name];
if (d.score && d.per_weightage) {
d.score_earned = flt(d.per_weightage*d.score, precision("score_earned", d))/100;
}
else {
d.score_earned = 0;
}
refresh_field('score_earned', d.name, 'goals');
}
frm.trigger('calculate_total');
}
});
frappe.ui.form.on('Appraisal Goal', {
score: function(frm, cdt, cdn) {
var d = locals[cdt][cdn];
if (d.score) {
if (flt(d.score) > 5) {
frappe.msgprint(__("Score must be less than or equal to 5"));
d.score = 0;
refresh_field('score', d.name, 'goals');
}
d.score_earned = flt(d.per_weightage*d.score, precision("score_earned", d))/100;
} else {
d.score_earned = 0;
if (flt(d.score) > 5) {
frappe.msgprint(__("Score must be less than or equal to 5"));
d.score = 0;
refresh_field('score', d.name, 'goals');
}
refresh_field('score_earned', d.name, 'goals');
frm.trigger('calculate_total');
else {
frm.trigger('set_score_earned');
}
},
per_weightage: function(frm) {
frm.trigger('set_score_earned');
},
goals_remove: function(frm) {
frm.trigger('set_score_earned');
}
});
});

View File

@ -1,775 +1,254 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "naming_series:",
"beta": 0,
"creation": "2013-01-10 16:34:12",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 0,
"actions": [],
"autoname": "naming_series:",
"creation": "2013-01-10 16:34:12",
"doctype": "DocType",
"document_type": "Setup",
"engine": "InnoDB",
"field_order": [
"employee_details",
"naming_series",
"kra_template",
"employee",
"employee_name",
"column_break0",
"status",
"start_date",
"end_date",
"department",
"section_break0",
"goals",
"total_score",
"section_break1",
"remarks",
"other_details",
"company",
"column_break_17",
"amended_from"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "employee_details",
"fieldtype": "Section 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,
"label": "",
"length": 0,
"no_copy": 0,
"oldfieldtype": "Section Break",
"permlevel": 0,
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "employee_details",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"fieldname": "naming_series",
"fieldtype": "Select",
"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": "Series",
"length": 0,
"no_copy": 1,
"options": "HR-APR-.YY.-.MM.",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 1,
"translatable": 0,
"unique": 0
},
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"no_copy": 1,
"options": "HR-APR-.YY.-.MM.",
"print_hide": 1,
"reqd": 1,
"set_only_once": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "",
"fieldname": "kra_template",
"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": 1,
"label": "Appraisal Template",
"length": 0,
"no_copy": 0,
"oldfieldname": "kra_template",
"oldfieldtype": "Link",
"options": "Appraisal Template",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "kra_template",
"fieldtype": "Link",
"in_standard_filter": 1,
"label": "Appraisal Template",
"oldfieldname": "kra_template",
"oldfieldtype": "Link",
"options": "Appraisal Template",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "kra_template",
"description": "",
"fieldname": "employee",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "For Employee",
"length": 0,
"no_copy": 0,
"oldfieldname": "employee",
"oldfieldtype": "Link",
"options": "Employee",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"depends_on": "kra_template",
"fieldname": "employee",
"fieldtype": "Link",
"in_global_search": 1,
"in_standard_filter": 1,
"label": "For Employee",
"oldfieldname": "employee",
"oldfieldtype": "Link",
"options": "Employee",
"reqd": 1,
"search_index": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "kra_template",
"fieldname": "employee_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "For Employee Name",
"length": 0,
"no_copy": 0,
"oldfieldname": "employee_name",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"depends_on": "kra_template",
"fieldname": "employee_name",
"fieldtype": "Data",
"in_global_search": 1,
"label": "For Employee Name",
"oldfieldname": "employee_name",
"oldfieldtype": "Data",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "kra_template",
"fieldname": "column_break0",
"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,
"oldfieldtype": "Column Break",
"permlevel": 0,
"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,
"translatable": 0,
"unique": 0,
"depends_on": "kra_template",
"fieldname": "column_break0",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"width": "50%"
},
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Draft",
"depends_on": "kra_template",
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Status",
"length": 0,
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
"options": "\nDraft\nSubmitted\nCompleted\nCancelled",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"default": "Draft",
"depends_on": "kra_template",
"fieldname": "status",
"fieldtype": "Select",
"in_standard_filter": 1,
"label": "Status",
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
"options": "\nDraft\nSubmitted\nCompleted\nCancelled",
"read_only": 1,
"reqd": 1,
"search_index": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "kra_template",
"fieldname": "start_date",
"fieldtype": "Date",
"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": "Start Date",
"length": 0,
"no_copy": 0,
"oldfieldname": "start_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"depends_on": "kra_template",
"fieldname": "start_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Start Date",
"oldfieldname": "start_date",
"oldfieldtype": "Date",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "kra_template",
"fieldname": "end_date",
"fieldtype": "Date",
"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": "End Date",
"length": 0,
"no_copy": 0,
"oldfieldname": "end_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"depends_on": "kra_template",
"fieldname": "end_date",
"fieldtype": "Date",
"label": "End Date",
"oldfieldname": "end_date",
"oldfieldtype": "Date",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "employee.department",
"fieldname": "department",
"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": "Department",
"length": 0,
"no_copy": 0,
"options": "Department",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fetch_from": "employee.department",
"fieldname": "department",
"fieldtype": "Link",
"label": "Department",
"options": "Department",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "kra_template",
"fieldname": "section_break0",
"fieldtype": "Section 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,
"label": "Goals",
"length": 0,
"no_copy": 0,
"oldfieldtype": "Section Break",
"options": "Simple",
"permlevel": 0,
"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,
"translatable": 0,
"unique": 0
},
"depends_on": "kra_template",
"fieldname": "section_break0",
"fieldtype": "Section Break",
"label": "Goals",
"oldfieldtype": "Section Break",
"options": "Simple"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "goals",
"fieldtype": "Table",
"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": "Goals",
"length": 0,
"no_copy": 0,
"oldfieldname": "appraisal_details",
"oldfieldtype": "Table",
"options": "Appraisal Goal",
"permlevel": 0,
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "goals",
"fieldtype": "Table",
"label": "Goals",
"oldfieldname": "appraisal_details",
"oldfieldtype": "Table",
"options": "Appraisal Goal"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "calculate_total_score",
"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": "Calculate Total Score",
"length": 0,
"no_copy": 0,
"oldfieldtype": "Button",
"options": "calculate_total",
"permlevel": 0,
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "total_score",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Total Score (Out of 5)",
"no_copy": 1,
"oldfieldname": "total_score",
"oldfieldtype": "Currency",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "total_score",
"fieldtype": "Float",
"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": "Total Score (Out of 5)",
"length": 0,
"no_copy": 1,
"oldfieldname": "total_score",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"depends_on": "kra_template",
"fieldname": "section_break1",
"fieldtype": "Section Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "kra_template",
"fieldname": "section_break1",
"fieldtype": "Section 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,
"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,
"translatable": 0,
"unique": 0
},
"description": "Any other remarks, noteworthy effort that should go in the records.",
"fieldname": "remarks",
"fieldtype": "Text",
"label": "Remarks"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Any other remarks, noteworthy effort that should go in the records.",
"fieldname": "remarks",
"fieldtype": "Text",
"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": "Remarks",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
"translatable": 0,
"unique": 0
},
"depends_on": "kra_template",
"fieldname": "other_details",
"fieldtype": "Section Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "kra_template",
"fieldname": "other_details",
"fieldtype": "Section 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,
"label": "",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"oldfieldname": "company",
"oldfieldtype": "Link",
"options": "Company",
"remember_last_selected_value": 1,
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "company",
"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": "Company",
"length": 0,
"no_copy": 0,
"oldfieldname": "company",
"oldfieldtype": "Link",
"options": "Company",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 1,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "column_break_17",
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_17",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Amended From",
"length": 0,
"no_copy": 1,
"oldfieldname": "amended_from",
"oldfieldtype": "Data",
"options": "Appraisal",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 1,
"label": "Amended From",
"no_copy": 1,
"oldfieldname": "amended_from",
"oldfieldtype": "Data",
"options": "Appraisal",
"print_hide": 1,
"read_only": 1,
"report_hide": 1,
"width": "150px"
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-thumbs-up",
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2020-09-18 17:26:09.703215",
"modified_by": "Administrator",
"module": "HR",
"name": "Appraisal",
"owner": "Administrator",
],
"icon": "fa fa-thumbs-up",
"idx": 1,
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2020-10-03 21:48:33.297065",
"modified_by": "Administrator",
"module": "HR",
"name": "Appraisal",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Employee",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"create": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Employee",
"share": 1,
"write": 1
},
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"submit": 1,
"write": 1
},
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "HR User",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "HR User",
"share": 1,
"submit": 1,
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "status, employee, employee_name",
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "employee",
"title_field": "employee_name",
"track_changes": 0,
"track_seen": 0,
"track_views": 0
],
"search_fields": "status, employee, employee_name",
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "employee",
"title_field": "employee_name"
}

View File

@ -50,7 +50,7 @@ class Appraisal(Document):
total_w += flt(d.per_weightage)
if int(total_w) != 100:
frappe.throw(_("Total weightage assigned should be 100%. It is {0}").format(str(total_w) + "%"))
frappe.throw(_("Total weightage assigned should be 100%.<br>It is {0}").format(str(total_w) + "%"))
if frappe.db.get_value("Employee", self.employee, "user_id") != \
frappe.session.user and total == 0:

View File

@ -109,7 +109,6 @@
"encashment_date",
"exit_interview_details",
"held_on",
"reason_for_resignation",
"new_workplace",
"feedback",
"lft",
@ -682,7 +681,7 @@
},
{
"fieldname": "reason_for_leaving",
"fieldtype": "Data",
"fieldtype": "Small Text",
"label": "Reason for Leaving",
"oldfieldname": "reason_for_leaving",
"oldfieldtype": "Data"
@ -696,6 +695,7 @@
"options": "\nYes\nNo"
},
{
"depends_on": "eval:doc.leave_encashed ==\"Yes\"",
"fieldname": "encashment_date",
"fieldtype": "Date",
"label": "Encashment Date",
@ -705,7 +705,6 @@
{
"fieldname": "exit_interview_details",
"fieldtype": "Column Break",
"label": "Exit Interview Details",
"oldfieldname": "col_brk6",
"oldfieldtype": "Column Break",
"width": "50%"
@ -713,18 +712,10 @@
{
"fieldname": "held_on",
"fieldtype": "Date",
"label": "Held On",
"label": "Exit Interview Held On",
"oldfieldname": "held_on",
"oldfieldtype": "Date"
},
{
"fieldname": "reason_for_resignation",
"fieldtype": "Select",
"label": "Reason for Resignation",
"oldfieldname": "reason_for_resignation",
"oldfieldtype": "Select",
"options": "\nBetter Prospects\nHealth Concerns"
},
{
"fieldname": "new_workplace",
"fieldtype": "Data",
@ -809,37 +800,29 @@
"fieldname": "expense_approver",
"fieldtype": "Link",
"label": "Expense Approver",
"options": "User",
"show_days": 1,
"show_seconds": 1
"options": "User"
},
{
"fieldname": "approvers_section",
"fieldtype": "Section Break",
"label": "Approvers",
"show_days": 1,
"show_seconds": 1
"label": "Approvers"
},
{
"fieldname": "column_break_45",
"fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
"fieldtype": "Column Break"
},
{
"fieldname": "shift_request_approver",
"fieldtype": "Link",
"label": "Shift Request Approver",
"options": "User",
"show_days": 1,
"show_seconds": 1
"options": "User"
}
],
"icon": "fa fa-user",
"idx": 24,
"image_field": "image",
"links": [],
"modified": "2020-07-28 01:36:04.109189",
"modified": "2020-10-06 15:58:23.805489",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee",

View File

@ -56,6 +56,9 @@ class Employee(NestedSet):
if existing_user_id:
remove_user_permission(
"Employee", self.name, existing_user_id)
def after_rename(self, old, new, merge):
self.db_set("employee", new)
def set_employee_name(self):
self.employee_name = ' '.join(filter(lambda x: x, [self.first_name, self.middle_name, self.last_name]))

View File

@ -434,7 +434,8 @@ var get_bom_material_detail= function(doc, cdt, cdn, scrap_items) {
"include_item_in_manufacturing": d.include_item_in_manufacturing,
"uom": d.uom,
"stock_uom": d.stock_uom,
"conversion_factor": d.conversion_factor
"conversion_factor": d.conversion_factor,
"sourced_by_supplier": d.sourced_by_supplier
},
callback: function(r) {
d = locals[cdt][cdn];
@ -616,6 +617,22 @@ frappe.ui.form.on("BOM Item", "item_code", function(frm, cdt, cdn) {
refresh_field("allow_alternative_item", d.name, d.parentfield);
});
frappe.ui.form.on("BOM Item", "sourced_by_supplier", function(frm, cdt, cdn) {
var d = locals[cdt][cdn];
if (d.sourced_by_supplier) {
d.rate = 0;
refresh_field("rate", d.name, d.parentfield);
}
});
frappe.ui.form.on("BOM Item", "rate", function(frm, cdt, cdn) {
var d = locals[cdt][cdn];
if (d.sourced_by_supplier) {
d.rate = 0;
refresh_field("rate", d.name, d.parentfield);
}
});
frappe.ui.form.on("BOM Operation", "operations_remove", function(frm) {
erpnext.bom.calculate_op_cost(frm.doc);
erpnext.bom.calculate_total(frm.doc);

View File

@ -137,7 +137,8 @@ class BOM(WebsiteGenerator):
"qty": item.qty,
"uom": item.uom,
"stock_uom": item.stock_uom,
"conversion_factor": item.conversion_factor
"conversion_factor": item.conversion_factor,
"sourced_by_supplier": item.sourced_by_supplier
})
for r in ret:
if not item.get(r):
@ -172,7 +173,8 @@ class BOM(WebsiteGenerator):
'qty' : args.get("qty") or args.get("stock_qty") or 1,
'stock_qty' : args.get("qty") or args.get("stock_qty") or 1,
'base_rate' : flt(rate) * (flt(self.conversion_rate) or 1),
'include_item_in_manufacturing': cint(args['transfer_for_manufacture']) or 0
'include_item_in_manufacturing': cint(args['transfer_for_manufacture']) or 0,
'sourced_by_supplier' : args['sourced_by_supplier'] or 0
}
return ret_item
@ -191,8 +193,8 @@ class BOM(WebsiteGenerator):
if arg.get('scrap_items'):
rate = get_valuation_rate(arg)
elif arg:
#Customer Provided parts will have zero rate
if not frappe.db.get_value('Item', arg["item_code"], 'is_customer_provided_item'):
#Customer Provided parts and Supplier sourced parts will have zero rate
if not frappe.db.get_value('Item', arg["item_code"], 'is_customer_provided_item') and not arg.get('sourced_by_supplier'):
if arg.get('bom_no') and self.set_rate_of_sub_assembly_item_based_on_bom:
rate = flt(self.get_bom_unitcost(arg['bom_no'])) * (arg.get("conversion_factor") or 1)
else:
@ -205,7 +207,6 @@ class BOM(WebsiteGenerator):
else:
frappe.msgprint(_("{0} not found for item {1}")
.format(self.rm_cost_as_per, arg["item_code"]), alert=True)
return flt(rate) * flt(self.plc_conversion_rate or 1) / (self.conversion_rate or 1)
def update_cost(self, update_parent=True, from_child_bom=False, save=True):
@ -221,7 +222,8 @@ class BOM(WebsiteGenerator):
"qty": d.qty,
"uom": d.uom,
"stock_uom": d.stock_uom,
"conversion_factor": d.conversion_factor
"conversion_factor": d.conversion_factor,
"sourced_by_supplier": d.sourced_by_supplier
})
if rate:
@ -495,7 +497,8 @@ class BOM(WebsiteGenerator):
'stock_uom' : d.stock_uom,
'stock_qty' : flt(d.stock_qty),
'rate' : flt(d.base_rate) / (flt(d.conversion_factor) or 1.0),
'include_item_in_manufacturing': d.include_item_in_manufacturing
'include_item_in_manufacturing': d.include_item_in_manufacturing,
'sourced_by_supplier': d.sourced_by_supplier
}))
def company_currency(self):
@ -521,6 +524,7 @@ class BOM(WebsiteGenerator):
bom_item.stock_qty,
bom_item.rate,
bom_item.include_item_in_manufacturing,
bom_item.sourced_by_supplier,
bom_item.stock_qty / ifnull(bom.quantity, 1) AS qty_consumed_per_unit
FROM `tabBOM Explosion Item` bom_item, tabBOM bom
WHERE
@ -539,7 +543,8 @@ class BOM(WebsiteGenerator):
'stock_uom' : d['stock_uom'],
'stock_qty' : d['qty_consumed_per_unit'] * stock_qty,
'rate' : flt(d['rate']),
'include_item_in_manufacturing': d.get('include_item_in_manufacturing', 0)
'include_item_in_manufacturing': d.get('include_item_in_manufacturing', 0),
'sourced_by_supplier': d.get('sourced_by_supplier', 0)
}))
def add_exploded_items(self):
@ -679,7 +684,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
is_stock_item=is_stock_item,
qty_field="stock_qty",
select_columns = """, bom_item.source_warehouse, bom_item.operation,
bom_item.include_item_in_manufacturing, bom_item.description, bom_item.rate,
bom_item.include_item_in_manufacturing, bom_item.description, bom_item.rate, bom_item.sourced_by_supplier,
(Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s limit 1) as idx""")
items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True)
@ -692,7 +697,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
query = query.format(table="BOM Item", where_conditions="", is_stock_item=is_stock_item,
qty_field="stock_qty" if fetch_qty_in_stock_uom else "qty",
select_columns = """, bom_item.uom, bom_item.conversion_factor, bom_item.source_warehouse,
bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing,
bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing, bom_item.sourced_by_supplier,
bom_item.description, bom_item.base_rate as rate """)
items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True)

View File

@ -10,6 +10,8 @@ from frappe.test_runner import make_test_records
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost
from six import string_types
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
test_records = frappe.get_test_records('BOM')
@ -138,6 +140,74 @@ class TestBOM(unittest.TestCase):
self.assertEqual(bom.items[0].rate, 20)
def test_subcontractor_sourced_item(self):
item_code = "_Test Subcontracted FG Item 1"
if not frappe.db.exists('Item', item_code):
make_item(item_code, {
'is_stock_item': 1,
'is_sub_contracted_item': 1,
'stock_uom': 'Nos'
})
if not frappe.db.exists('Item', "Test Extra Item 1"):
make_item("Test Extra Item 1", {
'is_stock_item': 1,
'stock_uom': 'Nos'
})
if not frappe.db.exists('Item', "Test Extra Item 2"):
make_item("Test Extra Item 2", {
'is_stock_item': 1,
'stock_uom': 'Nos'
})
if not frappe.db.exists('Item', "Test Extra Item 3"):
make_item("Test Extra Item 3", {
'is_stock_item': 1,
'stock_uom': 'Nos'
})
bom = frappe.get_doc({
'doctype': 'BOM',
'is_default': 1,
'item': item_code,
'currency': 'USD',
'quantity': 1,
'company': '_Test Company'
})
for item in ["Test Extra Item 1", "Test Extra Item 2"]:
item_doc = frappe.get_doc('Item', item)
bom.append('items', {
'item_code': item,
'qty': 1,
'uom': item_doc.stock_uom,
'stock_uom': item_doc.stock_uom,
'rate': item_doc.valuation_rate
})
bom.append('items', {
'item_code': "Test Extra Item 3",
'qty': 1,
'uom': item_doc.stock_uom,
'stock_uom': item_doc.stock_uom,
'rate': 0,
'sourced_by_supplier': 1
})
bom.insert(ignore_permissions=True)
bom.update_cost()
bom.submit()
# test that sourced_by_supplier rate is zero even after updating cost
self.assertEqual(bom.items[2].rate, 0)
# test in Purchase Order sourced_by_supplier is not added to Supplied Item
po = create_purchase_order(item_code=item_code, qty=1,
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
bom_items = sorted([d.item_code for d in bom.items if d.sourced_by_supplier != 1])
supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
self.assertEquals(bom_items, supplied_items)
def get_default_bom(item_code="_Test FG Item 2"):
return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})

View File

@ -1,626 +1,181 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "hash",
"beta": 0,
"creation": "2013-03-07 11:42:57",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
"engine": "InnoDB",
"actions": [],
"autoname": "hash",
"creation": "2013-03-07 11:42:57",
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"item_code",
"item_name",
"cb",
"source_warehouse",
"operation",
"section_break_3",
"description",
"column_break_2",
"image",
"image_view",
"section_break_4",
"stock_qty",
"rate",
"qty_consumed_per_unit",
"column_break_8",
"stock_uom",
"amount",
"include_item_in_manufacturing",
"sourced_by_supplier"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_code",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Item Code",
"length": 0,
"no_copy": 0,
"oldfieldname": "item_code",
"oldfieldtype": "Link",
"options": "Item",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "item_code",
"fieldtype": "Link",
"in_global_search": 1,
"in_list_view": 1,
"label": "Item Code",
"oldfieldname": "item_code",
"oldfieldtype": "Link",
"options": "Item",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Item Name",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "item_name",
"fieldtype": "Data",
"in_global_search": 1,
"in_list_view": 1,
"label": "Item Name",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "cb",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "cb",
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "source_warehouse",
"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": "Source Warehouse",
"length": 0,
"no_copy": 0,
"options": "Warehouse",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "source_warehouse",
"fieldtype": "Link",
"label": "Source Warehouse",
"options": "Warehouse",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "operation",
"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": "Operation",
"length": 0,
"no_copy": 0,
"options": "Operation",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "operation",
"fieldtype": "Link",
"label": "Operation",
"options": "Operation",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_3",
"fieldtype": "Section 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,
"translatable": 0,
"unique": 0
},
"fieldname": "section_break_3",
"fieldtype": "Section Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "description",
"fieldtype": "Text Editor",
"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": "Description",
"length": 0,
"no_copy": 0,
"oldfieldname": "description",
"oldfieldtype": "Text",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "300px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"fieldname": "description",
"fieldtype": "Text Editor",
"in_list_view": 1,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
"print_width": "300px",
"read_only": 1,
"width": "300px"
},
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "column_break_2",
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Image",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
"label": "Image",
"print_hide": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "image_view",
"fieldtype": "Image",
"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": "Image View",
"length": 0,
"no_copy": 0,
"options": "image",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "image_view",
"fieldtype": "Image",
"label": "Image View",
"options": "image"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_4",
"fieldtype": "Section 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,
"translatable": 0,
"unique": 0
},
"fieldname": "section_break_4",
"fieldtype": "Section Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "stock_qty",
"fieldtype": "Float",
"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": "Stock Qty",
"length": 0,
"no_copy": 0,
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "stock_qty",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Stock Qty",
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "rate",
"fieldtype": "Currency",
"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": "Rate",
"length": 0,
"no_copy": 0,
"oldfieldname": "standard_rate",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "rate",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Rate",
"oldfieldname": "standard_rate",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "qty_consumed_per_unit",
"fieldtype": "Float",
"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": "Qty Consumed Per Unit",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "qty_consumed_per_unit",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Qty Consumed Per Unit",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_8",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "column_break_8",
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "stock_uom",
"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": "Stock UOM",
"length": 0,
"no_copy": 0,
"oldfieldname": "stock_uom",
"oldfieldtype": "Link",
"options": "UOM",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "stock_uom",
"fieldtype": "Link",
"label": "Stock UOM",
"oldfieldname": "stock_uom",
"oldfieldtype": "Link",
"options": "UOM",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"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": "Amount",
"length": 0,
"no_copy": 0,
"oldfieldname": "amount_as_per_sr",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount",
"oldfieldname": "amount_as_per_sr",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "include_item_in_manufacturing",
"fieldtype": "Check",
"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": "Include Item In Manufacturing",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"default": "0",
"fieldname": "include_item_in_manufacturing",
"fieldtype": "Check",
"label": "Include Item In Manufacturing",
"read_only": 1
},
{
"default": "0",
"fieldname": "sourced_by_supplier",
"fieldtype": "Check",
"label": "Sourced by Supplier",
"read_only": 1
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-11-20 19:04:59.813773",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Explosion Item",
"owner": "Administrator",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"track_changes": 1,
"track_seen": 0,
"track_views": 0
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-10-08 16:21:29.386212",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Explosion Item",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -37,7 +37,9 @@
"section_break_27",
"has_variants",
"include_item_in_manufacturing",
"original_item"
"original_item",
"column_break_33",
"sourced_by_supplier"
],
"fields": [
{
@ -272,12 +274,23 @@
"no_copy": 1,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "column_break_33",
"fieldtype": "Column Break"
},
{
"default": "0",
"fieldname": "sourced_by_supplier",
"fieldtype": "Check",
"label": "Sourced by Supplier"
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-04-09 14:30:26.535546",
"modified": "2020-10-08 14:19:37.563300",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Item",

View File

@ -381,7 +381,6 @@ class ProductionPlan(Document):
"transaction_date": nowdate(),
"status": "Draft",
"company": self.company,
"requested_by": frappe.session.user,
'material_request_type': material_request_type,
'customer': item_doc.customer or ''
})

View File

@ -434,7 +434,7 @@ class WorkOrder(Document):
elif flt(d.completed_qty) <= max_allowed_qty_for_wo:
d.status = "Completed"
else:
frappe.throw(_("Completed Qty can not be greater than 'Qty to Manufacture'"))
frappe.throw(_("Completed Qty cannot be greater than 'Qty to Manufacture'"))
def set_actual_dates(self):
if self.get("operations"):

View File

@ -224,7 +224,8 @@ def trigger_razorpay_subscription(*args, **kwargs):
member.subscription_activated = 1
member.save(ignore_permissions=True)
except Exception as e:
log = frappe.log_error(e, "Error creating membership entry")
message = "{0}\n\n{1}\n\n{2}: {3}".format(e, frappe.get_traceback(), __("Payment ID"), payment.id)
log = frappe.log_error(message, _("Error creating membership entry for {0}").format(member.name))
notify_failure(log)
return { 'status': 'Failed', 'reason': e}
@ -250,4 +251,4 @@ def get_plan_from_razorpay_id(plan_id):
try:
return plan[0]['name']
except:
return None
return None

View File

@ -217,7 +217,7 @@
"fieldname": "help",
"fieldtype": "HTML",
"label": "Help",
"options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condtion. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base &lt; 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS &gt; 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
"options": "<h3>Help</h3>\n\n<p>Notes:</p>\n\n<ol>\n<li>Use field <code>base</code> for using base salary of the Employee</li>\n<li>Use Salary Component abbreviations in conditions and formulas. <code>BS = Basic Salary</code></li>\n<li>Use field name for employee details in conditions and formulas. <code>Employment Type = employment_type</code><code>Branch = branch</code></li>\n<li>Use field name from Salary Slip in conditions and formulas. <code>Payment Days = payment_days</code><code>Leave without pay = leave_without_pay</code></li>\n<li>Direct Amount can also be entered based on Condition. See example 3</li></ol>\n\n<h4>Examples</h4>\n<ol>\n<li>Calculating Basic Salary based on <code>base</code>\n<pre><code>Condition: base &lt; 10000</code></pre>\n<pre><code>Formula: base * .2</code></pre></li>\n<li>Calculating HRA based on Basic Salary<code>BS</code> \n<pre><code>Condition: BS &gt; 2000</code></pre>\n<pre><code>Formula: BS * .1</code></pre></li>\n<li>Calculating TDS based on Employment Type<code>employment_type</code> \n<pre><code>Condition: employment_type==\"Intern\"</code></pre>\n<pre><code>Amount: 1000</code></pre></li>\n</ol>"
},
{
"default": "0",
@ -238,14 +238,13 @@
"depends_on": "eval:doc.type == \"Deduction\"",
"fieldname": "is_income_tax_component",
"fieldtype": "Check",
"label": "Is Income Tax Component",
"show_days": 1,
"show_seconds": 1
"label": "Is Income Tax Component"
}
],
"icon": "fa fa-flag",
"index_web_pages_for_search": 1,
"links": [],
"modified": "2020-06-22 15:39:20.826565",
"modified": "2020-10-07 20:38:33.795853",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Salary Component",

View File

@ -117,7 +117,7 @@
"depends_on": "eval:doc.is_flexible_benefit != 1",
"fieldname": "section_break_2",
"fieldtype": "Section Break",
"label": "Condtion and formula"
"label": "Condition and formula"
},
{
"allow_on_submit": 1,
@ -206,38 +206,28 @@
"collapsible": 1,
"fieldname": "section_break_5",
"fieldtype": "Section Break",
"label": "Component properties and references ",
"show_days": 1,
"show_seconds": 1
"label": "Component properties and references "
},
{
"fieldname": "column_break_11",
"fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_19",
"fieldtype": "Section Break",
"show_days": 1,
"show_seconds": 1
"fieldtype": "Section Break"
},
{
"fieldname": "column_break_18",
"fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
"fieldtype": "Column Break"
},
{
"fieldname": "column_break_24",
"fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
"fieldtype": "Column Break"
}
],
"istable": 1,
"links": [],
"modified": "2020-07-01 12:13:41.956495",
"modified": "2020-10-07 20:39:41.619283",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Salary Detail",

View File

@ -452,6 +452,9 @@ erpnext.utils.update_child_items = function(opts) {
const frm = opts.frm;
const cannot_add_row = (typeof opts.cannot_add_row === 'undefined') ? true : opts.cannot_add_row;
const child_docname = (typeof opts.cannot_add_row === 'undefined') ? "items" : opts.child_docname;
const child_meta = frappe.get_meta(`${frm.doc.doctype} Item`);
const get_precision = (fieldname) => child_meta.fields.find(f => f.fieldname == fieldname).precision;
this.data = [];
const fields = [{
fieldtype:'Data',
@ -480,7 +483,7 @@ erpnext.utils.update_child_items = function(opts) {
callback: r => {
if(!r.exc) {
if (this.doc.conversion_factor == r.message.conversion_factor) return;
const docname = this.doc.docname;
dialog.fields_dict.trans_items.df.data.some(doc => {
if (doc.docname == docname) {
@ -499,14 +502,16 @@ erpnext.utils.update_child_items = function(opts) {
default: 0,
read_only: 0,
in_list_view: 1,
label: __('Qty')
label: __('Qty'),
precision: get_precision("qty")
}, {
fieldtype:'Currency',
fieldname:"rate",
default: 0,
read_only: 0,
in_list_view: 1,
label: __('Rate')
label: __('Rate'),
precision: get_precision("rate")
}];
if (frm.doc.doctype == 'Sales Order' || frm.doc.doctype == 'Purchase Order' ) {
@ -521,7 +526,8 @@ erpnext.utils.update_child_items = function(opts) {
fieldtype: 'Float',
fieldname: "conversion_factor",
in_list_view: 1,
label: __("Conversion Factor")
label: __("Conversion Factor"),
precision: get_precision('conversion_factor')
})
}
@ -677,6 +683,7 @@ erpnext.utils.map_current_doc = function(opts) {
date_field: opts.date_field || undefined,
setters: opts.setters,
get_query: opts.get_query,
add_filters_group: 1,
action: function(selections, args) {
let values = selections;
if(values.length === 0){

View File

@ -1,14 +0,0 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt
frappe.ui.form.on('Website Theme', {
validate(frm) {
let theme_scss = frm.doc.theme_scss;
if (theme_scss && (theme_scss.includes('frappe/public/scss/website')
&& !theme_scss.includes('erpnext/public/scss/website'))
) {
frm.set_value('theme_scss',
`${frm.doc.theme_scss}\n@import "erpnext/public/scss/website";`);
}
}
});

View File

@ -23,7 +23,7 @@
{
"hidden": 0,
"label": "Other Reports",
"links": "[\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Lead Details\",\n \"name\": \"Lead Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Address\"\n ],\n \"doctype\": \"Address\",\n \"is_query_report\": true,\n \"label\": \"Customer Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"route_options\": {\n \"party_type\": \"Customer\"\n },\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Available Stock for Packing Items\",\n \"name\": \"Available Stock for Packing Items\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Pending SO Items For Purchase Request\",\n \"name\": \"Pending SO Items For Purchase Request\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Delivery Note Trends\",\n \"name\": \"Delivery Note Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Invoice Trends\",\n \"name\": \"Sales Invoice Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customer Credit Balance\",\n \"name\": \"Customer Credit Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customers Without Any Sales Transactions\",\n \"name\": \"Customers Without Any Sales Transactions\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Sales Partners Commission\",\n \"name\": \"Sales Partners Commission\",\n \"type\": \"report\"\n }\n]"
"links": "[\n {\n \"dependencies\": [\n \"Lead\"\n ],\n \"doctype\": \"Lead\",\n \"is_query_report\": true,\n \"label\": \"Lead Details\",\n \"name\": \"Lead Details\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Address\"\n ],\n \"doctype\": \"Address\",\n \"is_query_report\": true,\n \"label\": \"Customer Addresses And Contacts\",\n \"name\": \"Address And Contacts\",\n \"route_options\": {\n \"party_type\": \"Customer\"\n },\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Available Stock for Packing Items\",\n \"name\": \"Available Stock for Packing Items\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Pending SO Items For Purchase Request\",\n \"name\": \"Pending SO Items For Purchase Request\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Delivery Note Trends\",\n \"name\": \"Delivery Note Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Invoice Trends\",\n \"name\": \"Sales Invoice Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customer Credit Balance\",\n \"name\": \"Customer Credit Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customers Without Any Sales Transactions\",\n \"name\": \"Customers Without Any Sales Transactions\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Sales Partners Commission\",\n \"name\": \"Sales Partners Commission\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Territory Target Variance Based On Item Group\",\n \"name\": \"Territory Target Variance Based On Item Group\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Person Target Variance Based On Item Group\",\n \"name\": \"Sales Person Target Variance Based On Item Group\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Partner Target Variance Based On Item Group\",\n \"name\": \"Sales Partner Target Variance based on Item Group\",\n \"type\": \"report\"\n }\n \n]"
}
],
"category": "Modules",
@ -44,7 +44,7 @@
"idx": 0,
"is_standard": 1,
"label": "Selling",
"modified": "2020-08-15 10:12:53.131621",
"modified": "2020-10-08 10:23:09.984377",
"modified_by": "Administrator",
"module": "Selling",
"name": "Selling",

View File

@ -132,7 +132,7 @@ class Customer(TransactionBase):
address = frappe.get_doc('Address', address_name.get('name'))
if not address.has_link('Customer', self.name):
address.append('links', dict(link_doctype='Customer', link_name=self.name))
address.save()
address.save(ignore_permissions=self.flags.ignore_permissions)
lead = frappe.db.get_value("Lead", self.lead_name, ["organization_lead", "lead_name", "email_id", "phone", "mobile_no", "gender", "salutation"], as_dict=True)
@ -150,7 +150,7 @@ class Customer(TransactionBase):
contact = frappe.get_doc('Contact', contact_name.get('name'))
if not contact.has_link('Customer', self.name):
contact.append('links', dict(link_doctype='Customer', link_name=self.name))
contact.save()
contact.save(ignore_permissions=self.flags.ignore_permissions)
else:
lead.lead_name = lead.lead_name.lstrip().split(" ")

View File

@ -108,6 +108,10 @@ class TestQuotation(unittest.TestCase):
sales_order.transaction_date = nowdate()
sales_order.insert()
# Remove any unknown taxes if applied
sales_order.set('taxes', [])
sales_order.save()
self.assertEqual(sales_order.payment_schedule[0].payment_amount, 8906.00)
self.assertEqual(sales_order.payment_schedule[0].due_date, getdate(quotation.transaction_date))
self.assertEqual(sales_order.payment_schedule[1].payment_amount, 8906.00)

View File

@ -46,7 +46,7 @@ QUnit.test("test: quotation", function (assert) {
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 Condtions
// 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");

View File

@ -181,7 +181,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
}
// project
if(flt(doc.per_delivered, 2) < 100 && (order_is_a_sale || order_is_a_custom_sale) && allow_delivery) {
if(flt(doc.per_delivered, 2) < 100) {
this.frm.add_custom_button(__('Project'), () => this.make_project(), __('Create'));
}

View File

@ -1460,7 +1460,7 @@
"idx": 105,
"is_submittable": 1,
"links": [],
"modified": "2020-07-31 14:13:17.962015",
"modified": "2020-10-07 14:30:01.782617",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",
@ -1534,7 +1534,7 @@
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "customer",
"title_field": "customer",
"title_field": "customer_name",
"track_changes": 1,
"track_seen": 1
}

View File

@ -989,7 +989,6 @@ def make_raw_material_request(items, company, sales_order, project=None):
doctype = 'Material Request',
transaction_date = nowdate(),
company = company,
requested_by = frappe.session.user,
material_request_type = 'Purchase'
))
for item in raw_materials:

View File

@ -89,6 +89,8 @@ class TestSalesOrder(unittest.TestCase):
self.assertEqual(len(si.get("items")), 1)
si.insert()
si.set('taxes', [])
si.save()
self.assertEqual(si.payment_schedule[0].payment_amount, 500.0)
self.assertEqual(si.payment_schedule[0].due_date, so.transaction_date)
@ -401,6 +403,22 @@ class TestSalesOrder(unittest.TestCase):
trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 2, 'docname': so.items[0].name}])
self.assertRaises(frappe.ValidationError, update_child_qty_rate,'Sales Order', trans_item, so.name)
def test_update_child_with_precision(self):
from frappe.model.meta import get_field_precision
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
precision = get_field_precision(frappe.get_meta("Sales Order Item").get_field("rate"))
make_property_setter("Sales Order Item", "rate", "precision", 7, "Currency")
so = make_sales_order(item_code= "_Test Item", qty=4, rate=200.34664)
trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200.34669, 'qty' : 4, 'docname': so.items[0].name}])
update_child_qty_rate('Sales Order', trans_item, so.name)
so.reload()
self.assertEqual(so.items[0].rate, 200.34669)
make_property_setter("Sales Order Item", "rate", "precision", precision, "Currency")
def test_update_child_perm(self):
so = make_sales_order(item_code= "_Test Item", qty=4)

View File

@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr
from frappe.utils import cstr, cint
from frappe import msgprint, throw, _
from frappe.model.document import Document
@ -159,7 +159,7 @@ class NamingSeries(Document):
prefix = self.parse_naming_series()
self.insert_series(prefix)
frappe.db.sql("update `tabSeries` set current = %s where name = %s",
(self.current_value, prefix))
(cint(self.current_value), prefix))
msgprint(_("Series Updated Successfully"))
else:
msgprint(_("Please select prefix first"))

View File

@ -96,7 +96,9 @@ def place_order():
def request_for_quotation():
quotation = _get_cart_quotation()
quotation.flags.ignore_permissions = True
quotation.submit()
quotation.save()
if not get_shopping_cart_settings().save_quotations_as_draft:
quotation.submit()
return quotation.name
@frappe.whitelist()

View File

@ -27,6 +27,7 @@
"enable_checkout",
"payment_success_url",
"column_break_11",
"save_quotations_as_draft",
"payment_gateway_account"
],
"fields": [
@ -166,13 +167,20 @@
"fieldname": "enable_variants",
"fieldtype": "Check",
"label": "Enable Variants"
},
{
"default": "0",
"depends_on": "eval: doc.enable_checkout == 0",
"fieldname": "save_quotations_as_draft",
"fieldtype": "Check",
"label": "Save Quotations as Draft"
}
],
"icon": "fa fa-shopping-cart",
"idx": 1,
"issingle": 1,
"links": [],
"modified": "2020-08-02 18:21:43.873303",
"modified": "2020-09-24 16:28:07.192525",
"modified_by": "Administrator",
"module": "Shopping Cart",
"name": "Shopping Cart Settings",

View File

@ -3,7 +3,7 @@
{
"hidden": 0,
"label": "Items and Pricing",
"links": "[\n {\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Item Group\",\n \"link\": \"Tree/Item Group\",\n \"name\": \"Item Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Shipping Rule\",\n \"name\": \"Shipping Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Alternative\",\n \"name\": \"Item Alternative\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Manufacturer\",\n \"name\": \"Item Manufacturer\",\n \"type\": \"doctype\"\n }\n]"
"links": "[\n {\n \"label\": \"Item\",\n \"name\": \"Item\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Item Group\",\n \"link\": \"Tree/Item Group\",\n \"name\": \"Item Group\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Product Bundle\",\n \"name\": \"Product Bundle\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Price List\",\n \"name\": \"Price List\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Price\",\n \"name\": \"Item Price\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Shipping Rule\",\n \"name\": \"Shipping Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Pricing Rule\",\n \"name\": \"Pricing Rule\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Alternative\",\n \"name\": \"Item Alternative\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Manufacturer\",\n \"name\": \"Item Manufacturer\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Customs Tariff Number\",\n \"name\": \"Customs Tariff Number\",\n \"type\": \"doctype\"\n }\n]"
},
{
"hidden": 0,
@ -18,7 +18,7 @@
{
"hidden": 0,
"label": "Settings",
"links": "[\n {\n \"label\": \"Stock Settings\",\n \"name\": \"Stock Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Warehouse\",\n \"name\": \"Warehouse\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Unit of Measure (UOM)\",\n \"name\": \"UOM\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Variant Settings\",\n \"name\": \"Item Variant Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Brand\",\n \"name\": \"Brand\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Attribute\",\n \"name\": \"Item Attribute\",\n \"type\": \"doctype\"\n }\n]"
"links": "[\n {\n \"label\": \"Stock Settings\",\n \"name\": \"Stock Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Warehouse\",\n \"name\": \"Warehouse\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Unit of Measure (UOM)\",\n \"name\": \"UOM\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Variant Settings\",\n \"name\": \"Item Variant Settings\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Brand\",\n \"name\": \"Brand\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Item Attribute\",\n \"name\": \"Item Attribute\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"UOM Conversion Factor\",\n \"name\": \"UOM Conversion Factor\",\n \"type\": \"doctype\"\n }\n]"
},
{
"hidden": 0,
@ -58,7 +58,7 @@
"idx": 0,
"is_standard": 1,
"label": "Stock",
"modified": "2020-08-11 17:29:32.626067",
"modified": "2020-10-07 18:40:17.130207",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock",

View File

@ -984,9 +984,7 @@ class Item(WebsiteGenerator):
if self.stock_ledger_created():
return True
elif frappe.db.get_value(doctype, filters={"item_code": self.name, "docstatus": 1}) or \
frappe.db.get_value("Production Order",
filters={"production_item": self.name, "docstatus": 1}):
elif frappe.db.get_value(doctype, filters={"item_code": self.name, "docstatus": 1}):
return True
def validate_auto_reorder_enabled_in_stock_settings(self):

View File

@ -1,357 +1,97 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:attribute_name",
"beta": 0,
"creation": "2014-09-26 03:49:54.899170",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 0,
"actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:attribute_name",
"creation": "2014-09-26 03:49:54.899170",
"doctype": "DocType",
"document_type": "Setup",
"engine": "InnoDB",
"field_order": [
"attribute_name",
"numeric_values",
"section_break_4",
"from_range",
"increment",
"column_break_8",
"to_range",
"section_break_5",
"item_attribute_values"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "attribute_name",
"fieldtype": "Data",
"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": "Attribute Name",
"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": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"fieldname": "attribute_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Attribute Name",
"reqd": 1,
"unique": 1
},
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"fieldname": "numeric_values",
"fieldtype": "Check",
"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": "Numeric Values",
"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,
"translatable": 0,
"unique": 0
},
"default": "0",
"fieldname": "numeric_values",
"fieldtype": "Check",
"label": "Numeric Values"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "numeric_values",
"fieldname": "section_break_4",
"fieldtype": "Section 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,
"translatable": 0,
"unique": 0
},
"depends_on": "numeric_values",
"fieldname": "section_break_4",
"fieldtype": "Section Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "from_range",
"fieldtype": "Float",
"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": "From Range",
"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,
"translatable": 0,
"unique": 0
},
"default": "0",
"fieldname": "from_range",
"fieldtype": "Float",
"label": "From Range"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "increment",
"fieldtype": "Float",
"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": "Increment",
"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,
"translatable": 0,
"unique": 0
},
"default": "0",
"fieldname": "increment",
"fieldtype": "Float",
"label": "Increment"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_8",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "column_break_8",
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "to_range",
"fieldtype": "Float",
"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": "To Range",
"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,
"translatable": 0,
"unique": 0
},
"default": "0",
"fieldname": "to_range",
"fieldtype": "Float",
"label": "To Range"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval: !doc.numeric_values",
"fieldname": "section_break_5",
"fieldtype": "Section 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,
"translatable": 0,
"unique": 0
},
"depends_on": "eval: !doc.numeric_values",
"fieldname": "section_break_5",
"fieldtype": "Section Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "item_attribute_values",
"fieldtype": "Table",
"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": "Item Attribute Values",
"length": 0,
"no_copy": 0,
"options": "Item Attribute Value",
"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,
"translatable": 0,
"unique": 0
"fieldname": "item_attribute_values",
"fieldtype": "Table",
"label": "Item Attribute Values",
"options": "Item Attribute Value"
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-edit",
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-01-01 13:17:46.524806",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item Attribute",
"name_case": "",
"owner": "Administrator",
],
"icon": "fa fa-edit",
"index_web_pages_for_search": 1,
"links": [],
"modified": "2020-10-02 12:03:02.359202",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item Attribute",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 1,
"role": "Item Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"create": 1,
"delete": 1,
"read": 1,
"report": 1,
"role": "Item Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe import _
from frappe.utils import flt
from erpnext.controllers.item_variant import (validate_is_incremental,
validate_item_attribute_value, InvalidItemAttributeValueError)
@ -28,9 +29,18 @@ class ItemAttribute(Document):
'''Validate that if there are existing items with attributes, they are valid'''
attributes_list = [d.attribute_value for d in self.item_attribute_values]
for item in frappe.db.sql('''select i.name, iva.attribute_value as value
from `tabItem Variant Attribute` iva, `tabItem` i where iva.attribute = %s
and iva.parent = i.name and i.has_variants = 0''', self.name, as_dict=1):
# Get Item Variant Attribute details of variant items
items = frappe.db.sql("""
select
i.name, iva.attribute_value as value
from
`tabItem Variant Attribute` iva, `tabItem` i
where
iva.attribute = %(attribute)s
and iva.parent = i.name and
i.variant_of is not null and i.variant_of != ''""", {"attribute" : self.name}, as_dict=1)
for item in items:
if self.numeric_values:
validate_is_incremental(self, self.name, item.value, item.name)
else:
@ -42,7 +52,7 @@ class ItemAttribute(Document):
if self.from_range is None or self.to_range is None:
frappe.throw(_("Please specify from/to range"))
elif self.from_range >= self.to_range:
elif flt(self.from_range) >= flt(self.to_range):
frappe.throw(_("From Range has to be less than To Range"))
if not self.increment:

View File

@ -50,16 +50,18 @@ class ItemPrice(Document):
def check_duplicates(self):
conditions = "where item_code=%(item_code)s and price_list=%(price_list)s and name != %(name)s"
condition_data_dict = dict(item_code=self.item_code, price_list=self.price_list, name=self.name)
for field in ['uom', 'valid_from',
'valid_upto', 'packing_unit', 'customer', 'supplier']:
if self.get(field):
conditions += " and {0} = %({1})s".format(field, field)
condition_data_dict[field] = self.get(field)
price_list_rate = frappe.db.sql("""
SELECT price_list_rate
FROM `tabItem Price`
{conditions} """.format(conditions=conditions), self.as_dict())
{conditions} """.format(conditions=conditions), condition_data_dict)
if price_list_rate :
frappe.throw(_("Item Price appears multiple times based on Price List, Supplier/Customer, Currency, Item, UOM, Qty and Dates."), ItemPriceDuplicateItem)

View File

@ -280,7 +280,8 @@ frappe.ui.form.on('Material Request', {
fieldname:'default_supplier',
fieldtype: 'Link',
options: 'Supplier',
description: __('Select a Supplier from the Default Supplier List of the items below.'),
description: __('Select a Supplier from the Default Suppliers of the items below. \
On selection, a Purchase Order will be made against items belonging to the selected Supplier only.'),
get_query: () => {
return{
query: "erpnext.stock.doctype.material_request.material_request.get_default_supplier_query",

View File

@ -13,7 +13,9 @@
"material_request_type",
"transfer_status",
"customer",
"status",
"column_break_2",
"transaction_date",
"schedule_date",
"company",
"amended_from",
@ -25,11 +27,8 @@
"scan_barcode",
"items",
"more_info",
"requested_by",
"transaction_date",
"column_break2",
"status",
"per_ordered",
"column_break2",
"per_received",
"printing_details",
"letter_head",
@ -82,7 +81,8 @@
"fieldname": "customer",
"fieldtype": "Link",
"label": "Customer",
"options": "Customer"
"options": "Customer",
"print_hide": 1
},
{
"fieldname": "column_break_2",
@ -92,12 +92,12 @@
"allow_on_submit": 1,
"fieldname": "schedule_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Required By"
},
{
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"oldfieldname": "company",
@ -153,18 +153,10 @@
"oldfieldtype": "Section Break",
"options": "fa fa-file-text"
},
{
"fieldname": "requested_by",
"fieldtype": "Data",
"in_standard_filter": 1,
"label": "Requested For",
"options": "Email"
},
{
"default": "Today",
"fieldname": "transaction_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Transaction Date",
"no_copy": 1,
"oldfieldname": "transaction_date",
@ -197,7 +189,7 @@
"width": "100px"
},
{
"depends_on": "eval:doc.docstatus==1",
"depends_on": "eval:doc.per_ordered > 0",
"fieldname": "per_ordered",
"fieldtype": "Percent",
"label": "% Ordered",
@ -208,7 +200,7 @@
"read_only": 1
},
{
"depends_on": "eval:doc.docstatus==1",
"depends_on": "eval:doc.per_received > 0",
"fieldname": "per_received",
"fieldtype": "Percent",
"label": "% Received",
@ -282,13 +274,15 @@
},
{
"fieldname": "warehouse_section",
"fieldtype": "Section Break"
"fieldtype": "Section Break",
"label": "Warehouse"
},
{
"description": "Sets 'For Warehouse' in each row of the Items table.",
"description": "Sets 'Target Warehouse' in each row of the Items table.",
"fieldname": "set_warehouse",
"fieldtype": "Link",
"label": "Set Warehouse",
"in_list_view": 1,
"label": "Set Target Warehouse",
"options": "Warehouse"
},
{
@ -300,9 +294,10 @@
},
{
"depends_on": "eval:doc.material_request_type == 'Material Transfer'",
"description": "Sets 'Source Warehouse' in each row of the Items table.",
"fieldname": "set_from_warehouse",
"fieldtype": "Link",
"label": "Set From Warehouse",
"label": "Set Source Warehouse",
"options": "Warehouse"
},
{
@ -319,7 +314,7 @@
"idx": 70,
"is_submittable": 1,
"links": [],
"modified": "2020-08-10 13:27:54.891058",
"modified": "2020-09-19 01:04:09.285862",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request",

View File

@ -7,7 +7,7 @@ def get_data():
'fieldname': 'material_request',
'transactions': [
{
'label': _('Related'),
'label': _('Reference'),
'items': ['Request for Quotation', 'Supplier Quotation', 'Purchase Order']
},
{

View File

@ -13,12 +13,10 @@
"schedule_date",
"section_break_4",
"description",
"column_break_12",
"item_group",
"brand",
"image_section",
"image",
"column_break_12",
"manufacturer_part_no",
"quantity_and_warehouse",
"qty",
"stock_uom",
@ -28,12 +26,26 @@
"uom",
"conversion_factor",
"stock_qty",
"qty_info_sec_break",
"min_order_qty",
"projected_qty",
"qty_info_col_break",
"actual_qty",
"ordered_qty",
"received_qty",
"rate_and_amount_section_break",
"rate",
"col_break3",
"amount",
"manufacture_details",
"manufacturer",
"manufacturer_part_no",
"col_break_mfg",
"bom_no",
"accounting_dimensions_section",
"project",
"dimension_col_break",
"cost_center",
"more_info",
"lead_time_date",
"sales_order",
@ -41,19 +53,7 @@
"production_plan",
"material_request_plan_item",
"col_break4",
"min_order_qty",
"projected_qty",
"actual_qty",
"ordered_qty",
"received_qty",
"accounting_details",
"expense_account",
"accounting_dimensions_section",
"project",
"dimension_col_break",
"cost_center",
"section_break_37",
"bom_no",
"section_break_46",
"page_break"
],
@ -164,7 +164,7 @@
"fieldname": "warehouse",
"fieldtype": "Link",
"in_list_view": 1,
"label": "For Warehouse",
"label": "Target Warehouse",
"oldfieldname": "warehouse",
"oldfieldtype": "Link",
"options": "Warehouse",
@ -191,12 +191,14 @@
{
"fieldname": "rate",
"fieldtype": "Currency",
"label": "Rate"
"label": "Rate",
"print_hide": 1
},
{
"fieldname": "amount",
"fieldtype": "Currency",
"label": "Amount",
"print_hide": 1,
"read_only": 1
},
{
@ -326,6 +328,7 @@
"report_hide": 1
},
{
"depends_on": "eval:doc.docstatus==1",
"fieldname": "ordered_qty",
"fieldtype": "Float",
"label": "Completed Qty",
@ -335,12 +338,6 @@
"print_hide": 1,
"read_only": 1
},
{
"collapsible": 1,
"fieldname": "accounting_details",
"fieldtype": "Section Break",
"label": "Accounting Details"
},
{
"fieldname": "expense_account",
"fieldtype": "Link",
@ -367,21 +364,10 @@
"print_hide": 1
},
{
"collapsible": 1,
"fieldname": "image_section",
"fieldtype": "Section Break",
"label": "Image"
},
{
"depends_on": "eval:parent.material_request_type == \"Manufacture\"",
"fieldname": "section_break_37",
"fieldtype": "Section Break",
"label": "Manufacturing"
},
{
"depends_on": "eval:doc.docstatus==1",
"fieldname": "received_qty",
"fieldtype": "Float",
"label": "Received Quantity",
"label": "Received Qty",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
@ -398,6 +384,7 @@
},
{
"collapsible": 1,
"depends_on": "eval:in_list([\"Manufacture\", \"Purchase\"], parent.material_request_type)",
"fieldname": "manufacture_details",
"fieldtype": "Section Break",
"label": "Manufacture"
@ -430,10 +417,11 @@
"depends_on": "eval:parent.material_request_type == \"Material Transfer\"",
"fieldname": "from_warehouse",
"fieldtype": "Link",
"label": "Source Warehouse (Material Transfer)",
"label": "Source Warehouse",
"options": "Warehouse"
},
{
"allow_on_submit": 1,
"fieldname": "bom_no",
"fieldtype": "Link",
"label": "BOM No",
@ -444,12 +432,25 @@
{
"fieldname": "section_break_46",
"fieldtype": "Section Break"
},
{
"fieldname": "col_break_mfg",
"fieldtype": "Column Break"
},
{
"fieldname": "qty_info_sec_break",
"fieldtype": "Section Break"
},
{
"fieldname": "qty_info_col_break",
"fieldtype": "Column Break"
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-05-15 09:00:00.992835",
"modified": "2020-10-02 11:44:36.553064",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request Item",

View File

@ -77,38 +77,33 @@ def get_price_list():
return item_rate_map
def get_last_purchase_rate():
item_last_purchase_rate_map = {}
query = """select * from (select
result.item_code,
result.base_rate
from (
(select
po_item.item_code,
po_item.item_name,
po.transaction_date as posting_date,
po_item.base_price_list_rate,
po_item.discount_percentage,
po_item.base_rate
from `tabPurchase Order` po, `tabPurchase Order Item` po_item
where po.name = po_item.parent and po.docstatus = 1)
union
(select
pr_item.item_code,
pr_item.item_name,
pr.posting_date,
pr_item.base_price_list_rate,
pr_item.discount_percentage,
pr_item.base_rate
from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
where pr.name = pr_item.parent and pr.docstatus = 1)
) result
order by result.item_code asc, result.posting_date desc) result_wrapper
group by item_code"""
query = """select * from (
(select
po_item.item_code,
po.transaction_date as posting_date,
po_item.base_rate
from `tabPurchase Order` po, `tabPurchase Order Item` po_item
where po.name = po_item.parent and po.docstatus = 1)
union
(select
pr_item.item_code,
pr.posting_date,
pr_item.base_rate
from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
where pr.name = pr_item.parent and pr.docstatus = 1)
union
(select
pi_item.item_code,
pi.posting_date,
pi_item.base_rate
from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pi_item
where pi.name = pi_item.parent and pi.docstatus = 1 and pi.update_stock = 1)
) result order by result.item_code asc, result.posting_date asc"""
for d in frappe.db.sql(query, as_dict=1):
item_last_purchase_rate_map.setdefault(d.item_code, d.base_rate)
item_last_purchase_rate_map[d.item_code] = d.base_rate
return item_last_purchase_rate_map

View File

@ -10,7 +10,10 @@
{{ product_info.price.formatted_price_sales_uom }}
<small class="text-muted">({{ product_info.price.formatted_price }} / {{ product_info.uom }})</small>
</h4>
{% else %}
{{ _("Unit of Measurement") }} : {{ product_info.uom }}
{% endif %}
{% if cart_settings.show_stock_availability %}
<div>
{% if product_info.in_stock == 0 %}

View File

@ -14,7 +14,11 @@
</div>
</div>
<div class="col-sm-3 text-right bold">
{{ doc.get_formatted("grand_total") }}
{% if doc.doctype == "Quotation" and not doc.docstatus %}
{{ _("Pending") }}
{% else %}
{{ doc.get_formatted("grand_total") }}
{% endif %}
</div>
</div>
<a class="transaction-item-link" href="/{{ pathname }}/{{ doc.name }}">Link</a>

View File

@ -12,22 +12,21 @@
{% endblock %}
{% block header_actions %}
<div class="dropdown">
<button class="btn btn-outline-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span>{{ _('Actions') }}</span>
<b class="caret"></b>
</button>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
{% if doc.doctype == 'Purchase Order' %}
<a class="dropdown-item" href="/api/method/erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice_from_portal?purchase_order_name={{ doc.name }}" data-action="make_purchase_invoice">{{ _("Make Purchase Invoice") }}</a>
{% endif %}
<a class="dropdown-item" href='/printview?doctype={{ doc.doctype}}&name={{ doc.name }}&format={{ print_format }}'
target="_blank" rel="noopener noreferrer">
{{ _("Print") }}
</a>
</ul>
</div>
<div class="dropdown">
<button class="btn btn-outline-secondary dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span>{{ _('Actions') }}</span>
<b class="caret"></b>
</button>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
{% if doc.doctype == 'Purchase Order' %}
<a class="dropdown-item" href="/api/method/erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice_from_portal?purchase_order_name={{ doc.name }}" data-action="make_purchase_invoice">{{ _("Make Purchase Invoice") }}</a>
{% endif %}
<a class="dropdown-item" href='/printview?doctype={{ doc.doctype}}&name={{ doc.name }}&format={{ print_format }}'
target="_blank" rel="noopener noreferrer">
{{ _("Print") }}
</a>
</ul>
</div>
{% endblock %}
{% block page_content %}
@ -35,7 +34,11 @@
<div class="row transaction-subheading">
<div class="col-6">
<span class="indicator {{ doc.indicator_color or ("blue" if doc.docstatus==1 else "darkgrey") }}">
{{ _(doc.get('indicator_title')) or _(doc.status) or _("Submitted") }}
{% if doc.doctype == "Quotation" and not doc.docstatus %}
{{ _("Pending") }}
{% else %}
{{ _(doc.get('indicator_title')) or _(doc.status) or _("Submitted") }}
{% endif %}
</span>
</div>
<div class="col-6 text-muted text-right small">
@ -95,7 +98,6 @@
</div>
{% endfor %}
</div>
<!-- taxes -->
<div class="order-taxes d-flex justify-content-end">
<table>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -25,4 +25,3 @@ All Lead (Open),Alle Bly (Open),
Default Selling Cost Center,Standard Selling Cost center,
"Attach .csv file with two columns, one for the old name and one for the new name","Vedhæfte .csv fil med to kolonner, en for det gamle navn og et til det nye navn",
Lead Details,Bly Detaljer,
Lead Id,Bly Id,

1 'Opening' 'Åbning'
25 Default Selling Cost Center Standard Selling Cost center
26 Attach .csv file with two columns, one for the old name and one for the new name Vedhæfte .csv fil med to kolonner, en for det gamle navn og et til det nye navn
27 Lead Details Bly Detaljer
Lead Id Bly Id

Some files were not shown because too many files have changed in this diff Show More