Merge branch 'develop' into item-variant-attributes-optional
This commit is contained in:
commit
9a45bd11d6
File diff suppressed because it is too large
Load Diff
@ -403,7 +403,7 @@ def make_purchase_invoice(source_name, target_doc=None):
|
|||||||
or item.get("buying_cost_center")
|
or item.get("buying_cost_center")
|
||||||
or item_group.get("buying_cost_center"))
|
or item_group.get("buying_cost_center"))
|
||||||
|
|
||||||
doc = get_mapped_doc("Purchase Order", source_name, {
|
fields = {
|
||||||
"Purchase Order": {
|
"Purchase Order": {
|
||||||
"doctype": "Purchase Invoice",
|
"doctype": "Purchase Invoice",
|
||||||
"field_map": {
|
"field_map": {
|
||||||
@ -426,8 +426,16 @@ def make_purchase_invoice(source_name, target_doc=None):
|
|||||||
"Purchase Taxes and Charges": {
|
"Purchase Taxes and Charges": {
|
||||||
"doctype": "Purchase Taxes and Charges",
|
"doctype": "Purchase Taxes and Charges",
|
||||||
"add_if_empty": True
|
"add_if_empty": True
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if frappe.get_single("Accounts Settings").automatically_fetch_payment_terms == 1:
|
||||||
|
fields["Payment Schedule"] = {
|
||||||
|
"doctype": "Payment Schedule",
|
||||||
|
"add_if_empty": True
|
||||||
}
|
}
|
||||||
}, target_doc, postprocess)
|
|
||||||
|
doc = get_mapped_doc("Purchase Order", source_name, fields, target_doc, postprocess)
|
||||||
|
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import unittest
|
|||||||
import frappe
|
import frappe
|
||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
|
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
|
||||||
from frappe.utils import flt, add_days, nowdate
|
from frappe.utils import flt, add_days, nowdate, getdate
|
||||||
from erpnext.stock.doctype.item.test_item import make_item
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
from erpnext.buying.doctype.purchase_order.purchase_order import (make_purchase_receipt, make_purchase_invoice, make_rm_stock_entry as make_subcontract_transfer_entry)
|
from erpnext.buying.doctype.purchase_order.purchase_order import (make_purchase_receipt, make_purchase_invoice, make_rm_stock_entry as make_subcontract_transfer_entry)
|
||||||
from erpnext.stock.doctype.material_request.test_material_request import make_material_request
|
from erpnext.stock.doctype.material_request.test_material_request import make_material_request
|
||||||
@ -142,9 +142,9 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
po.submit()
|
po.submit()
|
||||||
|
|
||||||
self.assertEqual(po.payment_schedule[0].payment_amount, 2500.0)
|
self.assertEqual(po.payment_schedule[0].payment_amount, 2500.0)
|
||||||
self.assertEqual(po.payment_schedule[0].due_date, po.transaction_date)
|
self.assertEqual(getdate(po.payment_schedule[0].due_date), getdate(po.transaction_date))
|
||||||
self.assertEqual(po.payment_schedule[1].payment_amount, 2500.0)
|
self.assertEqual(po.payment_schedule[1].payment_amount, 2500.0)
|
||||||
self.assertEqual(po.payment_schedule[1].due_date, add_days(po.transaction_date, 30))
|
self.assertEqual(getdate(po.payment_schedule[1].due_date), add_days(getdate(po.transaction_date), 30))
|
||||||
pi = make_purchase_invoice(po.name)
|
pi = make_purchase_invoice(po.name)
|
||||||
pi.save()
|
pi.save()
|
||||||
|
|
||||||
@ -152,9 +152,9 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
self.assertEqual(len(pi.get("items", [])), 1)
|
self.assertEqual(len(pi.get("items", [])), 1)
|
||||||
|
|
||||||
self.assertEqual(pi.payment_schedule[0].payment_amount, 2500.0)
|
self.assertEqual(pi.payment_schedule[0].payment_amount, 2500.0)
|
||||||
self.assertEqual(pi.payment_schedule[0].due_date, po.transaction_date)
|
self.assertEqual(getdate(pi.payment_schedule[0].due_date), getdate(po.transaction_date))
|
||||||
self.assertEqual(pi.payment_schedule[1].payment_amount, 2500.0)
|
self.assertEqual(pi.payment_schedule[1].payment_amount, 2500.0)
|
||||||
self.assertEqual(pi.payment_schedule[1].due_date, add_days(po.transaction_date, 30))
|
self.assertEqual(getdate(pi.payment_schedule[1].due_date), add_days(getdate(po.transaction_date), 30))
|
||||||
|
|
||||||
def test_subcontracting(self):
|
def test_subcontracting(self):
|
||||||
po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes")
|
po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes")
|
||||||
@ -303,6 +303,10 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100)
|
make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100)
|
||||||
make_stock_entry(target="_Test Warehouse - _TC", item_code="_Test Item Home Desktop 100",
|
make_stock_entry(target="_Test Warehouse - _TC", item_code="_Test Item Home Desktop 100",
|
||||||
qty=20, basic_rate=100)
|
qty=20, basic_rate=100)
|
||||||
|
make_stock_entry(target="_Test Warehouse 1 - _TC", item_code="_Test Item",
|
||||||
|
qty=30, basic_rate=100)
|
||||||
|
make_stock_entry(target="_Test Warehouse 1 - _TC", item_code="_Test Item Home Desktop 100",
|
||||||
|
qty=30, basic_rate=100)
|
||||||
|
|
||||||
bin1 = frappe.db.get_value("Bin",
|
bin1 = frappe.db.get_value("Bin",
|
||||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||||
@ -349,6 +353,11 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEquals(bin5.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
|
self.assertEquals(bin5.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
|
||||||
|
|
||||||
|
make_stock_entry(target="_Test Warehouse 1 - _TC", item_code="_Test Item",
|
||||||
|
qty=40, basic_rate=100)
|
||||||
|
make_stock_entry(target="_Test Warehouse 1 - _TC", item_code="_Test Item Home Desktop 100",
|
||||||
|
qty=40, basic_rate=100)
|
||||||
|
|
||||||
# make Purchase Receipt against PO
|
# make Purchase Receipt against PO
|
||||||
pr = make_purchase_receipt(po.name)
|
pr = make_purchase_receipt(po.name)
|
||||||
pr.supplier_warehouse = "_Test Warehouse 1 - _TC"
|
pr.supplier_warehouse = "_Test Warehouse 1 - _TC"
|
||||||
|
@ -600,3 +600,4 @@ erpnext.patches.v11_1.woocommerce_set_creation_user
|
|||||||
erpnext.patches.v11_1.set_salary_details_submittable
|
erpnext.patches.v11_1.set_salary_details_submittable
|
||||||
erpnext.patches.v11_1.rename_depends_on_lwp
|
erpnext.patches.v11_1.rename_depends_on_lwp
|
||||||
execute:frappe.delete_doc("Report", "Inactive Items")
|
execute:frappe.delete_doc("Report", "Inactive Items")
|
||||||
|
erpnext.patches.v11_1.delete_scheduling_tool
|
||||||
|
9
erpnext/patches/v11_1/delete_scheduling_tool.py
Normal file
9
erpnext/patches/v11_1/delete_scheduling_tool.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
if frappe.db.exists("DocType", "Scheduling Tool"):
|
||||||
|
frappe.delete_doc("DocType", "Scheduling Tool", ignore_permissions=True)
|
@ -66,15 +66,14 @@ class ItemVariantsCacheManager:
|
|||||||
as_list=1
|
as_list=1
|
||||||
)
|
)
|
||||||
|
|
||||||
disabled_items = [i.name for i in frappe.db.get_all('Item', {'disabled': 1})]
|
disabled_items = set([i.name for i in frappe.db.get_all('Item', {'disabled': 1})])
|
||||||
|
|
||||||
attribute_value_item_map = frappe._dict({})
|
attribute_value_item_map = frappe._dict({})
|
||||||
item_attribute_value_map = frappe._dict({})
|
item_attribute_value_map = frappe._dict({})
|
||||||
|
|
||||||
|
item_variants_data = [r for r in item_variants_data if r[0] not in disabled_items]
|
||||||
for row in item_variants_data:
|
for row in item_variants_data:
|
||||||
item_code, attribute, attribute_value = row
|
item_code, attribute, attribute_value = row
|
||||||
if item_code in disabled_items:
|
|
||||||
continue
|
|
||||||
# (attr, value) => [item1, item2]
|
# (attr, value) => [item1, item2]
|
||||||
attribute_value_item_map.setdefault((attribute, attribute_value), []).append(item_code)
|
attribute_value_item_map.setdefault((attribute, attribute_value), []).append(item_code)
|
||||||
# item => {attr1: value1, attr2: value2}
|
# item => {attr1: value1, attr2: value2}
|
||||||
@ -97,6 +96,10 @@ class ItemVariantsCacheManager:
|
|||||||
for key in keys:
|
for key in keys:
|
||||||
frappe.cache().hdel(key, self.item_code)
|
frappe.cache().hdel(key, self.item_code)
|
||||||
|
|
||||||
|
def rebuild_cache(self):
|
||||||
|
self.clear_cache()
|
||||||
|
enqueue_build_cache(self.item_code)
|
||||||
|
|
||||||
|
|
||||||
def build_cache(item_code):
|
def build_cache(item_code):
|
||||||
frappe.cache().hset('item_cache_build_in_progress', item_code, 1)
|
frappe.cache().hset('item_cache_build_in_progress', item_code, 1)
|
||||||
|
@ -260,7 +260,8 @@ def get_items_with_selected_attributes(item_code, selected_attributes):
|
|||||||
|
|
||||||
items = []
|
items = []
|
||||||
for attribute, value in selected_attributes.items():
|
for attribute, value in selected_attributes.items():
|
||||||
items.append(set(attribute_value_item_map[(attribute, value)]))
|
filtered_items = attribute_value_item_map.get((attribute, value), [])
|
||||||
|
items.append(set(filtered_items))
|
||||||
|
|
||||||
return set.intersection(*items)
|
return set.intersection(*items)
|
||||||
|
|
||||||
|
@ -109,6 +109,18 @@ frappe.ui.form.on("Project", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
status: function(frm) {
|
||||||
|
if (frm.doc.status === 'Cancelled') {
|
||||||
|
frappe.confirm(__('Set tasks in this project as cancelled?'), () => {
|
||||||
|
frm.doc.tasks = frm.doc.tasks.map(task => {
|
||||||
|
task.status = 'Cancelled';
|
||||||
|
return task;
|
||||||
|
});
|
||||||
|
frm.refresh_field('tasks');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on("Project Task", {
|
frappe.ui.form.on("Project Task", {
|
||||||
|
@ -35,6 +35,9 @@ class Project(Document):
|
|||||||
|
|
||||||
def load_tasks(self):
|
def load_tasks(self):
|
||||||
"""Load `tasks` from the database"""
|
"""Load `tasks` from the database"""
|
||||||
|
if frappe.flags.in_import:
|
||||||
|
return
|
||||||
|
|
||||||
self.tasks = []
|
self.tasks = []
|
||||||
for task in self.get_tasks():
|
for task in self.get_tasks():
|
||||||
task_map = {
|
task_map = {
|
||||||
@ -358,7 +361,8 @@ class Project(Document):
|
|||||||
if not self.get('deleted_task_list'): return
|
if not self.get('deleted_task_list'): return
|
||||||
|
|
||||||
for d in self.get('deleted_task_list'):
|
for d in self.get('deleted_task_list'):
|
||||||
frappe.delete_doc("Task", d)
|
# unlink project
|
||||||
|
frappe.db.set_value('Task', d, 'project', '')
|
||||||
|
|
||||||
self.deleted_task_list = []
|
self.deleted_task_list = []
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ class Task(NestedSet):
|
|||||||
|
|
||||||
def update_project(self):
|
def update_project(self):
|
||||||
if self.project and not self.flags.from_project:
|
if self.project and not self.flags.from_project:
|
||||||
frappe.get_doc("Project", self.project).update_project()
|
frappe.get_cached_doc("Project", self.project).update_project()
|
||||||
|
|
||||||
def check_recursion(self):
|
def check_recursion(self):
|
||||||
if self.flags.ignore_recursion_check: return
|
if self.flags.ignore_recursion_check: return
|
||||||
@ -150,7 +150,7 @@ class Task(NestedSet):
|
|||||||
|
|
||||||
def populate_depends_on(self):
|
def populate_depends_on(self):
|
||||||
if self.parent_task:
|
if self.parent_task:
|
||||||
parent = frappe.get_doc('Task', self.parent_task)
|
parent = frappe.get_cached_doc('Task', self.parent_task)
|
||||||
if not self.name in [row.task for row in parent.depends_on]:
|
if not self.name in [row.task for row in parent.depends_on]:
|
||||||
parent.append("depends_on", {
|
parent.append("depends_on", {
|
||||||
"doctype": "Task Depends On",
|
"doctype": "Task Depends On",
|
||||||
|
@ -123,5 +123,6 @@ frappe.ui.form.on("Customer", {
|
|||||||
},
|
},
|
||||||
validate: function(frm) {
|
validate: function(frm) {
|
||||||
if(frm.doc.lead_name) frappe.model.clear_doc("Lead", frm.doc.lead_name);
|
if(frm.doc.lead_name) frappe.model.clear_doc("Lead", frm.doc.lead_name);
|
||||||
|
|
||||||
},
|
},
|
||||||
});
|
});
|
@ -60,6 +60,10 @@ class Customer(TransactionBase):
|
|||||||
if self.loyalty_program == customer.loyalty_program and not self.loyalty_program_tier:
|
if self.loyalty_program == customer.loyalty_program and not self.loyalty_program_tier:
|
||||||
self.loyalty_program_tier = customer.loyalty_program_tier
|
self.loyalty_program_tier = customer.loyalty_program_tier
|
||||||
|
|
||||||
|
if self.sales_team:
|
||||||
|
if sum([member.allocated_percentage for member in self.sales_team]) != 100:
|
||||||
|
frappe.throw(_("Total contribution percentage should be equal to 100"))
|
||||||
|
|
||||||
def check_customer_group_change(self):
|
def check_customer_group_change(self):
|
||||||
frappe.flags.customer_group_changed = False
|
frappe.flags.customer_group_changed = False
|
||||||
|
|
||||||
|
@ -966,7 +966,7 @@ def invalidate_item_variants_cache_for_website(doc):
|
|||||||
|
|
||||||
if item_code:
|
if item_code:
|
||||||
item_cache = ItemVariantsCacheManager(item_code)
|
item_cache = ItemVariantsCacheManager(item_code)
|
||||||
item_cache.clear_cache()
|
item_cache.rebuild_cache()
|
||||||
|
|
||||||
|
|
||||||
def check_stock_uom_with_bin(item, stock_uom):
|
def check_stock_uom_with_bin(item, stock_uom):
|
||||||
|
@ -1116,7 +1116,7 @@ class StockEntry(StockController):
|
|||||||
frappe.MappingMismatchError)
|
frappe.MappingMismatchError)
|
||||||
|
|
||||||
def validate_batch(self):
|
def validate_batch(self):
|
||||||
if self.purpose in ["Material Transfer for Manufacture", "Manufacture", "Repack", "Send to Subcontractor", "Material Issue"]:
|
if self.purpose in ["Material Transfer for Manufacture", "Manufacture", "Repack", "Send to Subcontractor"]:
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
if item.batch_no:
|
if item.batch_no:
|
||||||
disabled = frappe.db.get_value("Batch", item.batch_no, "disabled")
|
disabled = frappe.db.get_value("Batch", item.batch_no, "disabled")
|
||||||
|
@ -40,6 +40,13 @@ $(document).ready(function() {
|
|||||||
right: 0%;
|
right: 0%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
{% include "templates/styles/card_style.css" %}
|
||||||
|
header, footer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
html, body {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user