mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-17 00:25:01 +00:00
Merge branch 'version-13-hotfix' into backport/version-13-hotfix/27008
This commit is contained in:
@@ -60,10 +60,23 @@ frappe.ui.form.on("Supplier", {
|
||||
erpnext.utils.make_pricing_rule(frm.doc.doctype, frm.doc.name);
|
||||
}, __('Create'));
|
||||
|
||||
frm.add_custom_button(__('Get Supplier Group Details'), function () {
|
||||
frm.trigger("get_supplier_group_details");
|
||||
}, __('Actions'));
|
||||
|
||||
// indicators
|
||||
erpnext.utils.set_party_dashboard_indicators(frm);
|
||||
}
|
||||
},
|
||||
get_supplier_group_details: function(frm) {
|
||||
frappe.call({
|
||||
method: "get_supplier_group_details",
|
||||
doc: frm.doc,
|
||||
callback: function() {
|
||||
frm.refresh();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
is_internal_supplier: function(frm) {
|
||||
if (frm.doc.is_internal_supplier == 1) {
|
||||
|
||||
@@ -51,6 +51,23 @@ class Supplier(TransactionBase):
|
||||
validate_party_accounts(self)
|
||||
self.validate_internal_supplier()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_supplier_group_details(self):
|
||||
doc = frappe.get_doc('Supplier Group', self.supplier_group)
|
||||
self.payment_terms = ""
|
||||
self.accounts = []
|
||||
|
||||
if doc.accounts:
|
||||
for account in doc.accounts:
|
||||
child = self.append('accounts')
|
||||
child.company = account.company
|
||||
child.account = account.account
|
||||
|
||||
if doc.payment_terms:
|
||||
self.payment_terms = doc.payment_terms
|
||||
|
||||
self.save()
|
||||
|
||||
def validate_internal_supplier(self):
|
||||
internal_supplier = frappe.db.get_value("Supplier",
|
||||
{"is_internal_supplier": 1, "represents_company": self.represents_company, "name": ("!=", self.name)}, "name")
|
||||
|
||||
@@ -13,6 +13,30 @@ test_records = frappe.get_test_records('Supplier')
|
||||
|
||||
|
||||
class TestSupplier(unittest.TestCase):
|
||||
def test_get_supplier_group_details(self):
|
||||
doc = frappe.new_doc("Supplier Group")
|
||||
doc.supplier_group_name = "_Testing Supplier Group"
|
||||
doc.payment_terms = "_Test Payment Term Template 3"
|
||||
doc.accounts = []
|
||||
test_account_details = {
|
||||
"company": "_Test Company",
|
||||
"account": "Creditors - _TC",
|
||||
}
|
||||
doc.append("accounts", test_account_details)
|
||||
doc.save()
|
||||
s_doc = frappe.new_doc("Supplier")
|
||||
s_doc.supplier_name = "Testing Supplier"
|
||||
s_doc.supplier_group = "_Testing Supplier Group"
|
||||
s_doc.payment_terms = ""
|
||||
s_doc.accounts = []
|
||||
s_doc.insert()
|
||||
s_doc.get_supplier_group_details()
|
||||
self.assertEqual(s_doc.payment_terms, "_Test Payment Term Template 3")
|
||||
self.assertEqual(s_doc.accounts[0].company, "_Test Company")
|
||||
self.assertEqual(s_doc.accounts[0].account, "Creditors - _TC")
|
||||
s_doc.delete()
|
||||
doc.delete()
|
||||
|
||||
def test_supplier_default_payment_terms(self):
|
||||
# Payment Term based on Days after invoice date
|
||||
frappe.db.set_value(
|
||||
|
||||
@@ -1841,6 +1841,11 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
||||
|
||||
for d in data:
|
||||
new_child_flag = False
|
||||
|
||||
if not d.get("item_code"):
|
||||
# ignore empty rows
|
||||
continue
|
||||
|
||||
if not d.get("docname"):
|
||||
new_child_flag = True
|
||||
check_doc_permissions(parent, 'create')
|
||||
|
||||
@@ -563,7 +563,7 @@ erpnext.utils.update_child_items = function(opts) {
|
||||
},
|
||||
],
|
||||
primary_action: function() {
|
||||
const trans_items = this.get_values()["trans_items"];
|
||||
const trans_items = this.get_values()["trans_items"].filter((item) => !!item.item_code);
|
||||
frappe.call({
|
||||
method: 'erpnext.controllers.accounts_controller.update_child_qty_rate',
|
||||
freeze: true,
|
||||
|
||||
@@ -130,6 +130,10 @@ frappe.ui.form.on("Customer", {
|
||||
erpnext.utils.make_pricing_rule(frm.doc.doctype, frm.doc.name);
|
||||
}, __('Create'));
|
||||
|
||||
frm.add_custom_button(__('Get Customer Group Details'), function () {
|
||||
frm.trigger("get_customer_group_details");
|
||||
}, __('Actions'));
|
||||
|
||||
// indicator
|
||||
erpnext.utils.set_party_dashboard_indicators(frm);
|
||||
|
||||
@@ -145,4 +149,15 @@ frappe.ui.form.on("Customer", {
|
||||
if(frm.doc.lead_name) frappe.model.clear_doc("Lead", frm.doc.lead_name);
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
get_customer_group_details: function(frm) {
|
||||
frappe.call({
|
||||
method: "get_customer_group_details",
|
||||
doc: frm.doc,
|
||||
callback: function() {
|
||||
frm.refresh();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
@@ -78,6 +78,29 @@ class Customer(TransactionBase):
|
||||
if sum(member.allocated_percentage or 0 for member in self.sales_team) != 100:
|
||||
frappe.throw(_("Total contribution percentage should be equal to 100"))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_customer_group_details(self):
|
||||
doc = frappe.get_doc('Customer Group', self.customer_group)
|
||||
self.accounts = self.credit_limits = []
|
||||
self.payment_terms = self.default_price_list = ""
|
||||
|
||||
tables = [["accounts", "account"], ["credit_limits", "credit_limit"]]
|
||||
fields = ["payment_terms", "default_price_list"]
|
||||
|
||||
for row in tables:
|
||||
table, field = row[0], row[1]
|
||||
if not doc.get(table): continue
|
||||
|
||||
for entry in doc.get(table):
|
||||
child = self.append(table)
|
||||
child.update({"company": entry.company, field: entry.get(field)})
|
||||
|
||||
for field in fields:
|
||||
if not doc.get(field): continue
|
||||
self.update({field: doc.get(field)})
|
||||
|
||||
self.save()
|
||||
|
||||
def check_customer_group_change(self):
|
||||
frappe.flags.customer_group_changed = False
|
||||
|
||||
|
||||
@@ -27,6 +27,42 @@ class TestCustomer(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
set_credit_limit('_Test Customer', '_Test Company', 0)
|
||||
|
||||
def test_get_customer_group_details(self):
|
||||
doc = frappe.new_doc("Customer Group")
|
||||
doc.customer_group_name = "_Testing Customer Group"
|
||||
doc.payment_terms = "_Test Payment Term Template 3"
|
||||
doc.accounts = []
|
||||
doc.default_price_list = "Standard Buying"
|
||||
doc.credit_limits = []
|
||||
test_account_details = {
|
||||
"company": "_Test Company",
|
||||
"account": "Creditors - _TC",
|
||||
}
|
||||
test_credit_limits = {
|
||||
"company": "_Test Company",
|
||||
"credit_limit": 350000
|
||||
}
|
||||
doc.append("accounts", test_account_details)
|
||||
doc.append("credit_limits", test_credit_limits)
|
||||
doc.insert()
|
||||
|
||||
c_doc = frappe.new_doc("Customer")
|
||||
c_doc.customer_name = "Testing Customer"
|
||||
c_doc.customer_group = "_Testing Customer Group"
|
||||
c_doc.payment_terms = c_doc.default_price_list = ""
|
||||
c_doc.accounts = c_doc.credit_limits= []
|
||||
c_doc.insert()
|
||||
c_doc.get_customer_group_details()
|
||||
self.assertEqual(c_doc.payment_terms, "_Test Payment Term Template 3")
|
||||
|
||||
self.assertEqual(c_doc.accounts[0].company, "_Test Company")
|
||||
self.assertEqual(c_doc.accounts[0].account, "Creditors - _TC")
|
||||
|
||||
self.assertEqual(c_doc.credit_limits[0].company, "_Test Company")
|
||||
self.assertEqual(c_doc.credit_limits[0].credit_limit, 350000)
|
||||
c_doc.delete()
|
||||
doc.delete()
|
||||
|
||||
def test_party_details(self):
|
||||
from erpnext.accounts.party import get_party_details
|
||||
|
||||
|
||||
@@ -84,8 +84,6 @@
|
||||
"oldfieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"default": "{purpose}",
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
@@ -630,7 +628,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-08-17 20:16:12.737743",
|
||||
"modified": "2021-08-20 19:19:31.514846",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Stock Entry",
|
||||
|
||||
@@ -58,6 +58,7 @@ class StockEntry(StockController):
|
||||
|
||||
self.validate_posting_time()
|
||||
self.validate_purpose()
|
||||
self.set_title()
|
||||
self.validate_item()
|
||||
self.validate_customer_provided_item()
|
||||
self.validate_qty()
|
||||
@@ -1608,6 +1609,14 @@ class StockEntry(StockController):
|
||||
|
||||
return sorted(list(set(get_serial_nos(self.pro_doc.serial_no)) - set(used_serial_nos)))
|
||||
|
||||
def set_title(self):
|
||||
if frappe.flags.in_import and self.title:
|
||||
# Allow updating title during data import/update
|
||||
return
|
||||
|
||||
self.title = self.purpose
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def move_sample_to_retention_warehouse(company, items):
|
||||
if isinstance(items, string_types):
|
||||
|
||||
@@ -36,12 +36,26 @@ frappe.query_reports["Stock Analytics"] = {
|
||||
options:"Brand",
|
||||
default: "",
|
||||
},
|
||||
{
|
||||
fieldname: "company",
|
||||
label: __("Company"),
|
||||
fieldtype: "Link",
|
||||
options: "Company",
|
||||
default: frappe.defaults.get_user_default("Company"),
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname: "warehouse",
|
||||
label: __("Warehouse"),
|
||||
fieldtype: "Link",
|
||||
options:"Warehouse",
|
||||
options: "Warehouse",
|
||||
default: "",
|
||||
get_query: function() {
|
||||
const company = frappe.query_report.get_filter_value('company');
|
||||
return {
|
||||
filters: { 'company': company }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
fieldname: "from_date",
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
import datetime
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _, scrub
|
||||
from frappe.utils import getdate, flt
|
||||
from frappe.utils import getdate, get_quarter_start, get_first_day_of_week
|
||||
from frappe.utils import get_first_day as get_first_day_of_month
|
||||
|
||||
from erpnext.stock.report.stock_balance.stock_balance import (get_items, get_stock_ledger_entries, get_item_details)
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
from erpnext.stock.utils import is_reposting_item_valuation_in_progress
|
||||
from six import iteritems
|
||||
|
||||
def execute(filters=None):
|
||||
is_reposting_item_valuation_in_progress()
|
||||
@@ -71,7 +72,8 @@ def get_columns(filters):
|
||||
|
||||
def get_period_date_ranges(filters):
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
|
||||
from_date = round_down_to_nearest_frequency(filters.from_date, filters.range)
|
||||
to_date = getdate(filters.to_date)
|
||||
|
||||
increment = {
|
||||
"Monthly": 1,
|
||||
@@ -97,6 +99,31 @@ def get_period_date_ranges(filters):
|
||||
|
||||
return periodic_daterange
|
||||
|
||||
|
||||
def round_down_to_nearest_frequency(date: str, frequency: str) -> datetime.datetime:
|
||||
"""Rounds down the date to nearest frequency unit.
|
||||
example:
|
||||
|
||||
>>> round_down_to_nearest_frequency("2021-02-21", "Monthly")
|
||||
datetime.datetime(2021, 2, 1)
|
||||
|
||||
>>> round_down_to_nearest_frequency("2021-08-21", "Yearly")
|
||||
datetime.datetime(2021, 1, 1)
|
||||
"""
|
||||
|
||||
def _get_first_day_of_fiscal_year(date):
|
||||
fiscal_year = get_fiscal_year(date)
|
||||
return fiscal_year and fiscal_year[1] or date
|
||||
|
||||
round_down_function = {
|
||||
"Monthly": get_first_day_of_month,
|
||||
"Quarterly": get_quarter_start,
|
||||
"Weekly": get_first_day_of_week,
|
||||
"Yearly": _get_first_day_of_fiscal_year,
|
||||
}.get(frequency, getdate)
|
||||
return round_down_function(date)
|
||||
|
||||
|
||||
def get_period(posting_date, filters):
|
||||
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
||||
|
||||
@@ -177,7 +204,7 @@ def get_data(filters):
|
||||
periodic_data = get_periodic_data(sle, filters)
|
||||
ranges = get_period_date_ranges(filters)
|
||||
|
||||
for dummy, item_data in iteritems(item_details):
|
||||
for dummy, item_data in item_details.items():
|
||||
row = {
|
||||
"name": item_data.name,
|
||||
"item_name": item_data.item_name,
|
||||
|
||||
35
erpnext/stock/report/stock_analytics/test_stock_analytics.py
Normal file
35
erpnext/stock/report/stock_analytics/test_stock_analytics.py
Normal file
@@ -0,0 +1,35 @@
|
||||
import datetime
|
||||
import unittest
|
||||
|
||||
from frappe import _dict
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
|
||||
from erpnext.stock.report.stock_analytics.stock_analytics import get_period_date_ranges
|
||||
|
||||
|
||||
class TestStockAnalyticsReport(unittest.TestCase):
|
||||
def test_get_period_date_ranges(self):
|
||||
|
||||
filters = _dict(range="Monthly", from_date="2020-12-28", to_date="2021-02-06")
|
||||
|
||||
ranges = get_period_date_ranges(filters)
|
||||
|
||||
expected_ranges = [
|
||||
[datetime.date(2020, 12, 1), datetime.date(2020, 12, 31)],
|
||||
[datetime.date(2021, 1, 1), datetime.date(2021, 1, 31)],
|
||||
[datetime.date(2021, 2, 1), datetime.date(2021, 2, 6)],
|
||||
]
|
||||
|
||||
self.assertEqual(ranges, expected_ranges)
|
||||
|
||||
def test_get_period_date_ranges_yearly(self):
|
||||
|
||||
filters = _dict(range="Yearly", from_date="2021-01-28", to_date="2021-02-06")
|
||||
|
||||
ranges = get_period_date_ranges(filters)
|
||||
first_date = get_fiscal_year("2021-01-28")[1]
|
||||
expected_ranges = [
|
||||
[first_date, datetime.date(2021, 2, 6)],
|
||||
]
|
||||
|
||||
self.assertEqual(ranges, expected_ranges)
|
||||
Reference in New Issue
Block a user