fix: merge conflict

This commit is contained in:
Nabin Hait 2021-07-16 15:58:50 +05:30
commit 11475487fb
24 changed files with 462 additions and 1149 deletions

View File

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

View File

@ -16,7 +16,6 @@ class ChartofAccountsImporter(Document):
def validate(self): def validate(self):
validate_accounts(self.import_file) validate_accounts(self.import_file)
@frappe.whitelist() @frappe.whitelist()
def validate_company(company): def validate_company(company):
parent_company, allow_account_creation_against_child_company = frappe.db.get_value('Company', parent_company, allow_account_creation_against_child_company = frappe.db.get_value('Company',
@ -307,7 +306,6 @@ def validate_accounts(file_name):
validate_account_types(accounts_dict) validate_account_types(accounts_dict)
return [True, len(accounts)] return [True, len(accounts)]
def validate_root(accounts): def validate_root(accounts):

View File

@ -139,7 +139,7 @@ def create_dunning_type_with_zero_interest_rate():
dunning_type.append( dunning_type.append(
"dunning_letter_text", { "dunning_letter_text", {
'language': 'en', 'language': 'en',
'body_text': 'We have still not received payment for our invoice ', 'body_text': 'We have still not received payment for our invoice ',
'closing_text': 'We kindly request that you pay the outstanding amount immediately, and late fees.' 'closing_text': 'We kindly request that you pay the outstanding amount immediately, and late fees.'
} }
) )

View File

@ -1,24 +1,6 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt // License: GNU General Public License v3. See license.txt
cur_frm.add_fetch("customer", "customer_group", "customer_group" );
cur_frm.add_fetch("supplier", "supplier_group_name", "supplier_group" );
frappe.ui.form.on("Tax Rule", "tax_type", function(frm) {
frm.toggle_reqd("sales_tax_template", frm.doc.tax_type=="Sales");
frm.toggle_reqd("purchase_tax_template", frm.doc.tax_type=="Purchase");
})
frappe.ui.form.on("Tax Rule", "onload", function(frm) {
if(frm.doc.__islocal) {
frm.set_value("use_for_shopping_cart", 1);
}
})
frappe.ui.form.on("Tax Rule", "refresh", function(frm) {
frappe.ui.form.trigger("Tax Rule", "tax_type");
})
frappe.ui.form.on("Tax Rule", "customer", function(frm) { frappe.ui.form.on("Tax Rule", "customer", function(frm) {
if(frm.doc.customer) { if(frm.doc.customer) {
frappe.call({ frappe.call({

File diff suppressed because it is too large Load Diff

View File

@ -50,7 +50,7 @@ class TestTaxRule(unittest.TestCase):
tax_rule1 = make_tax_rule(customer_group= "All Customer Groups", tax_rule1 = make_tax_rule(customer_group= "All Customer Groups",
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1, from_date = "2015-01-01") sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1, from_date = "2015-01-01")
tax_rule1.save() tax_rule1.save()
self.assertEqual(get_tax_template("2015-01-01", {"customer_group" : "Commercial", "use_for_shopping_cart":0}), self.assertEqual(get_tax_template("2015-01-01", {"customer_group" : "Commercial", "use_for_shopping_cart":1}),
"_Test Sales Taxes and Charges Template - _TC") "_Test Sales Taxes and Charges Template - _TC")
def test_conflict_with_overlapping_dates(self): def test_conflict_with_overlapping_dates(self):

View File

@ -0,0 +1,69 @@
# Version 13.7.0 Release Notes
### Features & Enhancements
- Optionally allow rejected quality inspection on submission ([#26133](https://github.com/frappe/erpnext/pull/26133))
- Bootstrapped GST Setup for India ([#25415](https://github.com/frappe/erpnext/pull/25415))
- Fetching details from supplier/customer groups ([#26454](https://github.com/frappe/erpnext/pull/26454))
- Provision to make subcontracted purchase order from the production plan ([#26240](https://github.com/frappe/erpnext/pull/26240))
- Optimized code for reposting item valuation ([#26432](https://github.com/frappe/erpnext/pull/26432))
### Fixes
- Auto process deferred accounting for multi-company setup ([#26277](https://github.com/frappe/erpnext/pull/26277))
- Error while fetching item taxes ([#26218](https://github.com/frappe/erpnext/pull/26218))
- Validation check for batch for stock reconciliation type in stock entry(bp #26370 ) ([#26488](https://github.com/frappe/erpnext/pull/26488))
- Error popup for COA errors ([#26358](https://github.com/frappe/erpnext/pull/26358))
- Precision for expected values in payment entry test ([#26394](https://github.com/frappe/erpnext/pull/26394))
- Bank statement import ([#26287](https://github.com/frappe/erpnext/pull/26287))
- LMS progress issue ([#26253](https://github.com/frappe/erpnext/pull/26253))
- Paging buttons not working on item group portal page ([#26497](https://github.com/frappe/erpnext/pull/26497))
- Omit item discount amount for e-invoicing ([#26353](https://github.com/frappe/erpnext/pull/26353))
- Validate LCV for Invoices without Update Stock ([#26333](https://github.com/frappe/erpnext/pull/26333))
- Remove cancelled entries in consolidated financial statements ([#26331](https://github.com/frappe/erpnext/pull/26331))
- Fetching employee in payroll entry ([#26271](https://github.com/frappe/erpnext/pull/26271))
- To fetch the correct field in Tax Rule ([#25927](https://github.com/frappe/erpnext/pull/25927))
- Order and time of operations in multilevel BOM work order ([#25886](https://github.com/frappe/erpnext/pull/25886))
- Fixed Budget Variance Graph color from all black to default ([#26368](https://github.com/frappe/erpnext/pull/26368))
- TDS computation summary shows cancelled invoices (#26456) ([#26486](https://github.com/frappe/erpnext/pull/26486))
- Do not consider cancelled entries in party dashboard ([#26231](https://github.com/frappe/erpnext/pull/26231))
- Add validation for 'for_qty' else throws errors ([#25829](https://github.com/frappe/erpnext/pull/25829))
- Move the rename abbreviation job to long queue (#26434) ([#26462](https://github.com/frappe/erpnext/pull/26462))
- Query for Training Event ([#26388](https://github.com/frappe/erpnext/pull/26388))
- Item group portal issues (backport) ([#26493](https://github.com/frappe/erpnext/pull/26493))
- When lead is created with mobile_no, mobile_no value gets lost ([#26298](https://github.com/frappe/erpnext/pull/26298))
- WIP needs to be set before submit on skip_transfer (bp #26499) ([#26507](https://github.com/frappe/erpnext/pull/26507))
- Incorrect valuation rate in stock reconciliation ([#26259](https://github.com/frappe/erpnext/pull/26259))
- Precision rate for packed items in internal transfers ([#26046](https://github.com/frappe/erpnext/pull/26046))
- Changed profitability analysis report width ([#26165](https://github.com/frappe/erpnext/pull/26165))
- Unable to download GSTR-1 json ([#26468](https://github.com/frappe/erpnext/pull/26468))
- Unallocated amount in Payment Entry after taxes ([#26472](https://github.com/frappe/erpnext/pull/26472))
- Include Stock Reco logic in `update_qty_in_future_sle` ([#26158](https://github.com/frappe/erpnext/pull/26158))
- Update cost not working in the draft BOM ([#26279](https://github.com/frappe/erpnext/pull/26279))
- Cancellation of Loan Security Pledges ([#26252](https://github.com/frappe/erpnext/pull/26252))
- fix(e-invoicing): allow export invoice even if no taxes applied (#26363) ([#26405](https://github.com/frappe/erpnext/pull/26405))
- Delete accounts (an empty file) ([#25323](https://github.com/frappe/erpnext/pull/25323))
- Errors on parallel requests creation of company for India ([#26470](https://github.com/frappe/erpnext/pull/26470))
- Incorrect bom no added for non-variant items on variant boms ([#26320](https://github.com/frappe/erpnext/pull/26320))
- Incorrect discount amount on amended document ([#26466](https://github.com/frappe/erpnext/pull/26466))
- Added a message to enable appointment booking if disabled ([#26334](https://github.com/frappe/erpnext/pull/26334))
- fix(pos): taxes amount in pos item cart ([#26411](https://github.com/frappe/erpnext/pull/26411))
- Track changes on batch ([#26382](https://github.com/frappe/erpnext/pull/26382))
- Stock entry with putaway rule not working ([#26350](https://github.com/frappe/erpnext/pull/26350))
- Only "Tax" type accounts should be shown for selection in GST Settings ([#26300](https://github.com/frappe/erpnext/pull/26300))
- Added permission for employee to book appointment ([#26255](https://github.com/frappe/erpnext/pull/26255))
- Allow to make job card without employee ([#26312](https://github.com/frappe/erpnext/pull/26312))
- Project Portal Enhancements ([#26290](https://github.com/frappe/erpnext/pull/26290))
- BOM stock report not working ([#26332](https://github.com/frappe/erpnext/pull/26332))
- Order Items by weightage in the web items query ([#26284](https://github.com/frappe/erpnext/pull/26284))
- Removed values out of sync validation from stock transactions ([#26226](https://github.com/frappe/erpnext/pull/26226))
- Payroll-entry minor fix ([#26349](https://github.com/frappe/erpnext/pull/26349))
- Allow user to change the To Date in the blanket order even after submit of order ([#26241](https://github.com/frappe/erpnext/pull/26241))
- Value fetching for custom field in POS ([#26367](https://github.com/frappe/erpnext/pull/26367))
- Iteration through accounts only when accounts exist ([#26391](https://github.com/frappe/erpnext/pull/26391))
- Employee Inactive status implications ([#26244](https://github.com/frappe/erpnext/pull/26244))
- Multi-currency issue ([#26458](https://github.com/frappe/erpnext/pull/26458))
- FG item not fetched in manufacture entry ([#26509](https://github.com/frappe/erpnext/pull/26509))
- Set query for training events ([#26303](https://github.com/frappe/erpnext/pull/26303))
- Fetch batch items in stock reconciliation ([#26213](https://github.com/frappe/erpnext/pull/26213))
- Employee selection not working in payroll entry ([#26278](https://github.com/frappe/erpnext/pull/26278))
- POS item cart dom updates (#26459) ([#26461](https://github.com/frappe/erpnext/pull/26461))
- dunning calculation of grand total when rate of interest is 0% ([#26285](https://github.com/frappe/erpnext/pull/26285))

View File

@ -102,7 +102,7 @@
} }
], ],
"links": [], "links": [],
"modified": "2021-06-30 12:09:14.228756", "modified": "2021-06-30 13:09:14.228756",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "CRM", "module": "CRM",
"name": "Appointment", "name": "Appointment",

View File

@ -35,7 +35,9 @@
"no_copy": 1, "no_copy": 1,
"options": "Loan Security Pledge", "options": "Loan Security Pledge",
"print_hide": 1, "print_hide": 1,
"read_only": 1 "read_only": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fetch_from": "loan_application.applicant", "fetch_from": "loan_application.applicant",
@ -45,47 +47,63 @@
"in_standard_filter": 1, "in_standard_filter": 1,
"label": "Applicant", "label": "Applicant",
"options": "applicant_type", "options": "applicant_type",
"reqd": 1 "reqd": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "loan_security_details_section", "fieldname": "loan_security_details_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Loan Security Details" "label": "Loan Security Details",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "column_break_3", "fieldname": "column_break_3",
"fieldtype": "Column Break" "fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "loan", "fieldname": "loan",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Loan", "label": "Loan",
"options": "Loan" "options": "Loan",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "loan_application", "fieldname": "loan_application",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Loan Application", "label": "Loan Application",
"options": "Loan Application" "options": "Loan Application",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "total_security_value", "fieldname": "total_security_value",
"fieldtype": "Currency", "fieldtype": "Currency",
"label": "Total Security Value", "label": "Total Security Value",
"options": "Company:company:default_currency", "options": "Company:company:default_currency",
"read_only": 1 "read_only": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "maximum_loan_value", "fieldname": "maximum_loan_value",
"fieldtype": "Currency", "fieldtype": "Currency",
"label": "Maximum Loan Value", "label": "Maximum Loan Value",
"options": "Company:company:default_currency", "options": "Company:company:default_currency",
"read_only": 1 "read_only": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "loan_details_section", "fieldname": "loan_details_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Loan Details" "label": "Loan Details",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"default": "Requested", "default": "Requested",
@ -94,37 +112,49 @@
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 1, "in_standard_filter": 1,
"label": "Status", "label": "Status",
"options": "Requested\nUnpledged\nPledged\nPartially Pledged", "options": "Requested\nUnpledged\nPledged\nPartially Pledged\nCancelled",
"read_only": 1 "read_only": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "pledge_time", "fieldname": "pledge_time",
"fieldtype": "Datetime", "fieldtype": "Datetime",
"label": "Pledge Time", "label": "Pledge Time",
"read_only": 1 "read_only": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "securities", "fieldname": "securities",
"fieldtype": "Table", "fieldtype": "Table",
"label": "Securities", "label": "Securities",
"options": "Pledge", "options": "Pledge",
"reqd": 1 "reqd": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "column_break_11", "fieldname": "column_break_11",
"fieldtype": "Column Break" "fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "section_break_10", "fieldname": "section_break_10",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Totals" "label": "Totals",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "company", "fieldname": "company",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Company", "label": "Company",
"options": "Company", "options": "Company",
"reqd": 1 "reqd": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fetch_from": "loan.applicant_type", "fetch_from": "loan.applicant_type",
@ -132,35 +162,45 @@
"fieldtype": "Select", "fieldtype": "Select",
"label": "Applicant Type", "label": "Applicant Type",
"options": "Employee\nMember\nCustomer", "options": "Employee\nMember\nCustomer",
"reqd": 1 "reqd": 1,
"show_days": 1,
"show_seconds": 1
}, },
{ {
"collapsible": 1, "collapsible": 1,
"fieldname": "more_information_section", "fieldname": "more_information_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "More Information" "label": "More Information",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"allow_on_submit": 1, "allow_on_submit": 1,
"fieldname": "reference_no", "fieldname": "reference_no",
"fieldtype": "Data", "fieldtype": "Data",
"label": "Reference No" "label": "Reference No",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"fieldname": "column_break_18", "fieldname": "column_break_18",
"fieldtype": "Column Break" "fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
}, },
{ {
"allow_on_submit": 1, "allow_on_submit": 1,
"fieldname": "description", "fieldname": "description",
"fieldtype": "Text", "fieldtype": "Text",
"label": "Description" "label": "Description",
"show_days": 1,
"show_seconds": 1
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2021-04-19 18:23:16.953305", "modified": "2021-06-29 17:15:16.082256",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Loan Management", "module": "Loan Management",
"name": "Loan Security Pledge", "name": "Loan Security Pledge",

View File

@ -23,6 +23,12 @@ class LoanSecurityPledge(Document):
update_shortfall_status(self.loan, self.total_security_value) update_shortfall_status(self.loan, self.total_security_value)
update_loan(self.loan, self.maximum_loan_value) update_loan(self.loan, self.maximum_loan_value)
def on_cancel(self):
if self.loan:
self.db_set("status", "Cancelled")
self.db_set("pledge_time", None)
update_loan(self.loan, self.maximum_loan_value, cancel=1)
def validate_duplicate_securities(self): def validate_duplicate_securities(self):
security_list = [] security_list = []
for security in self.securities: for security in self.securities:
@ -36,7 +42,7 @@ class LoanSecurityPledge(Document):
existing_pledge = '' existing_pledge = ''
if self.loan: if self.loan:
existing_pledge = frappe.db.get_value('Loan Security Pledge', {'loan': self.loan}, ['name']) existing_pledge = frappe.db.get_value('Loan Security Pledge', {'loan': self.loan, 'docstatus': 1}, ['name'])
if existing_pledge: if existing_pledge:
loan_security_type = frappe.db.get_value('Pledge', {'parent': existing_pledge}, ['loan_security_type']) loan_security_type = frappe.db.get_value('Pledge', {'parent': existing_pledge}, ['loan_security_type'])
@ -77,8 +83,12 @@ class LoanSecurityPledge(Document):
self.total_security_value = total_security_value self.total_security_value = total_security_value
self.maximum_loan_value = maximum_loan_value self.maximum_loan_value = maximum_loan_value
def update_loan(loan, maximum_value_against_pledge): def update_loan(loan, maximum_value_against_pledge, cancel=0):
maximum_loan_value = frappe.db.get_value('Loan', {'name': loan}, ['maximum_loan_amount']) maximum_loan_value = frappe.db.get_value('Loan', {'name': loan}, ['maximum_loan_amount'])
frappe.db.sql(""" UPDATE `tabLoan` SET maximum_loan_amount=%s, is_secured_loan=1 if cancel:
WHERE name=%s""", (maximum_loan_value + maximum_value_against_pledge, loan)) frappe.db.sql(""" UPDATE `tabLoan` SET maximum_loan_amount=%s
WHERE name=%s""", (maximum_loan_value - maximum_value_against_pledge, loan))
else:
frappe.db.sql(""" UPDATE `tabLoan` SET maximum_loan_amount=%s, is_secured_loan=1
WHERE name=%s""", (maximum_loan_value + maximum_value_against_pledge, loan))

View File

@ -13,7 +13,7 @@ frappe.ui.form.on('Blanket Order', {
refresh: function(frm) { refresh: function(frm) {
erpnext.hide_company(); erpnext.hide_company();
if (frm.doc.customer && frm.doc.docstatus === 1) { if (frm.doc.customer && frm.doc.docstatus === 1 && frm.doc.to_date > frappe.datetime.get_today()) {
frm.add_custom_button(__("Sales Order"), function() { frm.add_custom_button(__("Sales Order"), function() {
frappe.model.open_mapped_doc({ frappe.model.open_mapped_doc({
method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_order", method: "erpnext.manufacturing.doctype.blanket_order.blanket_order.make_order",

View File

@ -1,4 +1,5 @@
{ {
"actions": [],
"autoname": "naming_series:", "autoname": "naming_series:",
"creation": "2018-05-24 07:18:08.256060", "creation": "2018-05-24 07:18:08.256060",
"doctype": "DocType", "doctype": "DocType",
@ -79,6 +80,7 @@
"reqd": 1 "reqd": 1
}, },
{ {
"allow_on_submit": 1,
"fieldname": "to_date", "fieldname": "to_date",
"fieldtype": "Date", "fieldtype": "Date",
"label": "To Date", "label": "To Date",
@ -129,8 +131,10 @@
"label": "Terms and Conditions Details" "label": "Terms and Conditions Details"
} }
], ],
"index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"modified": "2019-11-18 19:37:37.151686", "links": [],
"modified": "2021-06-29 00:30:30.621636",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "Blanket Order", "name": "Blanket Order",

View File

@ -713,7 +713,8 @@ def get_bom_item_rate(args, bom_doc):
"conversion_rate": 1, # Passed conversion rate as 1 purposefully, as conversion rate is applied at the end of the function "conversion_rate": 1, # Passed conversion rate as 1 purposefully, as conversion rate is applied at the end of the function
"conversion_factor": args.get("conversion_factor") or 1, "conversion_factor": args.get("conversion_factor") or 1,
"plc_conversion_rate": 1, "plc_conversion_rate": 1,
"ignore_party": True "ignore_party": True,
"ignore_conversion_rate": True
}) })
item_doc = frappe.get_cached_doc("Item", args.get("item_code")) item_doc = frappe.get_cached_doc("Item", args.get("item_code"))
out = frappe._dict() out = frappe._dict()

View File

@ -192,15 +192,20 @@ class JobCard(Document):
"completed_qty": args.get("completed_qty") or 0.0 "completed_qty": args.get("completed_qty") or 0.0
}) })
elif args.get("start_time"): elif args.get("start_time"):
for name in employees: new_args = {
self.append("time_logs", { "from_time": get_datetime(args.get("start_time")),
"from_time": get_datetime(args.get("start_time")), "operation": args.get("sub_operation"),
"employee": name.get('employee'), "completed_qty": 0.0
"operation": args.get("sub_operation"), }
"completed_qty": 0.0
})
if not self.employee: if employees:
for name in employees:
new_args.employee = name.get('employee')
self.add_start_time_log(new_args)
else:
self.add_start_time_log(new_args)
if not self.employee and employees:
self.set_employees(employees) self.set_employees(employees)
if self.status == "On Hold": if self.status == "On Hold":
@ -208,6 +213,9 @@ class JobCard(Document):
self.save() self.save()
def add_start_time_log(self, args):
self.append("time_logs", args)
def set_employees(self, employees): def set_employees(self, employees):
for name in employees: for name in employees:
self.append('employee', { self.append('employee', {

View File

@ -70,12 +70,12 @@ def get_bom_stock(filters):
ON bom_item.item_code = ledger.item_code ON bom_item.item_code = ledger.item_code
{conditions} {conditions}
WHERE WHERE
bom_item.parent = '{bom}' and bom_item.parenttype='BOM' bom_item.parent = {bom} and bom_item.parenttype='BOM'
GROUP BY bom_item.item_code""".format( GROUP BY bom_item.item_code""".format(
qty_field=qty_field, qty_field=qty_field,
table=table, table=table,
conditions=conditions, conditions=conditions,
bom=bom, bom=frappe.db.escape(bom),
qty_to_produce=qty_to_produce or 1) qty_to_produce=qty_to_produce or 1)
) )

View File

@ -12,7 +12,10 @@ from erpnext.accounts.utils import get_fiscal_year, FiscalYearError
from frappe.utils import today from frappe.utils import today
def setup(company=None, patch=True): def setup(company=None, patch=True):
setup_company_independent_fixtures(patch=patch) # Company independent fixtures should be called only once at the first company setup
if frappe.db.count('Company', {'country': 'India'}) <=1:
setup_company_independent_fixtures(patch=patch)
if not patch: if not patch:
make_fixtures(company) make_fixtures(company)
@ -122,10 +125,12 @@ def add_print_formats():
def make_property_setters(patch=False): def make_property_setters(patch=False):
# GST rules do not allow for an invoice no. bigger than 16 characters # GST rules do not allow for an invoice no. bigger than 16 characters
journal_entry_types = frappe.get_meta("Journal Entry").get_options("voucher_type").split("\n") + ['Reversal Of ITC'] journal_entry_types = frappe.get_meta("Journal Entry").get_options("voucher_type").split("\n") + ['Reversal Of ITC']
sales_invoice_series = ['SINV-.YY.-', 'SRET-.YY.-', ''] + frappe.get_meta("Sales Invoice").get_options("naming_series").split("\n")
purchase_invoice_series = ['PINV-.YY.-', 'PRET-.YY.-', ''] + frappe.get_meta("Purchase Invoice").get_options("naming_series").split("\n")
if not patch: if not patch:
make_property_setter('Sales Invoice', 'naming_series', 'options', 'SINV-.YY.-\nSRET-.YY.-', '') make_property_setter('Sales Invoice', 'naming_series', 'options', '\n'.join(sales_invoice_series), '')
make_property_setter('Purchase Invoice', 'naming_series', 'options', 'PINV-.YY.-\nPRET-.YY.-', '') make_property_setter('Purchase Invoice', 'naming_series', 'options', '\n'.join(purchase_invoice_series), '')
make_property_setter('Journal Entry', 'voucher_type', 'options', '\n'.join(journal_entry_types), '') make_property_setter('Journal Entry', 'voucher_type', 'options', '\n'.join(journal_entry_types), '')
def make_custom_fields(update=True): def make_custom_fields(update=True):
@ -786,7 +791,7 @@ def set_tax_withholding_category(company):
doc.flags.ignore_mandatory = True doc.flags.ignore_mandatory = True
doc.insert() doc.insert()
else: else:
doc = frappe.get_doc("Tax Withholding Category", d.get("name")) doc = frappe.get_doc("Tax Withholding Category", d.get("name"), for_update=True)
if accounts: if accounts:
doc.append("accounts", accounts[0]) doc.append("accounts", accounts[0])

View File

@ -291,7 +291,7 @@ class Company(NestedSet):
cash = frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name') cash = frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name')
if cash and self.default_cash_account \ if cash and self.default_cash_account \
and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': cash}): and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': cash}):
mode_of_payment = frappe.get_doc('Mode of Payment', cash) mode_of_payment = frappe.get_doc('Mode of Payment', cash, for_update=True)
mode_of_payment.append('accounts', { mode_of_payment.append('accounts', {
'company': self.name, 'company': self.name,
'default_account': self.default_cash_account 'default_account': self.default_cash_account

View File

@ -26,7 +26,7 @@ def setup_taxes_and_charges(company_name: str, country: str):
if 'chart_of_accounts' not in country_wise_tax: if 'chart_of_accounts' not in country_wise_tax:
country_wise_tax = simple_to_detailed(country_wise_tax) country_wise_tax = simple_to_detailed(country_wise_tax)
from_detailed_data(company_name, country_wise_tax.get('chart_of_accounts')) from_detailed_data(company_name, country_wise_tax)
update_regional_tax_settings(country, company_name) update_regional_tax_settings(country, company_name)
@ -78,11 +78,12 @@ def simple_to_detailed(templates):
def from_detailed_data(company_name, data): def from_detailed_data(company_name, data):
"""Create Taxes and Charges Templates from detailed data.""" """Create Taxes and Charges Templates from detailed data."""
coa_name = frappe.db.get_value('Company', company_name, 'chart_of_accounts') coa_name = frappe.db.get_value('Company', company_name, 'chart_of_accounts')
tax_templates = data.get(coa_name) or data.get('*') coa_data = data.get('chart_of_accounts', {})
sales_tax_templates = tax_templates.get('sales_tax_templates') or tax_templates.get('*') tax_templates = coa_data.get(coa_name) or coa_data.get('*', {})
purchase_tax_templates = tax_templates.get('purchase_tax_templates') or tax_templates.get('*') tax_categories = data.get('tax_categories')
item_tax_templates = tax_templates.get('item_tax_templates') or tax_templates.get('*') sales_tax_templates = tax_templates.get('sales_tax_templates') or tax_templates.get('*', {})
tax_categories = tax_templates.get('tax_categories') purchase_tax_templates = tax_templates.get('purchase_tax_templates') or tax_templates.get('*', {})
item_tax_templates = tax_templates.get('item_tax_templates') or tax_templates.get('*', {})
if tax_categories: if tax_categories:
for tax_category in tax_categories: for tax_category in tax_categories:

View File

@ -193,7 +193,7 @@
"image_field": "image", "image_field": "image",
"links": [], "links": [],
"max_attachments": 5, "max_attachments": 5,
"modified": "2021-01-07 11:10:09.149170", "modified": "2021-07-08 16:22:01.343105",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Batch", "name": "Batch",
@ -217,5 +217,6 @@
"quick_entry": 1, "quick_entry": 1,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"title_field": "batch_id" "title_field": "batch_id",
"track_changes": 1
} }

View File

@ -405,17 +405,18 @@ class StockReconciliation(StockController):
key = (d.item_code, d.warehouse) key = (d.item_code, d.warehouse)
if key not in merge_similar_entries: if key not in merge_similar_entries:
d.total_amount = (d.actual_qty * d.valuation_rate)
merge_similar_entries[key] = d merge_similar_entries[key] = d
elif d.serial_no: elif d.serial_no:
data = merge_similar_entries[key] data = merge_similar_entries[key]
data.actual_qty += d.actual_qty data.actual_qty += d.actual_qty
data.qty_after_transaction += d.qty_after_transaction data.qty_after_transaction += d.qty_after_transaction
data.valuation_rate = (data.valuation_rate + d.valuation_rate) / data.actual_qty data.total_amount += (d.actual_qty * d.valuation_rate)
data.valuation_rate = (data.total_amount) / data.actual_qty
data.serial_no += '\n' + d.serial_no data.serial_no += '\n' + d.serial_no
if data.incoming_rate: data.incoming_rate = (data.total_amount) / data.actual_qty
data.incoming_rate = (data.incoming_rate + d.incoming_rate) / data.actual_qty
for key, value in merge_similar_entries.items(): for key, value in merge_similar_entries.items():
new_sl_entries.append(value) new_sl_entries.append(value)

View File

@ -6,7 +6,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe, unittest import frappe, unittest
from frappe.utils import flt, nowdate, nowtime, add_days from frappe.utils import flt, nowdate, nowtime, random_string, add_days
from erpnext.accounts.utils import get_stock_and_account_balance from erpnext.accounts.utils import get_stock_and_account_balance
from erpnext.stock.stock_ledger import get_previous_sle, update_entries_after from erpnext.stock.stock_ledger import get_previous_sle, update_entries_after
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import EmptyStockReconciliationItemsError, get_items from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import EmptyStockReconciliationItemsError, get_items
@ -152,6 +152,42 @@ class TestStockReconciliation(unittest.TestCase):
stock_doc = frappe.get_doc("Stock Reconciliation", d) stock_doc = frappe.get_doc("Stock Reconciliation", d)
stock_doc.cancel() stock_doc.cancel()
def test_stock_reco_for_merge_serialized_item(self):
to_delete_records = []
# Add new serial nos
serial_item_code = "Stock-Reco-Serial-Item-2"
serial_warehouse = "_Test Warehouse for Stock Reco1 - _TC"
sr = create_stock_reconciliation(item_code=serial_item_code, serial_no=random_string(6),
warehouse = serial_warehouse, qty=1, rate=100, do_not_submit=True, purpose='Opening Stock')
for i in range(3):
sr.append('items', {
'item_code': serial_item_code,
'warehouse': serial_warehouse,
'qty': 1,
'valuation_rate': 100,
'serial_no': random_string(6)
})
sr.save()
sr.submit()
sle_entries = frappe.get_all('Stock Ledger Entry', filters= {'voucher_no': sr.name},
fields = ['name', 'incoming_rate'])
self.assertEqual(len(sle_entries), 1)
self.assertEqual(sle_entries[0].incoming_rate, 100)
to_delete_records.append(sr.name)
to_delete_records.reverse()
for d in to_delete_records:
stock_doc = frappe.get_doc("Stock Reconciliation", d)
stock_doc.cancel()
def test_stock_reco_for_batch_item(self): def test_stock_reco_for_batch_item(self):
to_delete_records = [] to_delete_records = []
to_delete_serial_nos = [] to_delete_serial_nos = []
@ -364,6 +400,12 @@ def create_batch_or_serial_no_items():
serial_item_doc.serial_no_series = "SRSI.####" serial_item_doc.serial_no_series = "SRSI.####"
serial_item_doc.save(ignore_permissions=True) serial_item_doc.save(ignore_permissions=True)
serial_item_doc = create_item("Stock-Reco-Serial-Item-2", is_stock_item=1)
if not serial_item_doc.has_serial_no:
serial_item_doc.has_serial_no = 1
serial_item_doc.serial_no_series = "SRSII.####"
serial_item_doc.save(ignore_permissions=True)
batch_item_doc = create_item("Stock-Reco-batch-Item-1", is_stock_item=1) batch_item_doc = create_item("Stock-Reco-batch-Item-1", is_stock_item=1)
if not batch_item_doc.has_batch_no: if not batch_item_doc.has_batch_no:
batch_item_doc.has_batch_no = 1 batch_item_doc.has_batch_no = 1

View File

@ -807,10 +807,14 @@ def check_packing_list(price_list_rate_name, desired_qty, item_code):
def validate_conversion_rate(args, meta): def validate_conversion_rate(args, meta):
from erpnext.controllers.accounts_controller import validate_conversion_rate from erpnext.controllers.accounts_controller import validate_conversion_rate
if (not args.conversion_rate company_currency = frappe.get_cached_value('Company', args.company, "default_currency")
and args.currency==frappe.get_cached_value('Company', args.company, "default_currency")): if (not args.conversion_rate and args.currency==company_currency):
args.conversion_rate = 1.0 args.conversion_rate = 1.0
if (not args.ignore_conversion_rate and args.conversion_rate == 1 and args.currency!=company_currency):
args.conversion_rate = get_exchange_rate(args.currency,
company_currency, args.transaction_date, "for_buying") or 1.0
# validate currency conversion rate # validate currency conversion rate
validate_conversion_rate(args.currency, args.conversion_rate, validate_conversion_rate(args.currency, args.conversion_rate,
meta.get_label("conversion_rate"), args.company) meta.get_label("conversion_rate"), args.company)

View File

@ -12,7 +12,7 @@
.get_value("User", timesheet.modified_by, [ .get_value("User", timesheet.modified_by, [
"full_name", "user_image" "full_name", "user_image"
], as_dict = True) ], as_dict = True)
%} %}
{% if user_details.user_image %} {% if user_details.user_image %}
<span class="avatar avatar-small" style="width:32px; height:32px;" title="{{ user_details.full_name }}"> <span class="avatar avatar-small" style="width:32px; height:32px;" title="{{ user_details.full_name }}">
<img src="{{ user_details.user_image }}"> <img src="{{ user_details.user_image }}">