mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-17 00:25:01 +00:00
Merge branch 'version-13-hotfix' into mergify/bp/version-13-hotfix/pr-27916
This commit is contained in:
@@ -590,5 +590,11 @@ frappe.ui.form.on("Purchase Invoice", {
|
||||
|
||||
company: function(frm) {
|
||||
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
|
||||
|
||||
if (frm.doc.company) {
|
||||
frappe.db.get_value('Company', frm.doc.company, 'default_payable_account', (r) => {
|
||||
frm.set_value('credit_to', r.default_payable_account);
|
||||
});
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
@@ -10,9 +10,17 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
this.setup_posting_date_time_check();
|
||||
this._super(doc);
|
||||
},
|
||||
|
||||
company: function() {
|
||||
erpnext.accounts.dimensions.update_dimension(this.frm, this.frm.doctype);
|
||||
let me = this;
|
||||
if (this.frm.doc.company) {
|
||||
frappe.db.get_value('Company', this.frm.doc.company, 'default_receivable_account', (r) => {
|
||||
me.frm.set_value('debit_to', r.default_receivable_account);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onload: function() {
|
||||
var me = this;
|
||||
this._super();
|
||||
|
||||
@@ -1359,8 +1359,8 @@ class AccountsController(TransactionBase):
|
||||
total = 0
|
||||
base_total = 0
|
||||
for d in self.get("payment_schedule"):
|
||||
total += flt(d.payment_amount)
|
||||
base_total += flt(d.base_payment_amount)
|
||||
total += flt(d.payment_amount, d.precision("payment_amount"))
|
||||
base_total += flt(d.base_payment_amount, d.precision("base_payment_amount"))
|
||||
|
||||
base_grand_total = self.get("base_rounded_total") or self.base_grand_total
|
||||
grand_total = self.get("rounded_total") or self.grand_total
|
||||
@@ -1376,8 +1376,9 @@ class AccountsController(TransactionBase):
|
||||
else:
|
||||
grand_total -= self.get("total_advance")
|
||||
base_grand_total = flt(grand_total * self.get("conversion_rate"), self.precision("base_grand_total"))
|
||||
if total != flt(grand_total, self.precision("grand_total")) or \
|
||||
base_total != flt(base_grand_total, self.precision("base_grand_total")):
|
||||
|
||||
if flt(total, self.precision("grand_total")) != flt(grand_total, self.precision("grand_total")) or \
|
||||
flt(base_total, self.precision("base_grand_total")) != flt(base_grand_total, self.precision("base_grand_total")):
|
||||
frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total"))
|
||||
|
||||
def is_rounded_total_disabled(self):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
import frappe
|
||||
from frappe import _dict
|
||||
from frappe.utils import floor
|
||||
|
||||
|
||||
@@ -96,38 +95,32 @@ class ProductFiltersBuilder:
|
||||
return
|
||||
|
||||
attributes = [row.attribute for row in self.doc.filter_attributes]
|
||||
attribute_docs = [
|
||||
frappe.get_doc('Item Attribute', attribute) for attribute in attributes
|
||||
]
|
||||
|
||||
valid_attributes = []
|
||||
if not attributes:
|
||||
return []
|
||||
|
||||
for attr_doc in attribute_docs:
|
||||
selected_attributes = []
|
||||
for attr in attr_doc.item_attribute_values:
|
||||
or_filters = []
|
||||
filters= [
|
||||
["Item Variant Attribute", "attribute", "=", attr.parent],
|
||||
["Item Variant Attribute", "attribute_value", "=", attr.attribute_value]
|
||||
]
|
||||
if self.item_group:
|
||||
or_filters.extend([
|
||||
["item_group", "=", self.item_group],
|
||||
["Website Item Group", "item_group", "=", self.item_group]
|
||||
])
|
||||
result = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
distinct attribute, attribute_value
|
||||
from
|
||||
`tabItem Variant Attribute`
|
||||
where
|
||||
attribute in %(attributes)s
|
||||
and attribute_value is not null
|
||||
""",
|
||||
{"attributes": attributes},
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
if frappe.db.get_all("Item", filters, or_filters=or_filters, limit=1):
|
||||
selected_attributes.append(attr)
|
||||
attribute_value_map = {}
|
||||
for d in result:
|
||||
attribute_value_map.setdefault(d.attribute, []).append(d.attribute_value)
|
||||
|
||||
if selected_attributes:
|
||||
valid_attributes.append(
|
||||
_dict(
|
||||
item_attribute_values=selected_attributes,
|
||||
name=attr_doc.name
|
||||
)
|
||||
)
|
||||
|
||||
return valid_attributes
|
||||
out = []
|
||||
for name, values in attribute_value_map.items():
|
||||
out.append(frappe._dict(name=name, item_attribute_values=values))
|
||||
return out
|
||||
|
||||
def get_discount_filters(self, discounts):
|
||||
discount_filters = []
|
||||
@@ -147,4 +140,4 @@ class ProductFiltersBuilder:
|
||||
label = f"{discount}% and below"
|
||||
discount_filters.append([discount, label])
|
||||
|
||||
return discount_filters
|
||||
return discount_filters
|
||||
|
||||
@@ -175,9 +175,7 @@ class TestProductDataEngine(unittest.TestCase):
|
||||
|
||||
filter_engine = ProductFiltersBuilder()
|
||||
attribute_filter = filter_engine.get_attribute_filters()[0]
|
||||
attributes = attribute_filter.item_attribute_values
|
||||
|
||||
attribute_values = [d.attribute_value for d in attributes]
|
||||
attribute_values = attribute_filter.item_attribute_values
|
||||
|
||||
self.assertEqual(attribute_filter.name, "Test Size")
|
||||
self.assertGreater(len(attribute_values), 0)
|
||||
@@ -349,4 +347,4 @@ def create_variant_web_item():
|
||||
variant.save()
|
||||
|
||||
if not frappe.db.exists("Website Item", {"variant_of": "Test Web Item"}):
|
||||
make_website_item(variant, save=True)
|
||||
make_website_item(variant, save=True)
|
||||
|
||||
@@ -311,7 +311,7 @@ class ProductionPlan(Document):
|
||||
|
||||
if self.total_produced_qty > 0:
|
||||
self.status = "In Process"
|
||||
if self.total_produced_qty >= self.total_planned_qty:
|
||||
if self.check_have_work_orders_completed():
|
||||
self.status = "Completed"
|
||||
|
||||
if self.status != 'Completed':
|
||||
@@ -575,6 +575,15 @@ class ProductionPlan(Document):
|
||||
|
||||
self.append("sub_assembly_items", data)
|
||||
|
||||
def check_have_work_orders_completed(self):
|
||||
wo_status = frappe.db.get_list(
|
||||
"Work Order",
|
||||
filters={"production_plan": self.name},
|
||||
fields="status",
|
||||
pluck="status"
|
||||
)
|
||||
return all(s == "Completed" for s in wo_status)
|
||||
|
||||
@frappe.whitelist()
|
||||
def download_raw_materials(doc, warehouses=None):
|
||||
if isinstance(doc, str):
|
||||
|
||||
@@ -329,3 +329,4 @@ erpnext.patches.v13_0.trim_sales_invoice_custom_field_length
|
||||
erpnext.patches.v13_0.enable_scheduler_job_for_item_reposting
|
||||
erpnext.patches.v13_0.requeue_failed_reposts
|
||||
erpnext.patches.v13_0.fetch_thumbnail_in_website_items
|
||||
erpnext.patches.v12_0.update_production_plan_status
|
||||
|
||||
31
erpnext/patches/v12_0/update_production_plan_status.py
Normal file
31
erpnext/patches/v12_0/update_production_plan_status.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# Copyright (c) 2021, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("manufacturing", "doctype", "production_plan")
|
||||
frappe.db.sql("""
|
||||
UPDATE `tabProduction Plan` ppl
|
||||
SET status = "Completed"
|
||||
WHERE ppl.name IN (
|
||||
SELECT ss.name FROM (
|
||||
SELECT
|
||||
(
|
||||
count(wo.status = "Completed") =
|
||||
count(pp.name)
|
||||
) =
|
||||
(
|
||||
pp.status != "Completed"
|
||||
AND pp.total_produced_qty >= pp.total_planned_qty
|
||||
) AS should_set,
|
||||
pp.name AS name
|
||||
FROM
|
||||
`tabWork Order` wo INNER JOIN`tabProduction Plan` pp
|
||||
ON wo.production_plan = pp.name
|
||||
GROUP BY pp.name
|
||||
HAVING should_set = 1
|
||||
) ss
|
||||
)
|
||||
""")
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"category": "Modules",
|
||||
"charts": [],
|
||||
"content": "[{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Projects Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"HR Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Selling Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Buying Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Support Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Shopping Cart Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Portal Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Domain Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Products Settings\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Naming Series\",\"col\":4}}]",
|
||||
"creation": "2020-03-12 14:47:51.166455",
|
||||
"developer_mode_only": 0,
|
||||
"disable_user_customization": 0,
|
||||
@@ -15,7 +16,7 @@
|
||||
"is_standard": 1,
|
||||
"label": "ERPNext Settings",
|
||||
"links": [],
|
||||
"modified": "2021-06-12 01:58:11.399566",
|
||||
"modified": "2021-10-26 21:32:55.323591",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "ERPNext Settings",
|
||||
@@ -29,6 +30,14 @@
|
||||
"link_to": "Projects Settings",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"color": "Grey",
|
||||
"doc_view": "",
|
||||
"icon": "dot-horizontal",
|
||||
"label": "Naming Series",
|
||||
"link_to": "Naming Series",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"icon": "accounting",
|
||||
"label": "Accounts Settings",
|
||||
|
||||
@@ -339,15 +339,15 @@
|
||||
<div class="filter-options">
|
||||
{% for attr_value in attribute.item_attribute_values %}
|
||||
<div class="checkbox">
|
||||
<label data-value="{{ attr_value }}">
|
||||
<label>
|
||||
<input type="checkbox"
|
||||
class="product-filter attribute-filter"
|
||||
id="{{attr_value.name}}"
|
||||
id="{{ attr_value }}"
|
||||
data-attribute-name="{{ attribute.name }}"
|
||||
data-attribute-value="{{ attr_value.attribute_value }}"
|
||||
data-attribute-value="{{ attr_value }}"
|
||||
style="width: 14px !important"
|
||||
{% if attr_value.checked %} checked {% endif %}>
|
||||
<span class="label-area">{{ attr_value.attribute_value }}</span>
|
||||
<span class="label-area">{{ attr_value }}</span>
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
Reference in New Issue
Block a user