Merge branch 'develop'
This commit is contained in:
commit
5812fdb574
@ -1,2 +1,2 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
__version__ = '6.4.4'
|
__version__ = '6.4.5'
|
||||||
|
@ -210,6 +210,8 @@ def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
|
|
||||||
def get_account_currency(account):
|
def get_account_currency(account):
|
||||||
"""Helper function to get account currency"""
|
"""Helper function to get account currency"""
|
||||||
|
if not account:
|
||||||
|
return
|
||||||
def generator():
|
def generator():
|
||||||
account_currency, company = frappe.db.get_value("Account", account, ["account_currency", "company"])
|
account_currency, company = frappe.db.get_value("Account", account, ["account_currency", "company"])
|
||||||
if not account_currency:
|
if not account_currency:
|
||||||
|
@ -7,7 +7,6 @@ from frappe.utils import cstr, flt, fmt_money, formatdate
|
|||||||
from frappe import msgprint, _, scrub
|
from frappe import msgprint, _, scrub
|
||||||
from erpnext.controllers.accounts_controller import AccountsController
|
from erpnext.controllers.accounts_controller import AccountsController
|
||||||
from erpnext.accounts.utils import get_balance_on, get_account_currency
|
from erpnext.accounts.utils import get_balance_on, get_account_currency
|
||||||
from erpnext.accounts.party import get_party_account_currency
|
|
||||||
from erpnext.setup.utils import get_company_currency
|
from erpnext.setup.utils import get_company_currency
|
||||||
|
|
||||||
|
|
||||||
@ -278,9 +277,6 @@ class JournalEntry(AccountsController):
|
|||||||
if not self.multi_currency:
|
if not self.multi_currency:
|
||||||
frappe.throw(_("Please check Multi Currency option to allow accounts with other currency"))
|
frappe.throw(_("Please check Multi Currency option to allow accounts with other currency"))
|
||||||
|
|
||||||
if len(alternate_currency) > 1:
|
|
||||||
frappe.throw(_("Only one alternate currency can be used in a single Journal Entry"))
|
|
||||||
|
|
||||||
self.set_exchange_rate()
|
self.set_exchange_rate()
|
||||||
|
|
||||||
for d in self.get("accounts"):
|
for d in self.get("accounts"):
|
||||||
|
@ -207,8 +207,8 @@ class SalesInvoice(SellingController):
|
|||||||
def validate_time_logs_are_submitted(self):
|
def validate_time_logs_are_submitted(self):
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if d.time_log_batch:
|
if d.time_log_batch:
|
||||||
status = frappe.db.get_value("Time Log Batch", d.time_log_batch, "status")
|
docstatus = frappe.db.get_value("Time Log Batch", d.time_log_batch, "docstatus")
|
||||||
if status!="Submitted":
|
if docstatus!=1:
|
||||||
frappe.throw(_("Time Log Batch {0} must be 'Submitted'").format(d.time_log_batch))
|
frappe.throw(_("Time Log Batch {0} must be 'Submitted'").format(d.time_log_batch))
|
||||||
|
|
||||||
def set_pos_fields(self, for_validate=False):
|
def set_pos_fields(self, for_validate=False):
|
||||||
|
@ -1468,6 +1468,7 @@
|
|||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
"collapsible": 0,
|
"collapsible": 0,
|
||||||
|
"default": "Draft",
|
||||||
"fieldname": "status",
|
"fieldname": "status",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -1478,7 +1479,7 @@
|
|||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "status",
|
"oldfieldname": "status",
|
||||||
"oldfieldtype": "Select",
|
"oldfieldtype": "Select",
|
||||||
"options": "\nDraft\nSubmitted\nStopped\nCancelled",
|
"options": "\nDraft\nTo Receive and Bill\nTo Bill\nTo Receive\nCompleted\nStopped\nCancelled",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
@ -2032,7 +2033,7 @@
|
|||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2015-09-30 08:52:56.137185",
|
"modified": "2015-10-02 07:17:59.659036",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order",
|
"name": "Purchase Order",
|
||||||
|
@ -36,13 +36,7 @@ class PurchaseOrder(BuyingController):
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
super(PurchaseOrder, self).validate()
|
super(PurchaseOrder, self).validate()
|
||||||
|
|
||||||
if not self.status:
|
self.set_status()
|
||||||
self.status = "Draft"
|
|
||||||
|
|
||||||
from erpnext.controllers.status_updater import validate_status
|
|
||||||
validate_status(self.status, ["Draft", "Submitted", "Stopped",
|
|
||||||
"Cancelled"])
|
|
||||||
|
|
||||||
pc_obj = frappe.get_doc('Purchase Common')
|
pc_obj = frappe.get_doc('Purchase Common')
|
||||||
pc_obj.validate_for_items(self)
|
pc_obj.validate_for_items(self)
|
||||||
self.check_for_stopped_status(pc_obj)
|
self.check_for_stopped_status(pc_obj)
|
||||||
@ -160,12 +154,10 @@ class PurchaseOrder(BuyingController):
|
|||||||
|
|
||||||
def update_status(self, status):
|
def update_status(self, status):
|
||||||
self.check_modified_date()
|
self.check_modified_date()
|
||||||
frappe.db.set(self,'status',cstr(status))
|
self.db_set('status', status)
|
||||||
|
self.set_status(update=True)
|
||||||
self.update_requested_qty()
|
self.update_requested_qty()
|
||||||
self.update_ordered_qty()
|
self.update_ordered_qty()
|
||||||
|
|
||||||
msgprint(_("Status of {0} {1} is now {2}").format(self.doctype, self.name, status))
|
|
||||||
self.notify_update()
|
self.notify_update()
|
||||||
clear_doctype_notifications(self)
|
clear_doctype_notifications(self)
|
||||||
|
|
||||||
@ -183,8 +175,6 @@ class PurchaseOrder(BuyingController):
|
|||||||
|
|
||||||
purchase_controller.update_last_purchase_rate(self, is_submit = 1)
|
purchase_controller.update_last_purchase_rate(self, is_submit = 1)
|
||||||
|
|
||||||
frappe.db.set(self,'status','Submitted')
|
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
pc_obj = frappe.get_doc('Purchase Common')
|
pc_obj = frappe.get_doc('Purchase Common')
|
||||||
self.check_for_stopped_status(pc_obj)
|
self.check_for_stopped_status(pc_obj)
|
||||||
@ -238,7 +228,7 @@ def stop_or_unstop_purchase_orders(names, status):
|
|||||||
po.update_status("Stopped")
|
po.update_status("Stopped")
|
||||||
else:
|
else:
|
||||||
if po.status == "Stopped":
|
if po.status == "Stopped":
|
||||||
po.update_status("Submitted")
|
po.update_status("Draft")
|
||||||
|
|
||||||
frappe.local.message_log = []
|
frappe.local.message_log = []
|
||||||
|
|
||||||
|
@ -30,7 +30,19 @@ status_map = {
|
|||||||
],
|
],
|
||||||
"Sales Order": [
|
"Sales Order": [
|
||||||
["Draft", None],
|
["Draft", None],
|
||||||
["Submitted", "eval:self.docstatus==1"],
|
["To Deliver and Bill", "eval:self.per_delivered < 100 and self.per_billed < 100 and self.docstatus == 1"],
|
||||||
|
["To Bill", "eval:self.per_delivered == 100 and self.per_billed < 100 and self.docstatus == 1"],
|
||||||
|
["To Deliver", "eval:self.per_delivered < 100 and self.per_billed == 100 and self.docstatus == 1"],
|
||||||
|
["Completed", "eval:self.per_delivered == 100 and self.per_billed == 100 and self.docstatus == 1"],
|
||||||
|
["Stopped", "eval:self.status=='Stopped'"],
|
||||||
|
["Cancelled", "eval:self.docstatus==2"],
|
||||||
|
],
|
||||||
|
"Purchase Order": [
|
||||||
|
["Draft", None],
|
||||||
|
["To Receive and Bill", "eval:self.per_received < 100 and self.per_billed < 100 and self.docstatus == 1"],
|
||||||
|
["To Bill", "eval:self.per_received == 100 and self.per_billed < 100 and self.docstatus == 1"],
|
||||||
|
["To Receive", "eval:self.per_received < 100 and self.per_billed == 100 and self.docstatus == 1"],
|
||||||
|
["Completed", "eval:self.per_received == 100 and self.per_billed == 100 and self.docstatus == 1"],
|
||||||
["Stopped", "eval:self.status=='Stopped'"],
|
["Stopped", "eval:self.status=='Stopped'"],
|
||||||
["Cancelled", "eval:self.docstatus==2"],
|
["Cancelled", "eval:self.docstatus==2"],
|
||||||
],
|
],
|
||||||
@ -222,7 +234,9 @@ class StatusUpdater(Document):
|
|||||||
where name='%(name)s'""" % args)
|
where name='%(name)s'""" % args)
|
||||||
|
|
||||||
if args.get("set_modified"):
|
if args.get("set_modified"):
|
||||||
frappe.get_doc(args["target_parent_dt"], name).notify_update()
|
target = frappe.get_doc(args["target_parent_dt"], name)
|
||||||
|
target.set_status(update=True)
|
||||||
|
target.notify_update()
|
||||||
|
|
||||||
def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
|
def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
|
||||||
ref_fieldname = ref_dt.lower().replace(" ", "_")
|
ref_fieldname = ref_dt.lower().replace(" ", "_")
|
||||||
|
@ -35,6 +35,8 @@ def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_p
|
|||||||
key, parties = "customer", customers
|
key, parties = "customer", customers
|
||||||
elif suppliers:
|
elif suppliers:
|
||||||
key, parties = "supplier", suppliers
|
key, parties = "supplier", suppliers
|
||||||
|
else:
|
||||||
|
key, parties = "customer", []
|
||||||
|
|
||||||
filters.append((doctype, key, "in", parties))
|
filters.append((doctype, key, "in", parties))
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ blogs.
|
|||||||
"""
|
"""
|
||||||
app_icon = "icon-th"
|
app_icon = "icon-th"
|
||||||
app_color = "#e74c3c"
|
app_color = "#e74c3c"
|
||||||
app_version = "6.4.4"
|
app_version = "6.4.5"
|
||||||
github_link = "https://github.com/frappe/erpnext"
|
github_link = "https://github.com/frappe/erpnext"
|
||||||
|
|
||||||
error_report_email = "support@erpnext.com"
|
error_report_email = "support@erpnext.com"
|
||||||
@ -53,7 +53,7 @@ my_account_context = "erpnext.shopping_cart.utils.update_my_account_context"
|
|||||||
|
|
||||||
email_append_to = ["Job Applicant", "Opportunity", "Issue"]
|
email_append_to = ["Job Applicant", "Opportunity", "Issue"]
|
||||||
|
|
||||||
calendars = ["Task", "Production Order", "Time Log", "Leave Application", "Sales Order"]
|
calendars = ["Task", "Production Order", "Time Log", "Leave Application", "Sales Order", "Holiday List"]
|
||||||
|
|
||||||
website_generators = ["Item Group", "Item", "Sales Partner"]
|
website_generators = ["Item Group", "Item", "Sales Partner"]
|
||||||
|
|
||||||
|
@ -16,7 +16,8 @@ class HolidayList(Document):
|
|||||||
|
|
||||||
def get_weekly_off_dates(self):
|
def get_weekly_off_dates(self):
|
||||||
self.validate_values()
|
self.validate_values()
|
||||||
yr_start_date, yr_end_date = self.get_fy_start_end_dates()
|
self.validate_days()
|
||||||
|
yr_start_date, yr_end_date = get_fy_start_end_dates(self.fiscal_year)
|
||||||
date_list = self.get_weekly_off_date_list(yr_start_date, yr_end_date)
|
date_list = self.get_weekly_off_date_list(yr_start_date, yr_end_date)
|
||||||
last_idx = max([cint(d.idx) for d in self.get("holidays")] or [0,])
|
last_idx = max([cint(d.idx) for d in self.get("holidays")] or [0,])
|
||||||
for i, d in enumerate(date_list):
|
for i, d in enumerate(date_list):
|
||||||
@ -30,10 +31,11 @@ class HolidayList(Document):
|
|||||||
throw(_("Please select Fiscal Year"))
|
throw(_("Please select Fiscal Year"))
|
||||||
if not self.weekly_off:
|
if not self.weekly_off:
|
||||||
throw(_("Please select weekly off day"))
|
throw(_("Please select weekly off day"))
|
||||||
|
|
||||||
def get_fy_start_end_dates(self):
|
def validate_days(self):
|
||||||
return frappe.db.sql("""select year_start_date, year_end_date
|
for day in self.get("holidays"):
|
||||||
from `tabFiscal Year` where name=%s""", (self.fiscal_year,))[0]
|
if (self.weekly_off).upper() == (day.description).upper():
|
||||||
|
frappe.throw("Records alredy exist for mentioned weekly off")
|
||||||
|
|
||||||
def get_weekly_off_date_list(self, year_start_date, year_end_date):
|
def get_weekly_off_date_list(self, year_start_date, year_end_date):
|
||||||
from frappe.utils import getdate
|
from frappe.utils import getdate
|
||||||
@ -59,3 +61,39 @@ class HolidayList(Document):
|
|||||||
def update_default_holiday_list(self):
|
def update_default_holiday_list(self):
|
||||||
frappe.db.sql("""update `tabHoliday List` set is_default = 0
|
frappe.db.sql("""update `tabHoliday List` set is_default = 0
|
||||||
where ifnull(is_default, 0) = 1 and fiscal_year = %s""", (self.fiscal_year,))
|
where ifnull(is_default, 0) = 1 and fiscal_year = %s""", (self.fiscal_year,))
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_events(start, end, filters=None):
|
||||||
|
import json
|
||||||
|
"""Returns events for Gantt / Calendar view rendering.
|
||||||
|
|
||||||
|
:param start: Start date-time.
|
||||||
|
:param end: End date-time.
|
||||||
|
:param filters: Filters (JSON).
|
||||||
|
"""
|
||||||
|
from frappe.desk.calendar import get_event_conditions
|
||||||
|
conditions = get_event_conditions("Holiday List", filters)
|
||||||
|
|
||||||
|
fiscal_year = None
|
||||||
|
if filters:
|
||||||
|
fiscal_year = json.loads(filters).get("fiscal_year")
|
||||||
|
|
||||||
|
if not fiscal_year:
|
||||||
|
fiscal_year = frappe.db.get_value("Global Defaults", None, "current_fiscal_year")
|
||||||
|
|
||||||
|
yr_start_date, yr_end_date = get_fy_start_end_dates(fiscal_year)
|
||||||
|
|
||||||
|
data = frappe.db.sql("""select hl.name, hld.holiday_date, hld.description
|
||||||
|
from `tabHoliday List` hl, tabHoliday hld
|
||||||
|
where hld.parent = hl.name
|
||||||
|
and (ifnull(hld.holiday_date, "0000-00-00") != "0000-00-00"
|
||||||
|
and hld.holiday_date between %(start)s and %(end)s)
|
||||||
|
{conditions}""".format(conditions=conditions), {
|
||||||
|
"start": yr_start_date,
|
||||||
|
"end": yr_end_date
|
||||||
|
}, as_dict=True, update={"allDay": 1})
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_fy_start_end_dates(fiscal_year):
|
||||||
|
return frappe.db.get_value("Fiscal Year", fiscal_year, ["year_start_date", "year_end_date"])
|
21
erpnext/hr/doctype/holiday_list/holiday_list_calendar.js
Normal file
21
erpnext/hr/doctype/holiday_list/holiday_list_calendar.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
frappe.views.calendar["Holiday List"] = {
|
||||||
|
field_map: {
|
||||||
|
"start": "holiday_date",
|
||||||
|
"end": "holiday_date",
|
||||||
|
"id": "name",
|
||||||
|
"title": "description",
|
||||||
|
"allDay": "allDay"
|
||||||
|
},
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"fieldname": "fiscal_year",
|
||||||
|
"options": "Fiscal Year",
|
||||||
|
"label": __("Fiscal Year")
|
||||||
|
}
|
||||||
|
],
|
||||||
|
get_events_method: "erpnext.hr.doctype.holiday_list.holiday_list.get_events"
|
||||||
|
}
|
@ -213,4 +213,5 @@ erpnext.patches.v5_8.tax_rule
|
|||||||
erpnext.patches.v6_3.convert_applicable_territory
|
erpnext.patches.v6_3.convert_applicable_territory
|
||||||
erpnext.patches.v6_4.round_status_updater_percentages
|
erpnext.patches.v6_4.round_status_updater_percentages
|
||||||
erpnext.patches.v6_4.repost_gle_for_journal_entries_where_reference_name_missing
|
erpnext.patches.v6_4.repost_gle_for_journal_entries_where_reference_name_missing
|
||||||
erpnext.patches.v6_4.fix_journal_entries_due_to_reconciliation
|
erpnext.patches.v6_4.fix_journal_entries_due_to_reconciliation
|
||||||
|
erpnext.patches.v6_4.fix_status_in_sales_and_purchase_order
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
for doctype in ("Sales Order", "Purchase Order"):
|
||||||
|
for doc in frappe.get_all(doctype, filters={"docstatus": 1}):
|
||||||
|
doc = frappe.get_doc(doctype, doc.name)
|
||||||
|
doc.set_status(update=True)
|
@ -10,6 +10,7 @@ frappe.views.calendar["Time Log"] = {
|
|||||||
"allDay": "allDay"
|
"allDay": "allDay"
|
||||||
},
|
},
|
||||||
gantt: true,
|
gantt: true,
|
||||||
|
gantt_scale: "hours",
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
|
@ -34,7 +34,7 @@ class TimeLogBatch(Document):
|
|||||||
def validate_time_log_is_submitted(self, tl):
|
def validate_time_log_is_submitted(self, tl):
|
||||||
if tl.status == "Batched for Billing":
|
if tl.status == "Batched for Billing":
|
||||||
frappe.throw(_("Time Log {0} already billed").format(tl.name))
|
frappe.throw(_("Time Log {0} already billed").format(tl.name))
|
||||||
elif tl.status != "Submitted":
|
elif tl.docstatus != 1:
|
||||||
frappe.throw(_("Time Log {0} must be 'Submitted'").format(tl.name))
|
frappe.throw(_("Time Log {0} must be 'Submitted'").format(tl.name))
|
||||||
|
|
||||||
def set_status(self):
|
def set_status(self):
|
||||||
|
@ -212,7 +212,7 @@ def get_customer_outstanding(customer, company):
|
|||||||
from `tabSales Invoice Item`
|
from `tabSales Invoice Item`
|
||||||
where dn_detail = %s and docstatus = 1""", dn_item.name)[0][0]
|
where dn_detail = %s and docstatus = 1""", dn_item.name)[0][0]
|
||||||
|
|
||||||
if flt(dn_item.amount) > flt(si_amount):
|
if flt(dn_item.amount) > flt(si_amount) and dn_item.base_net_total:
|
||||||
outstanding_based_on_dn += ((flt(dn_item.amount) - flt(si_amount)) \
|
outstanding_based_on_dn += ((flt(dn_item.amount) - flt(si_amount)) \
|
||||||
/ dn_item.base_net_total) * dn_item.base_grand_total
|
/ dn_item.base_net_total) * dn_item.base_grand_total
|
||||||
|
|
||||||
|
@ -1977,7 +1977,7 @@
|
|||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "status",
|
"oldfieldname": "status",
|
||||||
"oldfieldtype": "Select",
|
"oldfieldtype": "Select",
|
||||||
"options": "\nDraft\nSubmitted\nStopped\nCancelled",
|
"options": "\nDraft\nTo Deliver and Bill\nTo Bill\nTo Deliver\nCompleted\nStopped\nCancelled",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
@ -2553,7 +2553,7 @@
|
|||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2015-09-30 08:52:52.211212",
|
"modified": "2015-10-02 07:17:43.178678",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Order",
|
"name": "Sales Order",
|
||||||
|
@ -20,6 +20,27 @@ form_grid_templates = {
|
|||||||
class WarehouseRequired(frappe.ValidationError): pass
|
class WarehouseRequired(frappe.ValidationError): pass
|
||||||
|
|
||||||
class SalesOrder(SellingController):
|
class SalesOrder(SellingController):
|
||||||
|
def validate(self):
|
||||||
|
super(SalesOrder, self).validate()
|
||||||
|
|
||||||
|
self.validate_order_type()
|
||||||
|
self.validate_delivery_date()
|
||||||
|
self.validate_mandatory()
|
||||||
|
self.validate_proj_cust()
|
||||||
|
self.validate_po()
|
||||||
|
self.validate_uom_is_integer("stock_uom", "qty")
|
||||||
|
self.validate_for_items()
|
||||||
|
self.validate_warehouse()
|
||||||
|
|
||||||
|
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
|
||||||
|
make_packing_list(self,'items')
|
||||||
|
|
||||||
|
self.validate_with_previous_doc()
|
||||||
|
self.set_status()
|
||||||
|
|
||||||
|
if not self.billing_status: self.billing_status = 'Not Billed'
|
||||||
|
if not self.delivery_status: self.delivery_status = 'Not Delivered'
|
||||||
|
|
||||||
def validate_mandatory(self):
|
def validate_mandatory(self):
|
||||||
# validate transaction date v/s delivery date
|
# validate transaction date v/s delivery date
|
||||||
if self.delivery_date:
|
if self.delivery_date:
|
||||||
@ -93,33 +114,6 @@ class SalesOrder(SellingController):
|
|||||||
if not res:
|
if not res:
|
||||||
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(self):
|
|
||||||
super(SalesOrder, self).validate()
|
|
||||||
|
|
||||||
self.validate_order_type()
|
|
||||||
self.validate_delivery_date()
|
|
||||||
self.validate_mandatory()
|
|
||||||
self.validate_proj_cust()
|
|
||||||
self.validate_po()
|
|
||||||
self.validate_uom_is_integer("stock_uom", "qty")
|
|
||||||
self.validate_for_items()
|
|
||||||
self.validate_warehouse()
|
|
||||||
|
|
||||||
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
|
|
||||||
make_packing_list(self,'items')
|
|
||||||
|
|
||||||
self.validate_with_previous_doc()
|
|
||||||
|
|
||||||
if not self.status:
|
|
||||||
self.status = "Draft"
|
|
||||||
|
|
||||||
from erpnext.controllers.status_updater import validate_status
|
|
||||||
validate_status(self.status, ["Draft", "Submitted", "Stopped",
|
|
||||||
"Cancelled"])
|
|
||||||
|
|
||||||
if not self.billing_status: self.billing_status = 'Not Billed'
|
|
||||||
if not self.delivery_status: self.delivery_status = 'Not Delivered'
|
|
||||||
|
|
||||||
def validate_warehouse(self):
|
def validate_warehouse(self):
|
||||||
from erpnext.stock.utils import validate_warehouse_company
|
from erpnext.stock.utils import validate_warehouse_company
|
||||||
|
|
||||||
@ -162,7 +156,6 @@ class SalesOrder(SellingController):
|
|||||||
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, self.base_grand_total, self)
|
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, self.base_grand_total, self)
|
||||||
|
|
||||||
self.update_prevdoc_status('submit')
|
self.update_prevdoc_status('submit')
|
||||||
frappe.db.set(self, 'status', 'Submitted')
|
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
# Cannot cancel stopped SO
|
# Cannot cancel stopped SO
|
||||||
@ -175,7 +168,7 @@ class SalesOrder(SellingController):
|
|||||||
self.update_prevdoc_status('cancel')
|
self.update_prevdoc_status('cancel')
|
||||||
|
|
||||||
frappe.db.set(self, 'status', 'Cancelled')
|
frappe.db.set(self, 'status', 'Cancelled')
|
||||||
|
|
||||||
def check_credit_limit(self):
|
def check_credit_limit(self):
|
||||||
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
||||||
check_credit_limit(self.customer, self.company)
|
check_credit_limit(self.customer, self.company)
|
||||||
@ -223,17 +216,16 @@ class SalesOrder(SellingController):
|
|||||||
|
|
||||||
def stop_sales_order(self):
|
def stop_sales_order(self):
|
||||||
self.check_modified_date()
|
self.check_modified_date()
|
||||||
frappe.db.set(self, 'status', 'Stopped')
|
self.db_set('status', 'Stopped')
|
||||||
self.update_reserved_qty()
|
self.update_reserved_qty()
|
||||||
frappe.msgprint(_("{0} {1} status is Stopped").format(self.doctype, self.name))
|
|
||||||
self.notify_update()
|
self.notify_update()
|
||||||
clear_doctype_notifications(self)
|
clear_doctype_notifications(self)
|
||||||
|
|
||||||
def unstop_sales_order(self):
|
def unstop_sales_order(self):
|
||||||
self.check_modified_date()
|
self.check_modified_date()
|
||||||
frappe.db.set(self, 'status', 'Submitted')
|
self.db_set('status', 'Draft')
|
||||||
|
self.set_status(update=True)
|
||||||
self.update_reserved_qty()
|
self.update_reserved_qty()
|
||||||
frappe.msgprint(_("{0} {1} status is Unstopped").format(self.doctype, self.name))
|
|
||||||
clear_doctype_notifications(self)
|
clear_doctype_notifications(self)
|
||||||
|
|
||||||
def update_reserved_qty(self, so_item_rows=None):
|
def update_reserved_qty(self, so_item_rows=None):
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
{
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
"apply_user_permissions": 1,
|
"apply_user_permissions": 1,
|
||||||
"creation": "2013-06-21 16:46:45",
|
"creation": "2013-06-21 16:46:45",
|
||||||
|
"disabled": 0,
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Report",
|
"doctype": "Report",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_standard": "Yes",
|
"is_standard": "Yes",
|
||||||
"modified": "2015-03-30 05:45:40.146567",
|
"modified": "2015-10-06 12:43:48.259027",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Pending SO Items For Purchase Request",
|
"name": "Pending SO Items For Purchase Request",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"query": "select \n so_item.item_code as \"Item Code:Link/Item:120\",\n so_item.item_name as \"Item Name::120\",\n so_item.description as \"Description::120\",\n so.`name` as \"S.O. No.:Link/Sales Order:120\",\n so.`transaction_date` as \"Date:Date:120\",\n mr.name as \"Material Request:Link/Material Request:120\",\n so.customer as \"Customer:Link/Customer:120\",\n so.territory as \"Terretory:Link/Territory:120\",\n sum(so_item.qty) as \"SO Qty:Float:100 \",\n sum(mr_item.qty) as \"Requested Qty:Float:100\",\n so.company as \"Company:Link/Company:\"\nfrom\n `tabSales Order` so, `tabSales Order Item` so_item, \n `tabMaterial Request` mr, `tabMaterial Request Item` mr_item\nwhere\n so_item.`parent` = so.`name` and mr_item.sales_order_no = so.name\n and mr_item.parent = mr.name \n and so.docstatus = 1 and so.status != \"Stopped\" \n and mr.docstatus = 1 and mr.status != \"Stopped\"\ngroup by so.name, so_item.item_code\norder by so.name desc, so_item.item_code asc",
|
"query": "select so_item.item_code as \"Item Code:Link/Item:120\",\n so_item.item_name as \"Item Name::120\",\n so_item.description as \"Description::120\",\n so.`name` as \"S.O. No.:Link/Sales Order:120\",\n so.`transaction_date` as \"Date:Date:120\",\n mr.name as \"Material Request:Link/Material Request:120\",\n so.customer as \"Customer:Link/Customer:120\",\n so.territory as \"Terretory:Link/Territory:120\",\n sum(so_item.qty) as \"SO Qty:Float:100 \",\n sum(mr_item.qty) as \"Requested Qty:Float:100\",\n sum(so_item.qty) - sum(mr_item.qty) as \"Pending Qty:Float:100 \", \n so.company as \"Company:Link/Company:\"\nfrom\n `tabSales Order` so, `tabSales Order Item` so_item, \n `tabMaterial Request` mr, `tabMaterial Request Item` mr_item\nwhere \n so_item.`parent` = so.`name` \n and mr_item.parent = mr.name\n and mr_item.sales_order_no = so.name\n and mr_item.item_code = so_item.item_code\n and so.docstatus = 1 and so.status != \"Stopped\" \n and mr.docstatus = 1 and mr.status != \"Stopped\"\ngroup by so.name, so_item.item_code\nhaving sum(so_item.qty) > sum(mr_item.qty)\norder by so.name desc, so_item.item_code asc",
|
||||||
"ref_doctype": "Sales Order",
|
"ref_doctype": "Sales Order",
|
||||||
"report_name": "Pending SO Items For Purchase Request",
|
"report_name": "Pending SO Items For Purchase Request",
|
||||||
"report_type": "Query Report"
|
"report_type": "Query Report"
|
||||||
|
@ -4,8 +4,9 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils.make_random import add_random_children, get_random
|
from frappe.utils.make_random import add_random_children
|
||||||
import frappe.utils
|
import frappe.utils
|
||||||
|
import random
|
||||||
|
|
||||||
def make_sample_data():
|
def make_sample_data():
|
||||||
"""Create a few opportunities, quotes, material requests, issues, todos, projects
|
"""Create a few opportunities, quotes, material requests, issues, todos, projects
|
||||||
@ -13,11 +14,13 @@ def make_sample_data():
|
|||||||
|
|
||||||
selling_items = frappe.get_all("Item", filters = {"is_sales_item": 1})
|
selling_items = frappe.get_all("Item", filters = {"is_sales_item": 1})
|
||||||
buying_items = frappe.get_all("Item", filters = {"is_purchase_item": 1})
|
buying_items = frappe.get_all("Item", filters = {"is_purchase_item": 1})
|
||||||
|
customers = frappe.get_all("Customer")
|
||||||
if selling_items:
|
|
||||||
|
if selling_items and customers:
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
make_opportunity(selling_items)
|
customer = random.choice(customers).name
|
||||||
make_quote(selling_items)
|
make_opportunity(selling_items, customer)
|
||||||
|
make_quote(selling_items, customer)
|
||||||
|
|
||||||
make_projects()
|
make_projects()
|
||||||
|
|
||||||
@ -26,11 +29,11 @@ def make_sample_data():
|
|||||||
|
|
||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
|
|
||||||
def make_opportunity(selling_items):
|
def make_opportunity(selling_items, customer):
|
||||||
b = frappe.get_doc({
|
b = frappe.get_doc({
|
||||||
"doctype": "Opportunity",
|
"doctype": "Opportunity",
|
||||||
"enquiry_from": "Customer",
|
"enquiry_from": "Customer",
|
||||||
"customer": get_random("Customer"),
|
"customer": customer,
|
||||||
"enquiry_type": "Sales",
|
"enquiry_type": "Sales",
|
||||||
"with_items": 1
|
"with_items": 1
|
||||||
})
|
})
|
||||||
@ -44,11 +47,11 @@ def make_opportunity(selling_items):
|
|||||||
|
|
||||||
b.add_comment("This is a dummy record")
|
b.add_comment("This is a dummy record")
|
||||||
|
|
||||||
def make_quote(selling_items):
|
def make_quote(selling_items, customer):
|
||||||
qtn = frappe.get_doc({
|
qtn = frappe.get_doc({
|
||||||
"doctype": "Quotation",
|
"doctype": "Quotation",
|
||||||
"quotation_to": "Customer",
|
"quotation_to": "Customer",
|
||||||
"customer": get_random("Customer"),
|
"customer": customer,
|
||||||
"order_type": "Sales"
|
"order_type": "Sales"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
|
||||||
|
|
||||||
def get_notification_config():
|
def get_notification_config():
|
||||||
return { "for_doctype":
|
return { "for_doctype":
|
||||||
@ -15,7 +14,11 @@ def get_notification_config():
|
|||||||
"Contact": {"status": "Open"},
|
"Contact": {"status": "Open"},
|
||||||
"Opportunity": {"status": "Open"},
|
"Opportunity": {"status": "Open"},
|
||||||
"Quotation": {"docstatus": 0},
|
"Quotation": {"docstatus": 0},
|
||||||
"Sales Order": { "per_billed": ("<", 100), "status": ("!=", "Stopped"), "docstatus": ("<", 2) },
|
"Sales Order": {
|
||||||
|
"status": ("!=", "Stopped"),
|
||||||
|
"status": ("!=", "Completed"),
|
||||||
|
"docstatus": ("<", 2)
|
||||||
|
},
|
||||||
"Journal Entry": {"docstatus": 0},
|
"Journal Entry": {"docstatus": 0},
|
||||||
"Sales Invoice": { "outstanding_amount": (">", 0), "docstatus": ("<", 2) },
|
"Sales Invoice": { "outstanding_amount": (">", 0), "docstatus": ("<", 2) },
|
||||||
"Purchase Invoice": {"docstatus": 0},
|
"Purchase Invoice": {"docstatus": 0},
|
||||||
@ -26,7 +29,11 @@ def get_notification_config():
|
|||||||
"Delivery Note": {"docstatus": 0},
|
"Delivery Note": {"docstatus": 0},
|
||||||
"Stock Entry": {"docstatus": 0},
|
"Stock Entry": {"docstatus": 0},
|
||||||
"Material Request": {"docstatus": 0},
|
"Material Request": {"docstatus": 0},
|
||||||
"Purchase Order": { "per_billed": ("<", 100), "status": ("!=", "Stopped"), "docstatus": ("<", 2) },
|
"Purchase Order": {
|
||||||
|
"status": ("!=", "Completed"),
|
||||||
|
"status": ("!=", "Stopped"),
|
||||||
|
"docstatus": ("<", 2)
|
||||||
|
},
|
||||||
"Production Order": { "status": "In Process" },
|
"Production Order": { "status": "In Process" },
|
||||||
"BOM": {"docstatus": 0},
|
"BOM": {"docstatus": 0},
|
||||||
"Timesheet": {"docstatus": 0},
|
"Timesheet": {"docstatus": 0},
|
||||||
|
@ -346,8 +346,7 @@ def get_conversion_factor(item_code, uom):
|
|||||||
variant_of = frappe.db.get_value("Item", item_code, "variant_of")
|
variant_of = frappe.db.get_value("Item", item_code, "variant_of")
|
||||||
filters = {"parent": item_code, "uom": uom}
|
filters = {"parent": item_code, "uom": uom}
|
||||||
if variant_of:
|
if variant_of:
|
||||||
filters = {"parent": ("in", (item_code, variant_of))}
|
filters["parent"] = ("in", (item_code, variant_of))
|
||||||
|
|
||||||
return {"conversion_factor": frappe.db.get_value("UOM Conversion Detail",
|
return {"conversion_factor": frappe.db.get_value("UOM Conversion Detail",
|
||||||
filters, "conversion_factor")}
|
filters, "conversion_factor")}
|
||||||
|
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
{
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
"apply_user_permissions": 1,
|
"apply_user_permissions": 1,
|
||||||
"creation": "2013-02-22 18:01:55",
|
"creation": "2013-02-22 18:01:55",
|
||||||
|
"disabled": 0,
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Report",
|
"doctype": "Report",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_standard": "Yes",
|
"is_standard": "Yes",
|
||||||
"modified": "2015-06-10 15:52:49.492144",
|
"modified": "2015-10-06 12:43:37.547654",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Ordered Items To Be Delivered",
|
"name": "Ordered Items To Be Delivered",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project_name` as \"Project\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.qty as \"Qty:Float:140\",\n `tabSales Order Item`.delivered_qty as \"Delivered Qty:Float:140\",\n (`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0)) as \"Qty to Deliver:Float:140\",\n `tabSales Order Item`.base_rate as \"Rate:Float:140\",\n `tabSales Order Item`.base_amount as \"Amount:Float:140\",\n ((`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0))*`tabSales Order Item`.base_rate) as \"Amount to Deliver:Float:140\",\n `tabBin`.actual_qty as \"Available Qty:Float:120\",\n `tabBin`.projected_qty as \"Projected Qty:Float:120\",\n `tabSales Order`.`delivery_date` as \"Expected Delivery Date:Date:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order Item`.item_group as \"Item Group:Link/Item Group:120\",\n `tabSales Order Item`.warehouse as \"Warehouse:Link/Warehouse:200\"\nfrom\n `tabSales Order`, `tabSales Order Item`, `tabBin`\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status != \"Stopped\"\n and ifnull(`tabSales Order Item`.delivered_qty,0) < ifnull(`tabSales Order Item`.qty,0)\n and `tabBin`.item_code = `tabSales Order Item`.item_code\n and `tabBin`.warehouse = `tabSales Order Item`.warehouse\norder by `tabSales Order`.transaction_date asc",
|
"query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project_name` as \"Project\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.qty as \"Qty:Float:140\",\n `tabSales Order Item`.delivered_qty as \"Delivered Qty:Float:140\",\n (`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0)) as \"Qty to Deliver:Float:140\",\n `tabSales Order Item`.base_rate as \"Rate:Float:140\",\n `tabSales Order Item`.base_amount as \"Amount:Float:140\",\n ((`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0))*`tabSales Order Item`.base_rate) as \"Amount to Deliver:Float:140\",\n `tabBin`.actual_qty as \"Available Qty:Float:120\",\n `tabBin`.projected_qty as \"Projected Qty:Float:120\",\n `tabSales Order`.`delivery_date` as \"Expected Delivery Date:Date:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order Item`.item_group as \"Item Group:Link/Item Group:120\",\n `tabSales Order Item`.warehouse as \"Warehouse:Link/Warehouse:200\"\nfrom\n `tabSales Order` JOIN `tabSales Order Item` \n LEFT JOIN `tabBin` ON (`tabBin`.item_code = `tabSales Order Item`.item_code\n and `tabBin`.warehouse = `tabSales Order Item`.warehouse)\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status != \"Stopped\"\n and ifnull(`tabSales Order Item`.delivered_qty,0) < ifnull(`tabSales Order Item`.qty,0)\norder by `tabSales Order`.transaction_date asc",
|
||||||
"ref_doctype": "Delivery Note",
|
"ref_doctype": "Delivery Note",
|
||||||
"report_name": "Ordered Items To Be Delivered",
|
"report_name": "Ordered Items To Be Delivered",
|
||||||
"report_type": "Query Report"
|
"report_type": "Query Report"
|
||||||
|
@ -93,14 +93,14 @@ def get_item_warehouse_map(filters):
|
|||||||
qty_dict.opening_qty += qty_diff
|
qty_dict.opening_qty += qty_diff
|
||||||
qty_dict.opening_val += value_diff
|
qty_dict.opening_val += value_diff
|
||||||
elif d.posting_date >= getdate(filters["from_date"]) and d.posting_date <= getdate(filters["to_date"]):
|
elif d.posting_date >= getdate(filters["from_date"]) and d.posting_date <= getdate(filters["to_date"]):
|
||||||
qty_dict.val_rate = d.valuation_rate
|
|
||||||
if qty_diff > 0:
|
if qty_diff > 0:
|
||||||
qty_dict.in_qty += qty_diff
|
qty_dict.in_qty += qty_diff
|
||||||
qty_dict.in_val += value_diff
|
qty_dict.in_val += value_diff
|
||||||
else:
|
else:
|
||||||
qty_dict.out_qty += abs(qty_diff)
|
qty_dict.out_qty += abs(qty_diff)
|
||||||
qty_dict.out_val += abs(value_diff)
|
qty_dict.out_val += abs(value_diff)
|
||||||
|
|
||||||
|
qty_dict.val_rate = d.valuation_rate
|
||||||
qty_dict.bal_qty += qty_diff
|
qty_dict.bal_qty += qty_diff
|
||||||
qty_dict.bal_val += value_diff
|
qty_dict.bal_val += value_diff
|
||||||
|
|
||||||
|
2
setup.py
2
setup.py
@ -1,6 +1,6 @@
|
|||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
version = "6.4.4"
|
version = "6.4.5"
|
||||||
|
|
||||||
with open("requirements.txt", "r") as f:
|
with open("requirements.txt", "r") as f:
|
||||||
install_requires = f.readlines()
|
install_requires = f.readlines()
|
||||||
|
Loading…
Reference in New Issue
Block a user