mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-25 07:54:46 +00:00
Merge pull request #4335 from saurabh6790/drop-ship-fixes-1
Move Drop Ship from Purchase Order to Purchase Order Items
This commit is contained in:
@@ -379,6 +379,8 @@ class SalesInvoice(SellingController):
|
|||||||
msgprint(_("Item Code required at Row No {0}").format(d.idx), raise_exception=True)
|
msgprint(_("Item Code required at Row No {0}").format(d.idx), raise_exception=True)
|
||||||
|
|
||||||
def validate_warehouse(self):
|
def validate_warehouse(self):
|
||||||
|
super(SalesInvoice, self).validate_warehouse()
|
||||||
|
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if not d.warehouse:
|
if not d.warehouse:
|
||||||
frappe.throw(_("Warehouse required at Row No {0}").format(d.idx))
|
frappe.throw(_("Warehouse required at Row No {0}").format(d.idx))
|
||||||
|
|||||||
@@ -18,9 +18,27 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
|||||||
var me = this;
|
var me = this;
|
||||||
this._super();
|
this._super();
|
||||||
// this.frm.dashboard.reset();
|
// this.frm.dashboard.reset();
|
||||||
|
var allow_receipt = false;
|
||||||
|
var is_drop_ship = false;
|
||||||
|
|
||||||
|
for (var i in cur_frm.doc.items) {
|
||||||
|
var item = cur_frm.doc.items[i];
|
||||||
|
if(item.delivered_by_supplier !== 1) {
|
||||||
|
allow_receipt = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
is_drop_ship = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_drop_ship && allow_receipt) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_frm.set_df_property("drop_ship", "hidden", !is_drop_ship);
|
||||||
|
|
||||||
if(doc.docstatus == 1 && !in_list(["Stopped", "Closed", "Delivered"], doc.status)) {
|
if(doc.docstatus == 1 && !in_list(["Stopped", "Closed", "Delivered"], doc.status)) {
|
||||||
|
|
||||||
if (this.frm.has_perm("submit")) {
|
if (this.frm.has_perm("submit")) {
|
||||||
if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100) {
|
if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100) {
|
||||||
cur_frm.add_custom_button(__('Stop'), this.stop_purchase_order);
|
cur_frm.add_custom_button(__('Stop'), this.stop_purchase_order);
|
||||||
@@ -29,7 +47,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
|||||||
cur_frm.add_custom_button(__('Close'), this.close_purchase_order);
|
cur_frm.add_custom_button(__('Close'), this.close_purchase_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(doc.delivered_by_supplier && doc.status!="Delivered"){
|
if(is_drop_ship && doc.status!="Delivered"){
|
||||||
cur_frm.add_custom_button(__('Mark as Delivered'), this.delivered_by_supplier);
|
cur_frm.add_custom_button(__('Mark as Delivered'), this.delivered_by_supplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +55,12 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
|||||||
cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_bank_entry);
|
cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_bank_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(flt(doc.per_received, 2) < 100 && this.frm.doc.__onload.has_stock_item) {
|
} else if(doc.docstatus===0) {
|
||||||
|
cur_frm.cscript.add_from_mappers();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(doc.docstatus == 1 && !in_list(["Stopped", "Closed"], doc.status)) {
|
||||||
|
if(flt(doc.per_received, 2) < 100 && this.frm.doc.__onload.has_stock_item && allow_receipt) {
|
||||||
cur_frm.add_custom_button(__('Receive'), this.make_purchase_receipt).addClass("btn-primary");
|
cur_frm.add_custom_button(__('Receive'), this.make_purchase_receipt).addClass("btn-primary");
|
||||||
|
|
||||||
if(doc.is_subcontracted==="Yes") {
|
if(doc.is_subcontracted==="Yes") {
|
||||||
@@ -47,13 +70,9 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(flt(doc.per_billed, 2) < 100)
|
if(flt(doc.per_billed, 2) < 100)
|
||||||
cur_frm.add_custom_button(__('Invoice'), this.make_purchase_invoice);
|
cur_frm.add_custom_button(__('Invoice'), this.make_purchase_invoice);
|
||||||
|
|
||||||
|
|
||||||
} else if(doc.docstatus===0) {
|
|
||||||
cur_frm.cscript.add_from_mappers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(doc.docstatus == 1 && in_list(["Stopped", "Closed", "Delivered"], doc.status)) {
|
if(doc.docstatus == 1 && in_list(["Stopped", "Closed", "Delivered"], doc.status)) {
|
||||||
if (this.frm.has_perm("submit")) {
|
if (this.frm.has_perm("submit")) {
|
||||||
cur_frm.add_custom_button(__('Re-open'), this.unstop_purchase_order);
|
cur_frm.add_custom_button(__('Re-open'), this.unstop_purchase_order);
|
||||||
|
|||||||
@@ -330,8 +330,8 @@
|
|||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 1,
|
"collapsible": 0,
|
||||||
"collapsible_depends_on": "delivered_by_supplier",
|
"collapsible_depends_on": "",
|
||||||
"fieldname": "drop_ship",
|
"fieldname": "drop_ship",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -354,7 +354,7 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"depends_on": "delivered_by_supplier",
|
"depends_on": "",
|
||||||
"fieldname": "customer",
|
"fieldname": "customer",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -378,7 +378,7 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"depends_on": "delivered_by_supplier",
|
"depends_on": "",
|
||||||
"fieldname": "customer_name",
|
"fieldname": "customer_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -397,28 +397,6 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"fieldname": "delivered_by_supplier",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"label": "To be delivered to customer",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 1,
|
|
||||||
"read_only": 1,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@@ -444,7 +422,7 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"depends_on": "delivered_by_supplier",
|
"depends_on": "",
|
||||||
"fieldname": "customer_address",
|
"fieldname": "customer_address",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -468,7 +446,7 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
"depends_on": "delivered_by_supplier",
|
"depends_on": "",
|
||||||
"fieldname": "customer_contact_person",
|
"fieldname": "customer_contact_person",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@@ -2283,7 +2261,7 @@
|
|||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2015-11-04 04:44:22.025827",
|
"modified": "2015-11-17 14:40:16.374394",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order",
|
"name": "Purchase Order",
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ class PurchaseOrder(BuyingController):
|
|||||||
self.validate_for_subcontracting()
|
self.validate_for_subcontracting()
|
||||||
self.validate_minimum_order_qty()
|
self.validate_minimum_order_qty()
|
||||||
self.create_raw_materials_supplied("supplied_items")
|
self.create_raw_materials_supplied("supplied_items")
|
||||||
|
self.set_received_qty_and_billed_amount_for_drop_ship_items()
|
||||||
|
|
||||||
def validate_with_previous_doc(self):
|
def validate_with_previous_doc(self):
|
||||||
super(PurchaseOrder, self).validate_with_previous_doc({
|
super(PurchaseOrder, self).validate_with_previous_doc({
|
||||||
@@ -137,9 +138,11 @@ class PurchaseOrder(BuyingController):
|
|||||||
"""update requested qty (before ordered_qty is updated)"""
|
"""update requested qty (before ordered_qty is updated)"""
|
||||||
item_wh_list = []
|
item_wh_list = []
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if (not po_item_rows or d.name in po_item_rows) and [d.item_code, d.warehouse] not in item_wh_list \
|
if (not po_item_rows or d.name in po_item_rows) \
|
||||||
and frappe.db.get_value("Item", d.item_code, "is_stock_item") and d.warehouse:
|
and [d.item_code, d.warehouse] not in item_wh_list \
|
||||||
item_wh_list.append([d.item_code, d.warehouse])
|
and frappe.db.get_value("Item", d.item_code, "is_stock_item") \
|
||||||
|
and d.warehouse and not d.delivered_by_supplier:
|
||||||
|
item_wh_list.append([d.item_code, d.warehouse])
|
||||||
|
|
||||||
for item_code, warehouse in item_wh_list:
|
for item_code, warehouse in item_wh_list:
|
||||||
update_bin_qty(item_code, warehouse, {
|
update_bin_qty(item_code, warehouse, {
|
||||||
@@ -164,13 +167,13 @@ class PurchaseOrder(BuyingController):
|
|||||||
clear_doctype_notifications(self)
|
clear_doctype_notifications(self)
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
if self.delivered_by_supplier == 1:
|
if self.has_drop_ship_item():
|
||||||
self.update_status_updater()
|
self.update_status_updater()
|
||||||
|
|
||||||
super(PurchaseOrder, self).on_submit()
|
super(PurchaseOrder, self).on_submit()
|
||||||
|
|
||||||
purchase_controller = frappe.get_doc("Purchase Common")
|
purchase_controller = frappe.get_doc("Purchase Common")
|
||||||
|
|
||||||
self.update_prevdoc_status()
|
self.update_prevdoc_status()
|
||||||
self.update_requested_qty()
|
self.update_requested_qty()
|
||||||
self.update_ordered_qty()
|
self.update_ordered_qty()
|
||||||
@@ -181,7 +184,7 @@ class PurchaseOrder(BuyingController):
|
|||||||
purchase_controller.update_last_purchase_rate(self, is_submit = 1)
|
purchase_controller.update_last_purchase_rate(self, is_submit = 1)
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
if self.delivered_by_supplier == 1:
|
if self.has_drop_ship_item():
|
||||||
self.update_status_updater()
|
self.update_status_updater()
|
||||||
|
|
||||||
pc_obj = frappe.get_doc('Purchase Common')
|
pc_obj = frappe.get_doc('Purchase Common')
|
||||||
@@ -234,7 +237,7 @@ class PurchaseOrder(BuyingController):
|
|||||||
"""Update delivered qty in Sales Order for drop ship"""
|
"""Update delivered qty in Sales Order for drop ship"""
|
||||||
sales_orders_to_update = []
|
sales_orders_to_update = []
|
||||||
for item in self.items:
|
for item in self.items:
|
||||||
if item.prevdoc_doctype == "Sales Order":
|
if item.prevdoc_doctype == "Sales Order" and item.delivered_by_supplier == 1:
|
||||||
if item.prevdoc_docname not in sales_orders_to_update:
|
if item.prevdoc_docname not in sales_orders_to_update:
|
||||||
sales_orders_to_update.append(item.prevdoc_docname)
|
sales_orders_to_update.append(item.prevdoc_docname)
|
||||||
|
|
||||||
@@ -244,6 +247,21 @@ class PurchaseOrder(BuyingController):
|
|||||||
so.set_status(update=True)
|
so.set_status(update=True)
|
||||||
so.notify_update()
|
so.notify_update()
|
||||||
|
|
||||||
|
def has_drop_ship_item(self):
|
||||||
|
is_drop_ship = False
|
||||||
|
|
||||||
|
for item in self.items:
|
||||||
|
if item.delivered_by_supplier == 1:
|
||||||
|
is_drop_ship = True
|
||||||
|
|
||||||
|
return is_drop_ship
|
||||||
|
|
||||||
|
def set_received_qty_and_billed_amount_for_drop_ship_items(self):
|
||||||
|
for item in self.items:
|
||||||
|
if item.delivered_by_supplier == 1:
|
||||||
|
item.received_qty = item.qty
|
||||||
|
item.billed_amt = item.amount
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def stop_or_unstop_purchase_orders(names, status):
|
def stop_or_unstop_purchase_orders(names, status):
|
||||||
if not frappe.has_permission("Purchase Order", "write"):
|
if not frappe.has_permission("Purchase Order", "write"):
|
||||||
@@ -262,7 +280,6 @@ def stop_or_unstop_purchase_orders(names, status):
|
|||||||
|
|
||||||
frappe.local.message_log = []
|
frappe.local.message_log = []
|
||||||
|
|
||||||
|
|
||||||
def set_missing_values(source, target):
|
def set_missing_values(source, target):
|
||||||
target.ignore_pricing_rule = 1
|
target.ignore_pricing_rule = 1
|
||||||
target.run_method("set_missing_values")
|
target.run_method("set_missing_values")
|
||||||
@@ -292,7 +309,7 @@ def make_purchase_receipt(source_name, target_doc=None):
|
|||||||
"parenttype": "prevdoc_doctype",
|
"parenttype": "prevdoc_doctype",
|
||||||
},
|
},
|
||||||
"postprocess": update_item,
|
"postprocess": update_item,
|
||||||
"condition": lambda doc: doc.received_qty < doc.qty
|
"condition": lambda doc: doc.received_qty < doc.qty and doc.delivered_by_supplier!=1
|
||||||
},
|
},
|
||||||
"Purchase Taxes and Charges": {
|
"Purchase Taxes and Charges": {
|
||||||
"doctype": "Purchase Taxes and Charges",
|
"doctype": "Purchase Taxes and Charges",
|
||||||
@@ -328,7 +345,7 @@ def make_purchase_invoice(source_name, target_doc=None):
|
|||||||
"parent": "purchase_order",
|
"parent": "purchase_order",
|
||||||
},
|
},
|
||||||
"postprocess": update_item,
|
"postprocess": update_item,
|
||||||
"condition": lambda doc: doc.base_amount==0 or doc.billed_amt < doc.amount
|
"condition": lambda doc: (doc.base_amount==0 or doc.billed_amt < doc.amount) and doc.delivered_by_supplier!=1
|
||||||
},
|
},
|
||||||
"Purchase Taxes and Charges": {
|
"Purchase Taxes and Charges": {
|
||||||
"doctype": "Purchase Taxes and Charges",
|
"doctype": "Purchase Taxes and Charges",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -52,15 +52,6 @@ class BuyingController(StockController):
|
|||||||
self.supplier = supplier
|
self.supplier = supplier
|
||||||
break
|
break
|
||||||
|
|
||||||
def validate_warehouse(self):
|
|
||||||
from erpnext.stock.utils import validate_warehouse_company
|
|
||||||
|
|
||||||
warehouses = list(set([d.warehouse for d in
|
|
||||||
self.get("items") if getattr(d, "warehouse", None)]))
|
|
||||||
|
|
||||||
for w in warehouses:
|
|
||||||
validate_warehouse_company(w, self.company)
|
|
||||||
|
|
||||||
def validate_stock_or_nonstock_items(self):
|
def validate_stock_or_nonstock_items(self):
|
||||||
if self.meta.get_field("taxes") and not self.get_stock_items():
|
if self.meta.get_field("taxes") and not self.get_stock_items():
|
||||||
tax_for_valuation = [d.account_head for d in self.get("taxes")
|
tax_for_valuation = [d.account_head for d in self.get("taxes")
|
||||||
|
|||||||
@@ -303,6 +303,15 @@ class StockController(AccountsController):
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
self.make_sl_entries(sl_entries)
|
self.make_sl_entries(sl_entries)
|
||||||
|
|
||||||
|
def validate_warehouse(self):
|
||||||
|
from erpnext.stock.utils import validate_warehouse_company
|
||||||
|
|
||||||
|
warehouses = list(set([d.warehouse for d in
|
||||||
|
self.get("items") if getattr(d, "warehouse", None)]))
|
||||||
|
|
||||||
|
for w in warehouses:
|
||||||
|
validate_warehouse_company(w, self.company)
|
||||||
|
|
||||||
def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
|
def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
|
||||||
warehouse_account=None):
|
warehouse_account=None):
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import unittest
|
|||||||
from frappe.utils import getdate
|
from frappe.utils import getdate
|
||||||
|
|
||||||
class TestLeaveAllocation(unittest.TestCase):
|
class TestLeaveAllocation(unittest.TestCase):
|
||||||
def test_overlapping_allocation(self):
|
def test_overlapping_allocation(self):
|
||||||
|
frappe.db.sql("delete from `tabLeave Allocation`")
|
||||||
|
|
||||||
employee = frappe.get_doc("Employee", frappe.db.sql_list("select name from tabEmployee limit 1")[0])
|
employee = frappe.get_doc("Employee", frappe.db.sql_list("select name from tabEmployee limit 1")[0])
|
||||||
leaves = [
|
leaves = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,7 +44,11 @@ _test_records = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class TestLeaveApplication(unittest.TestCase):
|
class TestLeaveApplication(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
for dt in ["Leave Application", "Leave Allocation", "Salary Slip"]:
|
||||||
|
frappe.db.sql("delete from `tab%s`" % dt)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
frappe.set_user("Administrator")
|
frappe.set_user("Administrator")
|
||||||
|
|
||||||
@@ -97,6 +101,8 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
|
|
||||||
frappe.db.set_value("Department", "_Test Department",
|
frappe.db.set_value("Department", "_Test Department",
|
||||||
"leave_block_list", "_Test Leave Block List")
|
"leave_block_list", "_Test Leave Block List")
|
||||||
|
|
||||||
|
make_allocation_record()
|
||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.insert()
|
application.insert()
|
||||||
@@ -120,6 +126,9 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
add_role("test2@example.com", "Leave Approver")
|
add_role("test2@example.com", "Leave Approver")
|
||||||
|
|
||||||
frappe.set_user("test@example.com")
|
frappe.set_user("test@example.com")
|
||||||
|
|
||||||
|
make_allocation_record()
|
||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
application.leave_approver = "test2@example.com"
|
||||||
application.insert()
|
application.insert()
|
||||||
@@ -135,7 +144,9 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
add_role("test1@example.com", "Employee")
|
add_role("test1@example.com", "Employee")
|
||||||
add_role("test@example.com", "Leave Approver")
|
add_role("test@example.com", "Leave Approver")
|
||||||
self._add_employee_leave_approver("_T-Employee-0002", "test@example.com")
|
self._add_employee_leave_approver("_T-Employee-0002", "test@example.com")
|
||||||
|
|
||||||
|
make_allocation_record(employee="_T-Employee-0002")
|
||||||
|
|
||||||
application = self.get_application(_test_records[1])
|
application = self.get_application(_test_records[1])
|
||||||
application.leave_approver = "test@example.com"
|
application.leave_approver = "test@example.com"
|
||||||
|
|
||||||
@@ -175,6 +186,9 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
|
|
||||||
# create leave application as Employee
|
# create leave application as Employee
|
||||||
frappe.set_user("test@example.com")
|
frappe.set_user("test@example.com")
|
||||||
|
|
||||||
|
make_allocation_record()
|
||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test1@example.com"
|
application.leave_approver = "test1@example.com"
|
||||||
application.insert()
|
application.insert()
|
||||||
@@ -196,6 +210,8 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com")
|
self._add_employee_leave_approver("_T-Employee-0001", "test2@example.com")
|
||||||
self._remove_employee_leave_approver("_T-Employee-0001", "test1@example.com")
|
self._remove_employee_leave_approver("_T-Employee-0001", "test1@example.com")
|
||||||
|
|
||||||
|
make_allocation_record()
|
||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
frappe.set_user("test@example.com")
|
frappe.set_user("test@example.com")
|
||||||
|
|
||||||
@@ -212,6 +228,9 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
# create leave application as employee
|
# create leave application as employee
|
||||||
# but submit as invalid leave approver - should raise exception
|
# but submit as invalid leave approver - should raise exception
|
||||||
frappe.set_user("test@example.com")
|
frappe.set_user("test@example.com")
|
||||||
|
|
||||||
|
make_allocation_record()
|
||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
application.leave_approver = "test2@example.com"
|
||||||
application.insert()
|
application.insert()
|
||||||
@@ -232,6 +251,9 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
frappe.db.set_value("Employee", "_T-Employee-0001", "department", None)
|
frappe.db.set_value("Employee", "_T-Employee-0001", "department", None)
|
||||||
|
|
||||||
frappe.set_user("test@example.com")
|
frappe.set_user("test@example.com")
|
||||||
|
|
||||||
|
make_allocation_record()
|
||||||
|
|
||||||
application = self.get_application(_test_records[0])
|
application = self.get_application(_test_records[0])
|
||||||
application.leave_approver = "test2@example.com"
|
application.leave_approver = "test2@example.com"
|
||||||
application.insert()
|
application.insert()
|
||||||
@@ -246,4 +268,19 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
frappe.db.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
|
frappe.db.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
|
||||||
"_T-Employee-0001")
|
"_T-Employee-0001")
|
||||||
|
|
||||||
frappe.db.set_value("Employee", "_T-Employee-0001", "department", original_department)
|
frappe.db.set_value("Employee", "_T-Employee-0001", "department", original_department)
|
||||||
|
|
||||||
|
def make_allocation_record(employee=None, leave_type=None):
|
||||||
|
frappe.db.sql("delete from `tabLeave Allocation`")
|
||||||
|
|
||||||
|
allocation = frappe.get_doc({
|
||||||
|
"doctype": "Leave Allocation",
|
||||||
|
"employee": employee or "_T-Employee-0001",
|
||||||
|
"leave_type": leave_type or "_Test Leave Type",
|
||||||
|
"from_date": "2013-01-01",
|
||||||
|
"to_date": "2015-12-31",
|
||||||
|
"new_leaves_allocated": 30
|
||||||
|
})
|
||||||
|
|
||||||
|
allocation.insert(ignore_permissions=True)
|
||||||
|
allocation.submit()
|
||||||
|
|||||||
@@ -7,23 +7,14 @@ import frappe
|
|||||||
from frappe.utils import today
|
from frappe.utils import today
|
||||||
from erpnext.hr.doctype.employee.employee import make_salary_structure
|
from erpnext.hr.doctype.employee.employee import make_salary_structure
|
||||||
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
|
||||||
|
from erpnext.hr.doctype.leave_application.test_leave_application import make_allocation_record
|
||||||
|
|
||||||
class TestSalarySlip(unittest.TestCase):
|
class TestSalarySlip(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
for dt in ["Leave Application", "Leave Allocation", "Salary Slip"]:
|
for dt in ["Leave Application", "Leave Allocation", "Salary Slip"]:
|
||||||
frappe.db.sql("delete from `tab%s`" % dt)
|
frappe.db.sql("delete from `tab%s`" % dt)
|
||||||
|
|
||||||
allocation = frappe.get_doc({
|
make_allocation_record(leave_type="_Test Leave Type LWP")
|
||||||
"doctype": "Leave Allocation",
|
|
||||||
"employee": "_T-Employee-0001",
|
|
||||||
"leave_type": "_Test Leave Type LWP",
|
|
||||||
"from_date": "2013-01-01",
|
|
||||||
"to_date": "2015-12-31",
|
|
||||||
"new_leaves_allocated": 5
|
|
||||||
})
|
|
||||||
|
|
||||||
allocation.insert()
|
|
||||||
allocation.submit()
|
|
||||||
|
|
||||||
frappe.db.set_value("Holiday List", "_Test Holiday List", "is_default", 1)
|
frappe.db.set_value("Holiday List", "_Test Holiday List", "is_default", 1)
|
||||||
|
|
||||||
|
|||||||
@@ -233,3 +233,4 @@ erpnext.patches.v6_6.fix_website_image
|
|||||||
erpnext.patches.v6_6.remove_fiscal_year_from_leave_allocation
|
erpnext.patches.v6_6.remove_fiscal_year_from_leave_allocation
|
||||||
execute:frappe.delete_doc_if_exists("DocType", "Stock UOM Replace Utility")
|
execute:frappe.delete_doc_if_exists("DocType", "Stock UOM Replace Utility")
|
||||||
erpnext.patches.v6_8.make_webform_standard
|
erpnext.patches.v6_8.make_webform_standard
|
||||||
|
erpnext.patches.v6_8.move_drop_ship_to_po_items
|
||||||
|
|||||||
36
erpnext/patches/v6_8/move_drop_ship_to_po_items.py
Normal file
36
erpnext/patches/v6_8/move_drop_ship_to_po_items.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
for po in frappe.get_all("Purchase Order", filters={"delivered_by_supplier": 1}, fields=["name"]):
|
||||||
|
purchase_order = frappe.get_doc("Purchase Order", po)
|
||||||
|
|
||||||
|
for item in purchase_order.items:
|
||||||
|
if item.prevdoc_doctype == "Sales Order":
|
||||||
|
delivered_by_supplier = frappe.get_value("Sales Order Item", item.prevdoc_detail_docname,
|
||||||
|
"delivered_by_supplier")
|
||||||
|
|
||||||
|
if delivered_by_supplier:
|
||||||
|
frappe.db.sql("""update `tabPurchase Order Item`
|
||||||
|
set delivered_by_supplier=1, billed_amt=amount, received_qty=qty
|
||||||
|
where name=%s """, item.name)
|
||||||
|
|
||||||
|
update_per_received(purchase_order)
|
||||||
|
update_per_billed(purchase_order)
|
||||||
|
|
||||||
|
def update_per_received(po):
|
||||||
|
frappe.db.sql(""" update `tabPurchase Order`
|
||||||
|
set per_received = round((select sum(if(qty > ifnull(received_qty, 0),
|
||||||
|
ifnull(received_qty, 0), qty)) / sum(qty) *100
|
||||||
|
from `tabPurchase Order Item`
|
||||||
|
where parent = %(name)s), 2)
|
||||||
|
where name = %(name)s """, {"name": po.name})
|
||||||
|
|
||||||
|
def update_per_billed(po):
|
||||||
|
frappe.db.sql(""" update `tabPurchase Order`
|
||||||
|
set per_billed = round((select sum( if(amount > ifnull(billed_amt, 0),
|
||||||
|
ifnull(billed_amt, 0), amount)) / sum(amount) *100
|
||||||
|
from `tabPurchase Order Item`
|
||||||
|
where parent = %(name)s), 2)
|
||||||
|
where name = %(name)s """, {"name": po.name})
|
||||||
|
|
||||||
|
|
||||||
@@ -66,12 +66,6 @@ class SalesOrder(SellingController):
|
|||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
check_list.append(cstr(d.item_code))
|
check_list.append(cstr(d.item_code))
|
||||||
|
|
||||||
if (frappe.db.get_value("Item", d.item_code, "is_stock_item")==1 or
|
|
||||||
(self.has_product_bundle(d.item_code) and self.product_bundle_has_stock_item(d.item_code))) \
|
|
||||||
and not d.warehouse and not cint(d.delivered_by_supplier):
|
|
||||||
frappe.throw(_("Delivery warehouse required for stock item {0}").format(d.item_code),
|
|
||||||
WarehouseRequired)
|
|
||||||
|
|
||||||
# used for production plan
|
# used for production plan
|
||||||
d.transaction_date = self.transaction_date
|
d.transaction_date = self.transaction_date
|
||||||
|
|
||||||
@@ -116,14 +110,15 @@ class SalesOrder(SellingController):
|
|||||||
frappe.throw(_("Customer {0} does not belong to project {1}").format(self.customer, self.project_name))
|
frappe.throw(_("Customer {0} does not belong to project {1}").format(self.customer, self.project_name))
|
||||||
|
|
||||||
def validate_warehouse(self):
|
def validate_warehouse(self):
|
||||||
from erpnext.stock.utils import validate_warehouse_company
|
super(SalesOrder, self).validate_warehouse()
|
||||||
|
|
||||||
warehouses = list(set([d.warehouse for d in
|
for d in self.get("items"):
|
||||||
self.get("items") if d.warehouse]))
|
if (frappe.db.get_value("Item", d.item_code, "is_stock_item")==1 or
|
||||||
|
(self.has_product_bundle(d.item_code) and self.product_bundle_has_stock_item(d.item_code))) \
|
||||||
for w in warehouses:
|
and not d.warehouse and not cint(d.delivered_by_supplier):
|
||||||
validate_warehouse_company(w, self.company)
|
frappe.throw(_("Delivery warehouse required for stock item {0}").format(d.item_code),
|
||||||
|
WarehouseRequired)
|
||||||
|
|
||||||
def validate_with_previous_doc(self):
|
def validate_with_previous_doc(self):
|
||||||
super(SalesOrder, self).validate_with_previous_doc({
|
super(SalesOrder, self).validate_with_previous_doc({
|
||||||
"Quotation": {
|
"Quotation": {
|
||||||
@@ -236,13 +231,13 @@ class SalesOrder(SellingController):
|
|||||||
item_wh_list.append([item_code, warehouse])
|
item_wh_list.append([item_code, warehouse])
|
||||||
|
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if (not so_item_rows or d.name in so_item_rows):
|
if (not so_item_rows or d.name in so_item_rows) and not d.delivered_by_supplier:
|
||||||
_valid_for_reserve(d.item_code, d.warehouse)
|
|
||||||
|
|
||||||
if self.has_product_bundle(d.item_code):
|
if self.has_product_bundle(d.item_code):
|
||||||
for p in self.get("packed_items"):
|
for p in self.get("packed_items"):
|
||||||
if p.parent_detail_docname == d.name and p.parent_item == d.item_code:
|
if p.parent_detail_docname == d.name and p.parent_item == d.item_code:
|
||||||
_valid_for_reserve(p.item_code, p.warehouse)
|
_valid_for_reserve(p.item_code, p.warehouse)
|
||||||
|
else:
|
||||||
|
_valid_for_reserve(d.item_code, d.warehouse)
|
||||||
|
|
||||||
for item_code, warehouse in item_wh_list:
|
for item_code, warehouse in item_wh_list:
|
||||||
update_bin_qty(item_code, warehouse, {
|
update_bin_qty(item_code, warehouse, {
|
||||||
|
|||||||
@@ -355,10 +355,13 @@ class TestSalesOrder(unittest.TestCase):
|
|||||||
self.assertEquals(dn.items[0].item_code, dn_item.item_code)
|
self.assertEquals(dn.items[0].item_code, dn_item.item_code)
|
||||||
|
|
||||||
#test ordered_qty and reserved_qty
|
#test ordered_qty and reserved_qty
|
||||||
ordered_qty, reserved_qty = frappe.db.get_value("Bin",
|
bin = frappe.get_all("Bin", filters={"item_code": po_item.item_code, "warehouse": "_Test Warehouse - _TC"},
|
||||||
{"item_code": po_item.item_code, "warehouse": "_Test Warehouse - _TC"}, ["ordered_qty", "reserved_qty"])
|
fields=["ordered_qty", "reserved_qty"])
|
||||||
|
|
||||||
self.assertEquals(abs(flt(ordered_qty)), existing_ordered_qty + so_items[0]['qty'])
|
ordered_qty = bin[0].ordered_qty if bin else 0.0
|
||||||
|
reserved_qty = bin[0].reserved_qty if bin else 0.0
|
||||||
|
|
||||||
|
self.assertEquals(abs(flt(ordered_qty)), existing_ordered_qty)
|
||||||
self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty)
|
self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty)
|
||||||
|
|
||||||
reserved_qty = frappe.db.get_value("Bin",
|
reserved_qty = frappe.db.get_value("Bin",
|
||||||
@@ -384,8 +387,11 @@ class TestSalesOrder(unittest.TestCase):
|
|||||||
so.db_set('status', "Closed")
|
so.db_set('status', "Closed")
|
||||||
so.update_reserved_qty()
|
so.update_reserved_qty()
|
||||||
|
|
||||||
ordered_qty, reserved_qty = frappe.db.get_value("Bin",
|
bin = frappe.get_all("Bin", filters={"item_code": po_item.item_code, "warehouse": "_Test Warehouse - _TC"},
|
||||||
{"item_code": po_item.item_code, "warehouse": "_Test Warehouse - _TC"}, ["ordered_qty", "reserved_qty"])
|
fields=["ordered_qty", "reserved_qty"])
|
||||||
|
|
||||||
|
ordered_qty = bin[0].ordered_qty if bin else 0.0
|
||||||
|
reserved_qty = bin[0].reserved_qty if bin else 0.0
|
||||||
|
|
||||||
self.assertEquals(abs(flt(ordered_qty)), existing_ordered_qty)
|
self.assertEquals(abs(flt(ordered_qty)), existing_ordered_qty)
|
||||||
self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty)
|
self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty)
|
||||||
@@ -393,7 +399,7 @@ class TestSalesOrder(unittest.TestCase):
|
|||||||
reserved_qty = frappe.db.get_value("Bin",
|
reserved_qty = frappe.db.get_value("Bin",
|
||||||
{"item_code": dn_item.item_code, "warehouse": "_Test Warehouse - _TC"}, "reserved_qty")
|
{"item_code": dn_item.item_code, "warehouse": "_Test Warehouse - _TC"}, "reserved_qty")
|
||||||
|
|
||||||
self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty)
|
self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty_for_dn_item)
|
||||||
|
|
||||||
def test_reserved_qty_for_closing_so(self):
|
def test_reserved_qty_for_closing_so(self):
|
||||||
bin = frappe.get_all("Bin", filters={"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"},
|
bin = frappe.get_all("Bin", filters={"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"},
|
||||||
|
|||||||
@@ -170,6 +170,8 @@ class DeliveryNote(SellingController):
|
|||||||
chk_dupl_itm.append(f)
|
chk_dupl_itm.append(f)
|
||||||
|
|
||||||
def validate_warehouse(self):
|
def validate_warehouse(self):
|
||||||
|
super(DeliveryNote, self).validate_warehouse()
|
||||||
|
|
||||||
for d in self.get_item_list():
|
for d in self.get_item_list():
|
||||||
if frappe.db.get_value("Item", d['item_code'], "is_stock_item") == 1:
|
if frappe.db.get_value("Item", d['item_code'], "is_stock_item") == 1:
|
||||||
if not d['warehouse']:
|
if not d['warehouse']:
|
||||||
|
|||||||
@@ -76,10 +76,12 @@ def get_reserved_qty(item_code, warehouse):
|
|||||||
(
|
(
|
||||||
select qty from `tabSales Order Item`
|
select qty from `tabSales Order Item`
|
||||||
where name = dnpi.parent_detail_docname
|
where name = dnpi.parent_detail_docname
|
||||||
|
and (delivered_by_supplier is null or delivered_by_supplier = 0)
|
||||||
) as so_item_qty,
|
) as so_item_qty,
|
||||||
(
|
(
|
||||||
select ifnull(delivered_qty, 0) from `tabSales Order Item`
|
select ifnull(delivered_qty, 0) from `tabSales Order Item`
|
||||||
where name = dnpi.parent_detail_docname
|
where name = dnpi.parent_detail_docname
|
||||||
|
and (delivered_by_supplier is null or delivered_by_supplier = 0)
|
||||||
) as so_item_delivered_qty,
|
) as so_item_delivered_qty,
|
||||||
parent, name
|
parent, name
|
||||||
from
|
from
|
||||||
@@ -96,7 +98,8 @@ def get_reserved_qty(item_code, warehouse):
|
|||||||
(select qty as dnpi_qty, qty as so_item_qty,
|
(select qty as dnpi_qty, qty as so_item_qty,
|
||||||
ifnull(delivered_qty, 0) as so_item_delivered_qty, parent, name
|
ifnull(delivered_qty, 0) as so_item_delivered_qty, parent, name
|
||||||
from `tabSales Order Item` so_item
|
from `tabSales Order Item` so_item
|
||||||
where item_code = %s and warehouse = %s
|
where item_code = %s and warehouse = %s
|
||||||
|
and (so_item.delivered_by_supplier is null or so_item.delivered_by_supplier = 0)
|
||||||
and exists(select * from `tabSales Order` so
|
and exists(select * from `tabSales Order` so
|
||||||
where so.name = so_item.parent and so.docstatus = 1
|
where so.name = so_item.parent and so.docstatus = 1
|
||||||
and so.status not in ('Stopped','Closed')))
|
and so.status not in ('Stopped','Closed')))
|
||||||
@@ -122,7 +125,9 @@ def get_ordered_qty(item_code, warehouse):
|
|||||||
from `tabPurchase Order Item` po_item, `tabPurchase Order` po
|
from `tabPurchase Order Item` po_item, `tabPurchase Order` po
|
||||||
where po_item.item_code=%s and po_item.warehouse=%s
|
where po_item.item_code=%s and po_item.warehouse=%s
|
||||||
and po_item.qty > ifnull(po_item.received_qty, 0) and po_item.parent=po.name
|
and po_item.qty > ifnull(po_item.received_qty, 0) and po_item.parent=po.name
|
||||||
and po.status not in ('Stopped', 'Closed', 'Delivered') and po.docstatus=1""", (item_code, warehouse))
|
and po.status not in ('Stopped', 'Closed', 'Delivered') and po.docstatus=1
|
||||||
|
and (po_item.delivered_by_supplier is null or po_item.delivered_by_supplier = 0)
|
||||||
|
""", (item_code, warehouse))
|
||||||
|
|
||||||
return flt(ordered_qty[0][0]) if ordered_qty else 0
|
return flt(ordered_qty[0][0]) if ordered_qty else 0
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user