diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 92efe8e302..c00d90efe4 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '10.1.72' +__version__ = '10.1.73' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html index dfcf64c797..4930207abd 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html @@ -194,7 +194,7 @@ {% if(!filters.show_pdc_in_print) { %} {%= format_currency(data[i]["paid_amount"], data[i]["currency"]) %} - {%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["Debit Note"], data[i]["currency"]) %} + {%= report.report_name === "Accounts Receivable" ? format_currency(data[i]["credit_note"], data[i]["currency"]) : format_currency(data[i]["debit_note"], data[i]["currency"]) %} {% } %} {%= format_currency(data[i]["outstanding_amount"], data[i]["currency"]) %} diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py index 7b0072cd15..7bf99728f7 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py @@ -22,7 +22,7 @@ class AccountsReceivableSummary(ReceivablePayableReport): columns += [ args.get("party_type") + " Name::140"] credit_debit_label = "Credit Note Amt" if args.get('party_type') == 'Customer' else "Debit Note Amt" - + columns += [{ "label": _("Total Invoiced Amt"), "fieldname": "total_invoiced_amt", @@ -107,7 +107,7 @@ class AccountsReceivableSummary(ReceivablePayableReport): "options": "Supplier Group", "width": 80 }] - + columns.append({ "fieldname": "currency", "label": _("Currency"), @@ -138,7 +138,7 @@ class AccountsReceivableSummary(ReceivablePayableReport): row += [self.get_territory(party), self.get_customer_group(party)] if args.get("party_type") == "Supplier": row += [self.get_supplier_group(party)] - + row.append(party_dict.currency) data.append(row) @@ -162,7 +162,7 @@ class AccountsReceivableSummary(ReceivablePayableReport): for k in list(party_total[d.party]): if k != "currency": party_total[d.party][k] += flt(d.get(k, 0)) - + party_total[d.party].currency = d.currency return party_total diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index dbde30410c..ee6dc2a473 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -12,6 +12,7 @@ from erpnext.buying.utils import validate_for_items, update_last_purchase_rate from erpnext.stock.stock_ledger import get_valuation_rate from erpnext.stock.doctype.stock_entry.stock_entry import get_used_alternative_items from erpnext.stock.doctype.serial_no.serial_no import get_auto_serial_nos, auto_make_serial_nos, get_serial_nos +from frappe.contacts.doctype.address.address import get_address_display from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget from erpnext.controllers.stock_controller import StockController @@ -42,6 +43,7 @@ class BuyingController(StockController): self.set_qty_as_per_stock_uom() self.validate_stock_or_nonstock_items() self.validate_warehouse() + self.set_supplier_address() if self.doctype=="Purchase Invoice": self.validate_purchase_receipt_if_update_stock() @@ -113,6 +115,16 @@ class BuyingController(StockController): if not d.cost_center and lc_voucher_data and lc_voucher_data[0][1]: d.db_set('cost_center', lc_voucher_data[0][1]) + def set_supplier_address(self): + address_dict = { + 'supplier_address': 'address_display', + 'shipping_address': 'shipping_address_display' + } + + for address_field, address_display_field in address_dict.items(): + if self.get(address_field): + self.set(address_display_field, get_address_display(self.get(address_field))) + def set_total_in_words(self): from frappe.utils import money_in_words if self.meta.get_field("base_in_words"): diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 7739592ced..684a2cdbcb 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -9,6 +9,7 @@ from erpnext.stock.get_item_details import get_bin_details 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 get_item_defaults, set_item_default +from frappe.contacts.doctype.address.address import get_address_display from erpnext.controllers.stock_controller import StockController @@ -16,7 +17,7 @@ class SellingController(StockController): def __setup__(self): if hasattr(self, "taxes"): self.flags.print_taxes_with_zero_amount = cint(frappe.db.get_single_value("Print Settings", - "print_taxes_with_zero_amount")) + "print_taxes_with_zero_amount")) self.flags.show_inclusive_tax_in_print = self.is_inclusive_tax() self.print_templates = { @@ -43,6 +44,7 @@ class SellingController(StockController): self.set_po_nos() self.set_gross_profit() set_default_income_account_for_item(self) + self.set_customer_address() def set_missing_values(self, for_validate=False): @@ -355,6 +357,17 @@ class SellingController(StockController): item.gross_profit = flt(((item.base_rate - item.valuation_rate) * item.stock_qty), self.precision("amount", item)) + def set_customer_address(self): + address_dict = { + 'customer_address': 'address_display', + 'shipping_address_name': 'shipping_address', + 'company_address': 'company_address_display' + } + + for address_field, address_display_field in address_dict.items(): + if self.get(address_field): + self.set(address_display_field, get_address_display(self.get(address_field))) + def validate_items(self): # validate items to see if they have is_sales_item enabled from erpnext.controllers.buying_controller import validate_item_type diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 43afa2ae28..cbd3939b7b 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -12,7 +12,7 @@ app_license = "GNU General Public License (v3)" source_link = "https://github.com/frappe/erpnext" develop_version = '12.x.x-develop' -staging_version = '11.0.3-beta.24' +staging_version = '11.0.3-beta.25' error_report_email = "support@erpnext.com" diff --git a/erpnext/projects/doctype/task/task.js b/erpnext/projects/doctype/task/task.js index b8f324a85f..c1a9c448b4 100644 --- a/erpnext/projects/doctype/task/task.js +++ b/erpnext/projects/doctype/task/task.js @@ -80,15 +80,15 @@ frappe.ui.form.on("Task", { } }, - is_group: function(frm) { + is_group: function (frm) { frappe.call({ - method:"erpnext.projects.doctype.task.task.check_if_child_exists", + method: "erpnext.projects.doctype.task.task.check_if_child_exists", args: { name: frm.doc.name }, - callback: function(r){ - if(r.message){ - frappe.msgprint(__('Cannot convert it to non-group. Child Tasks exist.')); + callback: function (r) { + if (r.message.length > 0) { + frappe.msgprint(__(`Cannot convert it to non-group. The following child Tasks exist: ${r.message.join(", ")}.`)); frm.reload_doc(); } } diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 3dc52d4ebe..649d73a63f 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -2,12 +2,15 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe, json -from frappe.utils import getdate, date_diff, add_days, cstr +import json + +import frappe from frappe import _, throw +from frappe.utils import add_days, cstr, date_diff, get_link_to_form, getdate from frappe.utils.nestedset import NestedSet + class CircularReferenceError(frappe.ValidationError): pass class Task(NestedSet): @@ -157,8 +160,10 @@ class Task(NestedSet): @frappe.whitelist() def check_if_child_exists(name): - return frappe.db.sql("""select name from `tabTask` - where parent_task = %s""", name) + child_tasks = frappe.get_all("Task", filters={"parent_task": name}) + child_tasks = [get_link_to_form("Task", task.name) for task in child_tasks] + return child_tasks + def get_project(doctype, txt, searchfield, start, page_len, filters): from erpnext.controllers.queries import get_match_cond @@ -237,4 +242,4 @@ def add_multiple_tasks(data, parent): new_task.insert() def on_doctype_update(): - frappe.db.add_index("Task", ["lft", "rgt"]) \ No newline at end of file + frappe.db.add_index("Task", ["lft", "rgt"]) diff --git a/erpnext/public/css/erpnext.css b/erpnext/public/css/erpnext.css index 460efbfe9f..c55e422151 100644 --- a/erpnext/public/css/erpnext.css +++ b/erpnext/public/css/erpnext.css @@ -346,6 +346,11 @@ body[data-route="pos"] .btn-more { body[data-route="pos"] .collapse-btn { cursor: pointer; } +@media (max-width: 767px) { + body[data-route="pos"] .page-actions { + max-width: 110px; + } +} .price-info { position: absolute; left: 0; diff --git a/erpnext/public/js/projects/timer.js b/erpnext/public/js/projects/timer.js index 8b1d1b158b..26be997d48 100644 --- a/erpnext/public/js/projects/timer.js +++ b/erpnext/public/js/projects/timer.js @@ -44,8 +44,8 @@ erpnext.timesheet.timer = function(frm, row, timestamp=0) { }; erpnext.timesheet.control_timer = function(frm, dialog, row, timestamp=0) { - var $btn_start = $(".playpause .btn-start"); - var $btn_complete = $(".playpause .btn-complete"); + var $btn_start = dialog.$wrapper.find(".playpause .btn-start"); + var $btn_complete = dialog.$wrapper.find(".playpause .btn-complete"); var interval = null; var currentIncrement = timestamp; var initialised = row ? true : false; diff --git a/erpnext/stock/doctype/packed_item/packed_item.py b/erpnext/stock/doctype/packed_item/packed_item.py index fc53794093..cf72527205 100644 --- a/erpnext/stock/doctype/packed_item/packed_item.py +++ b/erpnext/stock/doctype/packed_item/packed_item.py @@ -53,8 +53,9 @@ def update_packing_list_item(doc, packing_item_code, qty, main_item_row, descrip pi.qty = flt(qty) pi.description = description if not pi.warehouse: - pi.warehouse = (main_item_row.warehouse - if (doc.get('is_pos') or not item.default_warehouse) else item.default_warehouse) + pi.warehouse = (main_item_row.warehouse if ((doc.get('is_pos') + or not item.default_warehouse) and main_item_row.warehouse) else item.default_warehouse) + if not pi.batch_no: pi.batch_no = cstr(main_item_row.get("batch_no")) if not pi.target_warehouse: diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 928dd8854a..0c83529702 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -178,7 +178,11 @@ class update_entries_after(object): # rounding as per precision self.stock_value = flt(self.stock_value, self.precision) - stock_value_difference = self.stock_value - self.prev_stock_value + if self.prev_stock_value < 0 and self.stock_value >= 0: + stock_value_difference = sle.actual_qty * self.valuation_rate + else: + stock_value_difference = self.stock_value - self.prev_stock_value + self.prev_stock_value = self.stock_value # update current sle