Merge branch 'master' into staging-fixes
This commit is contained in:
commit
e8c2fdfb8c
@ -5,7 +5,7 @@ import frappe
|
|||||||
from erpnext.hooks import regional_overrides
|
from erpnext.hooks import regional_overrides
|
||||||
from frappe.utils import getdate
|
from frappe.utils import getdate
|
||||||
|
|
||||||
__version__ = '10.1.74'
|
__version__ = '10.1.76'
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
'''Get default company for user'''
|
'''Get default company for user'''
|
||||||
|
@ -91,6 +91,7 @@ class PurchaseOrder(BuyingController):
|
|||||||
self.party_account_currency = get_party_account_currency("Supplier", self.supplier, self.company)
|
self.party_account_currency = get_party_account_currency("Supplier", self.supplier, self.company)
|
||||||
|
|
||||||
def validate_minimum_order_qty(self):
|
def validate_minimum_order_qty(self):
|
||||||
|
if not self.get("items"): return
|
||||||
items = list(set([d.item_code for d in self.get("items")]))
|
items = list(set([d.item_code for d in self.get("items")]))
|
||||||
|
|
||||||
itemwise_min_order_qty = frappe._dict(frappe.db.sql("""select name, min_order_qty
|
itemwise_min_order_qty = frappe._dict(frappe.db.sql("""select name, min_order_qty
|
||||||
|
@ -678,7 +678,7 @@ class BuyingController(StockController):
|
|||||||
frappe.db.sql("delete from `tabSerial No` where purchase_document_no=%s", self.name)
|
frappe.db.sql("delete from `tabSerial No` where purchase_document_no=%s", self.name)
|
||||||
|
|
||||||
def validate_schedule_date(self):
|
def validate_schedule_date(self):
|
||||||
if not self.schedule_date:
|
if not self.schedule_date and self.get("items"):
|
||||||
self.schedule_date = min([d.schedule_date for d in self.get("items")])
|
self.schedule_date = min([d.schedule_date for d in self.get("items")])
|
||||||
|
|
||||||
if self.schedule_date:
|
if self.schedule_date:
|
||||||
|
@ -62,7 +62,7 @@ class Employee(NestedSet):
|
|||||||
def validate_user_details(self):
|
def validate_user_details(self):
|
||||||
data = frappe.db.get_value('User',
|
data = frappe.db.get_value('User',
|
||||||
self.user_id, ['enabled', 'user_image'], as_dict=1)
|
self.user_id, ['enabled', 'user_image'], as_dict=1)
|
||||||
|
if data.get("user_image"):
|
||||||
self.image = data.get("user_image")
|
self.image = data.get("user_image")
|
||||||
self.validate_for_enabled_user_id(data.get("enabled", 0))
|
self.validate_for_enabled_user_id(data.get("enabled", 0))
|
||||||
self.validate_duplicate_user_id()
|
self.validate_duplicate_user_id()
|
||||||
|
@ -258,13 +258,13 @@ class Project(Document):
|
|||||||
self.total_purchase_cost = total_purchase_cost and total_purchase_cost[0][0] or 0
|
self.total_purchase_cost = total_purchase_cost and total_purchase_cost[0][0] or 0
|
||||||
|
|
||||||
def update_sales_amount(self):
|
def update_sales_amount(self):
|
||||||
total_sales_amount = frappe.db.sql("""select sum(base_grand_total)
|
total_sales_amount = frappe.db.sql("""select sum(base_net_total)
|
||||||
from `tabSales Order` where project = %s and docstatus=1""", self.name)
|
from `tabSales Order` where project = %s and docstatus=1""", self.name)
|
||||||
|
|
||||||
self.total_sales_amount = total_sales_amount and total_sales_amount[0][0] or 0
|
self.total_sales_amount = total_sales_amount and total_sales_amount[0][0] or 0
|
||||||
|
|
||||||
def update_billed_amount(self):
|
def update_billed_amount(self):
|
||||||
total_billed_amount = frappe.db.sql("""select sum(base_grand_total)
|
total_billed_amount = frappe.db.sql("""select sum(base_net_total)
|
||||||
from `tabSales Invoice` where project = %s and docstatus=1""", self.name)
|
from `tabSales Invoice` where project = %s and docstatus=1""", self.name)
|
||||||
|
|
||||||
self.total_billed_amount = total_billed_amount and total_billed_amount[0][0] or 0
|
self.total_billed_amount = total_billed_amount and total_billed_amount[0][0] or 0
|
||||||
|
@ -97,6 +97,9 @@ erpnext.setup.slides_settings = [
|
|||||||
if (!this.values.company_abbr) {
|
if (!this.values.company_abbr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (this.values.company_abbr.length > 5) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
Selling management module. Includes forms for capturing / managing the sales process.
|
Selling management module. Includes forms for capturing / managing the sales process:
|
||||||
|
|
||||||
|
- Customer
|
||||||
|
- Campaign
|
||||||
|
- Quotation
|
||||||
|
- Sales Order
|
||||||
|
|
||||||
|
Moved to CRM Module:
|
||||||
|
|
||||||
- Lead
|
- Lead
|
||||||
- Opportunity
|
- Opportunity
|
||||||
- Quotation
|
|
||||||
- Sales Order
|
|
@ -871,10 +871,12 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
@ -993,6 +995,7 @@
|
|||||||
"label": "Net Rate",
|
"label": "Net Rate",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
|
"options": "currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
@ -1910,7 +1913,7 @@
|
|||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"menu_index": 0,
|
"menu_index": 0,
|
||||||
"modified": "2018-08-22 16:15:52.750381",
|
"modified": "2018-12-12 05:52:46.135944",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Quotation Item",
|
"name": "Quotation Item",
|
||||||
|
@ -623,7 +623,7 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
|
|||||||
def update_item(source, target, source_parent):
|
def update_item(source, target, source_parent):
|
||||||
target.amount = flt(source.amount) - flt(source.billed_amt)
|
target.amount = flt(source.amount) - flt(source.billed_amt)
|
||||||
target.base_amount = target.amount * flt(source_parent.conversion_rate)
|
target.base_amount = target.amount * flt(source_parent.conversion_rate)
|
||||||
target.qty = target.amount / flt(source.rate) if (source.rate and source.billed_amt) else source.qty
|
target.qty = target.amount / flt(source.rate) if (source.rate and source.billed_amt) else source.qty - source.returned_qty
|
||||||
|
|
||||||
if source_parent.project:
|
if source_parent.project:
|
||||||
target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center")
|
target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center")
|
||||||
|
@ -391,8 +391,24 @@ def get_invoiced_qty_map(delivery_note):
|
|||||||
|
|
||||||
return invoiced_qty_map
|
return invoiced_qty_map
|
||||||
|
|
||||||
|
def get_returned_qty_map(sales_orders):
|
||||||
|
"""returns a map: {so_detail: returned_qty}"""
|
||||||
|
returned_qty_map = {}
|
||||||
|
|
||||||
|
for name, returned_qty in frappe.get_all('Sales Order Item', fields = ["name", "returned_qty"],
|
||||||
|
filters = {'parent': ('in', sales_orders), 'docstatus': 1}, as_list=1):
|
||||||
|
if not returned_qty_map.get(name):
|
||||||
|
returned_qty_map[name] = 0
|
||||||
|
returned_qty_map[name] += returned_qty
|
||||||
|
|
||||||
|
return returned_qty_map
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_sales_invoice(source_name, target_doc=None):
|
def make_sales_invoice(source_name, target_doc=None):
|
||||||
|
doc = frappe.get_doc('Delivery Note', source_name)
|
||||||
|
sales_orders = [d.against_sales_order for d in doc.items]
|
||||||
|
returned_qty_map = get_returned_qty_map(sales_orders)
|
||||||
|
|
||||||
invoiced_qty_map = get_invoiced_qty_map(source_name)
|
invoiced_qty_map = get_invoiced_qty_map(source_name)
|
||||||
|
|
||||||
def set_missing_values(source, target):
|
def set_missing_values(source, target):
|
||||||
@ -412,7 +428,9 @@ def make_sales_invoice(source_name, target_doc=None):
|
|||||||
target.update(get_fetch_values("Sales Invoice", 'company_address', target.company_address))
|
target.update(get_fetch_values("Sales Invoice", 'company_address', target.company_address))
|
||||||
|
|
||||||
def update_item(source_doc, target_doc, source_parent):
|
def update_item(source_doc, target_doc, source_parent):
|
||||||
target_doc.qty = source_doc.qty - invoiced_qty_map.get(source_doc.name, 0)
|
target_doc.qty = (source_doc.qty -
|
||||||
|
invoiced_qty_map.get(source_doc.name, 0) - returned_qty_map.get(source_doc.so_detail, 0))
|
||||||
|
|
||||||
if source_doc.serial_no and source_parent.per_billed > 0:
|
if source_doc.serial_no and source_parent.per_billed > 0:
|
||||||
target_doc.serial_no = get_delivery_note_serial_no(source_doc.item_code,
|
target_doc.serial_no = get_delivery_note_serial_no(source_doc.item_code,
|
||||||
target_doc.qty, source_parent.name)
|
target_doc.qty, source_parent.name)
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
frappe.listview_settings['Delivery Note'] = {
|
frappe.listview_settings['Delivery Note'] = {
|
||||||
add_fields: ["grand_total", "is_return", "per_billed", "status", "currency"],
|
add_fields: ["customer", "customer_name", "base_grand_total", "per_installed", "per_billed",
|
||||||
get_indicator: function (doc) {
|
"transporter_name", "grand_total", "is_return", "status", "currency"],
|
||||||
if (cint(doc.is_return) == 1) {
|
get_indicator: function(doc) {
|
||||||
|
if(cint(doc.is_return)==1) {
|
||||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||||
} else if (doc.status === "Closed") {
|
} else if (doc.status === "Closed") {
|
||||||
return [__("Closed"), "green", "status,=,Closed"];
|
return [__("Closed"), "green", "status,=,Closed"];
|
||||||
|
@ -637,6 +637,24 @@ class TestDeliveryNote(unittest.TestCase):
|
|||||||
|
|
||||||
set_perpetual_inventory(0, company)
|
set_perpetual_inventory(0, company)
|
||||||
|
|
||||||
|
def test_make_sales_invoice_from_dn_for_returned_qty(self):
|
||||||
|
from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
|
||||||
|
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
|
||||||
|
|
||||||
|
so = make_sales_order(qty=2)
|
||||||
|
so.submit()
|
||||||
|
|
||||||
|
dn = make_delivery_note(so.name)
|
||||||
|
dn.submit()
|
||||||
|
|
||||||
|
dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-1, do_not_submit=True)
|
||||||
|
dn1.items[0].against_sales_order = so.name
|
||||||
|
dn1.items[0].so_detail = so.items[0].name
|
||||||
|
dn1.submit()
|
||||||
|
|
||||||
|
si = make_sales_invoice(dn.name)
|
||||||
|
self.assertEquals(si.items[0].qty, 1)
|
||||||
|
|
||||||
def create_delivery_note(**args):
|
def create_delivery_note(**args):
|
||||||
dn = frappe.new_doc("Delivery Note")
|
dn = frappe.new_doc("Delivery Note")
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
frappe.listview_settings['Purchase Receipt'] = {
|
frappe.listview_settings['Purchase Receipt'] = {
|
||||||
add_fields: ["is_return", "grand_total", "status", "per_billed"],
|
add_fields: ["supplier", "supplier_name", "base_grand_total", "is_subcontracted",
|
||||||
get_indicator: function (doc) {
|
"transporter_name", "is_return", "status", "per_billed", "currency"],
|
||||||
if (cint(doc.is_return) == 1) {
|
get_indicator: function(doc) {
|
||||||
|
if(cint(doc.is_return)==1) {
|
||||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||||
} else if (doc.status === "Closed") {
|
} else if (doc.status === "Closed") {
|
||||||
return [__("Closed"), "green", "status,=,Closed"];
|
return [__("Closed"), "green", "status,=,Closed"];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user