Merge branch 'staging' into develop
This commit is contained in:
commit
4d1a9b10ed
11
.travis.yml
11
.travis.yml
@ -33,17 +33,16 @@ before_script:
|
||||
- cd ~/frappe-bench
|
||||
- bench get-app erpnext $TRAVIS_BUILD_DIR
|
||||
- bench use test_site
|
||||
- bench reinstall --mariadb-root-username root --mariadb-root-password travis --yes
|
||||
- bench build
|
||||
- bench scheduler disable
|
||||
- sed -i 's/9000/9001/g' sites/common_site_config.json
|
||||
- bench start &
|
||||
- sleep 10
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: test
|
||||
script:
|
||||
- bench reinstall --mariadb-root-username root --mariadb-root-password travis --yes
|
||||
- bench scheduler disable
|
||||
- sed -i 's/9000/9001/g' sites/common_site_config.json
|
||||
- bench start &
|
||||
- sleep 10
|
||||
- set -e
|
||||
- bench run-tests --app erpnext --coverage
|
||||
after_script:
|
||||
|
@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '10.1.77'
|
||||
__version__ = '10.1.78'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
@ -250,10 +250,12 @@ def get_serial_no_data(pos_profile, company):
|
||||
|
||||
cond = "1=1"
|
||||
if pos_profile.get('update_stock') and pos_profile.get('warehouse'):
|
||||
cond = "warehouse = '{0}'".format(pos_profile.get('warehouse'))
|
||||
cond = "warehouse = %(warehouse)s"
|
||||
|
||||
serial_nos = frappe.db.sql("""select name, warehouse, item_code from `tabSerial No` where {0}
|
||||
and company = %(company)s """.format(cond), {'company': company}, as_dict=1)
|
||||
serial_nos = frappe.db.sql("""select name, warehouse, item_code
|
||||
from `tabSerial No` where {0} and company = %(company)s """.format(cond),{
|
||||
'company': company, 'warehouse': frappe.db.escape(pos_profile.get('warehouse'))
|
||||
}, as_dict=1)
|
||||
|
||||
itemwise_serial_no = {}
|
||||
for sn in serial_nos:
|
||||
|
@ -1135,18 +1135,15 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
},
|
||||
|
||||
apply_category: function() {
|
||||
frappe.db.get_value("Item Group", {lft: 1, is_group: 1}, "name", (r) => {
|
||||
category = this.selected_item_group || r.name;
|
||||
|
||||
if(category == r.name) {
|
||||
return this.item_data
|
||||
} else {
|
||||
return this.item_data.filter(function(element, index, array){
|
||||
return element.item_group == category;
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
var me = this;
|
||||
category = this.selected_item_group || "All Item Groups";
|
||||
if(category == 'All Item Groups') {
|
||||
return this.item_data
|
||||
} else {
|
||||
return this.item_data.filter(function(element, index, array){
|
||||
return element.item_group == category;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
bind_items_event: function() {
|
||||
|
@ -190,7 +190,7 @@ class ReceivablePayableReport(object):
|
||||
dn_details = get_dn_details(args.get("party_type"), voucher_nos)
|
||||
self.voucher_details = get_voucher_details(args.get("party_type"), voucher_nos, dn_details)
|
||||
|
||||
if self.filters.based_on_payment_terms:
|
||||
if self.filters.based_on_payment_terms and gl_entries_data:
|
||||
self.payment_term_map = self.get_payment_term_detail(voucher_nos)
|
||||
|
||||
for gle in gl_entries_data:
|
||||
|
@ -180,7 +180,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
def get_voucherwise_data(self, party_naming_by, args):
|
||||
voucherwise_data = ReceivablePayableReport(self.filters).run(args)[1]
|
||||
|
||||
cols = ["posting_date", "party"]
|
||||
cols = ["posting_date", "party", "customer-contact"]
|
||||
|
||||
if party_naming_by == "Naming Series":
|
||||
cols += ["party_name"]
|
||||
|
@ -14,6 +14,7 @@ from erpnext.stock import get_warehouse_account_map
|
||||
|
||||
class QualityInspectionRequiredError(frappe.ValidationError): pass
|
||||
class QualityInspectionRejectedError(frappe.ValidationError): pass
|
||||
class QualityInspectionNotSubmittedError(frappe.ValidationError): pass
|
||||
|
||||
class StockController(AccountsController):
|
||||
def validate(self):
|
||||
@ -338,18 +339,20 @@ class StockController(AccountsController):
|
||||
qa_required = True
|
||||
elif self.doctype == "Stock Entry" and not d.quality_inspection and d.t_warehouse:
|
||||
qa_required = True
|
||||
if self.docstatus == 1 and d.quality_inspection:
|
||||
qa_doc = frappe.get_doc("Quality Inspection", d.quality_inspection)
|
||||
if qa_doc.docstatus == 0:
|
||||
link = frappe.utils.get_link_to_form('Quality Inspection', d.quality_inspection)
|
||||
frappe.throw(_("Quality Inspection: {0} is not submitted for the item: {1} in row {2}").format(link, d.item_code, d.idx), QualityInspectionNotSubmittedError)
|
||||
|
||||
if qa_required:
|
||||
qa_failed = any([r.status=="Rejected" for r in qa_doc.readings])
|
||||
if qa_failed:
|
||||
frappe.throw(_("Row {0}: Quality Inspection rejected for item {1}")
|
||||
.format(d.idx, d.item_code), QualityInspectionRejectedError)
|
||||
elif qa_required :
|
||||
frappe.msgprint(_("Quality Inspection required for Item {0}").format(d.item_code))
|
||||
if self.docstatus==1:
|
||||
raise QualityInspectionRequiredError
|
||||
elif self.docstatus == 1:
|
||||
if d.quality_inspection:
|
||||
qa_doc = frappe.get_doc("Quality Inspection", d.quality_inspection)
|
||||
qa_failed = any([r.status=="Rejected" for r in qa_doc.readings])
|
||||
if qa_failed:
|
||||
frappe.throw(_("Row {0}: Quality Inspection rejected for item {1}")
|
||||
.format(d.idx, d.item_code), QualityInspectionRejectedError)
|
||||
|
||||
|
||||
def update_blanket_order(self):
|
||||
@ -428,4 +431,4 @@ def get_voucherwise_gl_entries(future_stock_vouchers, posting_date):
|
||||
tuple([posting_date] + [d[1] for d in future_stock_vouchers]), as_dict=1):
|
||||
gl_entries.setdefault((d.voucher_type, d.voucher_no), []).append(d)
|
||||
|
||||
return gl_entries
|
||||
return gl_entries
|
||||
|
@ -12,7 +12,7 @@ app_license = "GNU General Public License (v3)"
|
||||
source_link = "https://github.com/frappe/erpnext"
|
||||
|
||||
develop_version = '12.x.x-develop'
|
||||
staging_version = '11.0.3-beta.34'
|
||||
staging_version = '11.0.3-beta.35'
|
||||
|
||||
error_report_email = "support@erpnext.com"
|
||||
|
||||
@ -232,12 +232,16 @@ doc_events = {
|
||||
}
|
||||
|
||||
scheduler_events = {
|
||||
"all": [
|
||||
"erpnext.projects.doctype.project.project.project_status_update_reminder"
|
||||
],
|
||||
"hourly": [
|
||||
'erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group.trigger_emails',
|
||||
"erpnext.accounts.doctype.subscription.subscription.process_all",
|
||||
"erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_settings.schedule_get_order_details",
|
||||
"erpnext.accounts.doctype.gl_entry.gl_entry.rename_gle_sle_docs",
|
||||
|
||||
"erpnext.projects.doctype.project.project.hourly_reminder",
|
||||
"erpnext.projects.doctype.project.project.collect_project_status"
|
||||
],
|
||||
"daily": [
|
||||
"erpnext.stock.reorder_item.reorder_item",
|
||||
@ -257,6 +261,7 @@ scheduler_events = {
|
||||
"erpnext.assets.doctype.asset.asset.make_post_gl_entry",
|
||||
"erpnext.crm.doctype.contract.contract.update_status_for_contracts",
|
||||
"erpnext.projects.doctype.project.project.update_project_sales_billing",
|
||||
"erpnext.projects.doctype.project.project.send_project_status_email_to_users",
|
||||
"erpnext.quality_management.doctype.quality_review.quality_review.review"
|
||||
],
|
||||
"daily_long": [
|
||||
|
@ -112,6 +112,10 @@ def get_user_emails_from_group(group):
|
||||
if isinstance(group_doc, string_types):
|
||||
group_doc = frappe.get_doc('Daily Work Summary Group', group)
|
||||
|
||||
emails = [d.email for d in group_doc.users if frappe.db.get_value("User", d.user, "enabled")]
|
||||
emails = get_users_email(group_doc)
|
||||
|
||||
return emails
|
||||
|
||||
def get_users_email(doc):
|
||||
return [d.email for d in doc.users
|
||||
if frappe.db.get_value("User", d.user, "enabled")]
|
||||
|
@ -350,7 +350,8 @@ frappe.ui.form.on("Work Order", {
|
||||
before_submit: function(frm) {
|
||||
frm.toggle_reqd(["fg_warehouse", "wip_warehouse"], true);
|
||||
frm.fields_dict.required_items.grid.toggle_reqd("source_warehouse", true);
|
||||
frm.toggle_reqd("transfer_material_against", frm.doc.operations);
|
||||
frm.toggle_reqd("transfer_material_against",
|
||||
frm.doc.operations && frm.doc.operations.length > 0);
|
||||
frm.fields_dict.operations.grid.toggle_reqd("workstation", frm.doc.operations);
|
||||
},
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
execute:import unidecode # new requirement
|
||||
erpnext.patches.v8_0.move_perpetual_inventory_setting
|
||||
erpnext.patches.v8_9.set_print_zero_amount_taxes
|
||||
erpnext.patches.v11_0.rename_production_order_to_work_order
|
||||
erpnext.patches.v11_0.refactor_naming_series
|
||||
erpnext.patches.v11_0.refactor_autoname_naming
|
||||
@ -442,7 +443,6 @@ erpnext.patches.v8_9.add_setup_progress_actions #08-09-2017 #26-09-2017 #22-11-2
|
||||
erpnext.patches.v8_9.rename_company_sales_target_field
|
||||
erpnext.patches.v8_8.set_bom_rate_as_per_uom
|
||||
erpnext.patches.v8_8.add_new_fields_in_accounts_settings
|
||||
erpnext.patches.v8_9.set_print_zero_amount_taxes
|
||||
erpnext.patches.v8_9.set_default_customer_group
|
||||
erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts
|
||||
erpnext.patches.v8_9.set_default_fields_in_variant_settings
|
||||
@ -572,7 +572,7 @@ execute:frappe.delete_doc_if_exists("Page", "sales-analytics")
|
||||
execute:frappe.delete_doc_if_exists("Page", "purchase-analytics")
|
||||
execute:frappe.delete_doc_if_exists("Page", "stock-analytics")
|
||||
execute:frappe.delete_doc_if_exists("Page", "production-analytics")
|
||||
erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13
|
||||
erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09
|
||||
erpnext.patches.v11_0.drop_column_max_days_allowed
|
||||
erpnext.patches.v11_0.change_healthcare_desktop_icons
|
||||
erpnext.patches.v10_0.update_user_image_in_employee
|
||||
@ -580,8 +580,9 @@ erpnext.patches.v11_0.update_delivery_trip_status
|
||||
erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items
|
||||
erpnext.patches.v11_0.set_missing_gst_hsn_code
|
||||
erpnext.patches.v11_0.rename_bom_wo_fields
|
||||
erpnext.patches.v11_0.rename_additional_salary_component_additional_salary
|
||||
erpnext.patches.v11_0.renamed_from_to_fields_in_project
|
||||
erpnext.patches.v12_0.change_qms_icon
|
||||
erpnext.patches.v12_0.rename_learn_to_help
|
||||
erpnext.patches.v12_0.rename_accounts_desktop_icon_to_accounting
|
||||
erpnext.patches.v12_0.replace_project_list_desktop_icon_with_projects_module_desktop_icon
|
||||
erpnext.patches.v11_0.rename_additional_salary_component_additional_salary
|
||||
|
13
erpnext/patches/v11_0/renamed_from_to_fields_in_project.py
Normal file
13
erpnext/patches/v11_0/renamed_from_to_fields_in_project.py
Normal file
@ -0,0 +1,13 @@
|
||||
# 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
|
||||
from frappe.model.utils.rename_field import rename_field
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('projects', 'doctype', 'project')
|
||||
|
||||
if frappe.db.has_column('Project', 'from'):
|
||||
rename_field('Project', 'from', 'from_time')
|
||||
rename_field('Project', 'to', 'to_time')
|
File diff suppressed because it is too large
Load Diff
@ -3,16 +3,16 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import flt, getdate, get_url, now
|
||||
from frappe import _
|
||||
|
||||
from frappe.model.document import Document
|
||||
from six import iteritems
|
||||
from email_reply_parser import EmailReplyParser
|
||||
from frappe.utils import (flt, getdate, get_url, now,
|
||||
nowtime, get_time, today, get_datetime, add_days)
|
||||
from erpnext.controllers.queries import get_filters_cond
|
||||
from frappe.desk.reportview import get_match_cond
|
||||
import datetime
|
||||
|
||||
from six import iteritems
|
||||
from erpnext.hr.doctype.daily_work_summary.daily_work_summary import get_users_email
|
||||
from erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group import is_holiday_today
|
||||
from frappe.model.document import Document
|
||||
|
||||
class Project(Document):
|
||||
def get_feed(self):
|
||||
@ -406,56 +406,137 @@ def get_users_for_project(doctype, txt, searchfield, start, page_len, filters):
|
||||
def get_cost_center_name(project):
|
||||
return frappe.db.get_value("Project", project, "cost_center")
|
||||
|
||||
@frappe.whitelist()
|
||||
def hourly_reminder():
|
||||
project = frappe.db.sql("""SELECT `tabProject`.name FROM `tabProject` WHERE `tabProject`.frequency = "Hourly" and (CURTIME() BETWEEN `tabProject`.from and `tabProject`.to) AND `tabProject`.collect_progress = 1 ORDER BY `tabProject`.name;""")
|
||||
create_project_update(project)
|
||||
fields = ["from_time", "to_time"]
|
||||
projects = get_projects_for_collect_progress("Hourly", fields)
|
||||
|
||||
@frappe.whitelist()
|
||||
def twice_daily_reminder():
|
||||
project = frappe.db.sql("""SELECT `tabProject User`.user FROM `tabProject User` INNER JOIN `tabProject` ON `tabProject`.project_name = `tabProject User`.parent WHERE (`tabProject`.frequency = "Twice Daily") AND ((`tabProject`.first_email BETWEEN DATE_ADD(curtime(), INTERVAL -15 MINUTE) AND DATE_ADD(curtime(), INTERVAL 15 MINUTE)) OR (`tabProject`.second_email BETWEEN DATE_ADD(curtime(), INTERVAL -15 MINUTE) AND DATE_ADD(curtime(), INTERVAL 15 MINUTE))) AND `tabProject`.collect_progress = 1;""")
|
||||
create_project_update(project)
|
||||
for project in projects:
|
||||
if (get_time(nowtime()) >= get_time(project.from_time) or
|
||||
get_time(nowtime()) <= get_time(project.to_time)):
|
||||
send_project_update_email_to_users(project.name)
|
||||
|
||||
def project_status_update_reminder():
|
||||
daily_reminder()
|
||||
twice_daily_reminder()
|
||||
weekly_reminder()
|
||||
|
||||
@frappe.whitelist()
|
||||
def daily_reminder():
|
||||
project = frappe.db.sql("""SELECT `tabProject User`.user FROM `tabProject User` INNER JOIN `tabProject` ON `tabProject`.project_name = `tabProject User`.parent WHERE (`tabProject`.frequency = "Daily") AND (`tabProject`.daily_time_to_send BETWEEN DATE_ADD(curtime(), INTERVAL -15 MINUTE) AND DATE_ADD(curtime(), INTERVAL 15 MINUTE)) AND `tabProject`.collect_progress = 1;""")
|
||||
create_project_update(project)
|
||||
fields = ["daily_time_to_send"]
|
||||
projects = get_projects_for_collect_progress("Daily", fields)
|
||||
|
||||
@frappe.whitelist()
|
||||
def weekly():
|
||||
today = datetime.datetime.now().strftime("%A")
|
||||
project = frappe.db.sql("""SELECT `tabProject User`.user FROM `tabProject User` INNER JOIN `tabProject` ON `tabProject`.project_name = `tabProject User`.parent WHERE (`tabProject`.frequency = "Weekly") AND (`tabProject`.day_to_send = %s) AND (`tabProject`.weekly_time_to_send BETWEEN DATE_ADD(curtime(), INTERVAL -15 MINUTE) AND DATE_ADD(curtime(), INTERVAL 15 MINUTE)) AND `tabProject`.collect_progress = 1""", today)
|
||||
create_project_update(project)
|
||||
for project in projects:
|
||||
if not check_project_update_exists(project.name, project.get("daily_time_to_send")):
|
||||
send_project_update_email_to_users(project.name)
|
||||
|
||||
#Call this function in order to generate the Project Update for a specific project
|
||||
def create_project_update(project):
|
||||
data = []
|
||||
date_today = datetime.date.today()
|
||||
time_now = frappe.utils.now_datetime().strftime('%H:%M:%S')
|
||||
for projects in project:
|
||||
project_update_dict = {
|
||||
"doctype" : "Project Update",
|
||||
"project" : projects[0],
|
||||
"date": date_today,
|
||||
"time": time_now,
|
||||
"naming_series": "UPDATE-.project.-.YY.MM.DD.-"
|
||||
def twice_daily_reminder():
|
||||
fields = ["first_email", "second_email"]
|
||||
projects = get_projects_for_collect_progress("Twice Daily", fields)
|
||||
|
||||
for project in projects:
|
||||
for d in fields:
|
||||
if not check_project_update_exists(project.name, project.get(d)):
|
||||
send_project_update_email_to_users(project.name)
|
||||
|
||||
def weekly_reminder():
|
||||
fields = ["day_to_send", "weekly_time_to_send"]
|
||||
projects = get_projects_for_collect_progress("Weekly", fields)
|
||||
|
||||
current_day = get_datetime().strftime("%A")
|
||||
for project in projects:
|
||||
if current_day != project.day_to_send:
|
||||
continue
|
||||
|
||||
if not check_project_update_exists(project.name, project.get("weekly_time_to_send")):
|
||||
send_project_update_email_to_users(project.name)
|
||||
|
||||
def check_project_update_exists(project, time):
|
||||
data = frappe.db.sql(""" SELECT name from `tabProject Update`
|
||||
WHERE project = %s and date = %s and time >= %s """, (project, today(), time))
|
||||
|
||||
return True if data and data[0][0] else False
|
||||
|
||||
def get_projects_for_collect_progress(frequency, fields):
|
||||
fields.extend(["name"])
|
||||
|
||||
return frappe.get_all("Project", fields = fields,
|
||||
filters = {'collect_progress': 1, 'frequency': frequency})
|
||||
|
||||
def send_project_update_email_to_users(project):
|
||||
doc = frappe.get_doc('Project', project)
|
||||
|
||||
if is_holiday_today(doc.holiday_list) or not doc.users: return
|
||||
|
||||
project_update = frappe.get_doc({
|
||||
"doctype" : "Project Update",
|
||||
"project" : project,
|
||||
"sent": 0,
|
||||
"date": today(),
|
||||
"time": nowtime(),
|
||||
"naming_series": "UPDATE-.project.-.YY.MM.DD.-",
|
||||
}).insert()
|
||||
|
||||
subject = "For project %s, update your status" % (project)
|
||||
|
||||
incoming_email_account = frappe.db.get_value('Email Account',
|
||||
dict(enable_incoming=1, default_incoming=1), 'email_id')
|
||||
|
||||
frappe.sendmail(recipients=get_users_email(doc),
|
||||
message=doc.message,
|
||||
subject=_(subject),
|
||||
reference_doctype=project_update.doctype,
|
||||
reference_name=project_update.name,
|
||||
reply_to=incoming_email_account
|
||||
)
|
||||
|
||||
def collect_project_status():
|
||||
for data in frappe.get_all("Project Update",
|
||||
{'date': today(), 'sent': 0}):
|
||||
replies = frappe.get_all('Communication',
|
||||
fields=['content', 'text_content', 'sender'],
|
||||
filters=dict(reference_doctype="Project Update",
|
||||
reference_name=data.name,
|
||||
communication_type='Communication',
|
||||
sent_or_received='Received'),
|
||||
order_by='creation asc')
|
||||
|
||||
for d in replies:
|
||||
doc = frappe.get_doc("Project Update", data.name)
|
||||
user_data = frappe.db.get_values("User", {"email": d.sender},
|
||||
["full_name", "user_image", "name"], as_dict=True)[0]
|
||||
|
||||
doc.append("users", {
|
||||
'user': user_data.name,
|
||||
'full_name': user_data.full_name,
|
||||
'image': user_data.user_image,
|
||||
'project_status': frappe.utils.md_to_html(
|
||||
EmailReplyParser.parse_reply(d.text_content) or d.content
|
||||
)
|
||||
})
|
||||
|
||||
doc.save(ignore_permissions=True)
|
||||
|
||||
def send_project_status_email_to_users():
|
||||
yesterday = add_days(today(), -1)
|
||||
|
||||
for d in frappe.get_all("Project Update",
|
||||
{'date': yesterday, 'sent': 0}):
|
||||
doc = frappe.get_doc("Project Update", d.name)
|
||||
|
||||
project_doc = frappe.get_doc('Project', doc.project)
|
||||
|
||||
args = {
|
||||
"users": doc.users,
|
||||
"title": _("Project Summary for {0}").format(yesterday)
|
||||
}
|
||||
project_update = frappe.get_doc(project_update_dict)
|
||||
project_update.insert()
|
||||
#you can edit your local_host
|
||||
local_host = "http://localhost:8003"
|
||||
project_update_url = "<a class = 'btn btn-primary' href=%s target='_blank'>" % (local_host +"/desk#Form/Project%20Update/" + (project_update.name)) + ("CREATE PROJECT UPDATE" + "</a>")
|
||||
data.append(project_update_url)
|
||||
|
||||
email = frappe.db.sql("""SELECT user from `tabProject User` WHERE parent = %s;""", project[0])
|
||||
for emails in email:
|
||||
frappe.sendmail(
|
||||
recipients=emails,
|
||||
subject=frappe._(projects[0]),
|
||||
header=[frappe._("Please Update your Project Status"), 'blue'],
|
||||
message= project_update_url
|
||||
)
|
||||
return data
|
||||
frappe.sendmail(recipients=get_users_email(project_doc),
|
||||
template='daily_project_summary',
|
||||
args=args,
|
||||
subject=_("Daily Project Summary for {0}").format(d.name),
|
||||
reference_doctype="Project Update",
|
||||
reference_name=d.name)
|
||||
|
||||
doc.db_set('sent', 1)
|
||||
|
||||
def update_project_sales_billing():
|
||||
sales_update_frequency = frappe.db.get_single_value("Selling Settings", "sales_update_frequency")
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
@ -13,6 +14,40 @@
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Series",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "PROJ-UPD-.YYYY.-",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
@ -46,6 +81,39 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "sent",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Sent",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
@ -172,39 +240,6 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "progress",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "How is the Project Progressing Right Now?",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Not Updated\nGreat/Quickly\nGood/Steady\nChallenging/Slow\nProblematic/Stuck",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
@ -238,38 +273,6 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "progress_details",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Progress Details",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
@ -301,40 +304,6 @@
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Series",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "PROJ-UPD-.YYYY.-",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
@ -347,7 +316,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-08-21 14:44:21.287709",
|
||||
"modified": "2019-01-16 19:31:05.210656",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Project Update",
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
@ -44,6 +45,136 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "user.email",
|
||||
"fieldname": "email",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Email",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "user.user_image",
|
||||
"fieldname": "image",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 1,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Image",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "user.full_name",
|
||||
"fieldname": "full_name",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Full Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
@ -107,6 +238,70 @@
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:parent.doctype == 'Project Update'",
|
||||
"fieldname": "project_status",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Project Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
@ -119,7 +314,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-09-09 12:39:38.376816",
|
||||
"modified": "2019-01-17 17:10:05.339735",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Project User",
|
||||
|
@ -28,7 +28,10 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
|
||||
if (this.frm.doc.__islocal
|
||||
&& frappe.meta.has_field(this.frm.doc.doctype, "disable_rounded_total")) {
|
||||
this.frm.set_value("disable_rounded_total", cint(frappe.sys_defaults.disable_rounded_total));
|
||||
|
||||
var df = frappe.meta.get_docfield(this.frm.doc.doctype, "disable_rounded_total");
|
||||
var disable = df.default || cint(frappe.sys_defaults.disable_rounded_total);
|
||||
this.frm.set_value("disable_rounded_total", disable);
|
||||
}
|
||||
|
||||
/* eslint-disable */
|
||||
@ -126,7 +129,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
if (doc.doctype == "Purchase Order" && item.blanket_order_rate) {
|
||||
item_rate = item.blanket_order_rate;
|
||||
}
|
||||
item.discount_amount = flt(item_rate) * flt(item.discount_percentage) / 100;
|
||||
item.discount_amount = flt(item_rate) * flt(item.discount_percentage) / 100;
|
||||
item.rate = flt((item.price_list_rate) - (item.discount_amount), precision('rate', item));
|
||||
|
||||
this.calculate_taxes_and_totals();
|
||||
@ -273,26 +276,26 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
d.qty = d.qty - my_qty;
|
||||
cur_frm.doc.items[i].stock_qty = my_qty*cur_frm.doc.items[i].conversion_factor;
|
||||
cur_frm.doc.items[i].qty = my_qty;
|
||||
|
||||
|
||||
frappe.msgprint("Assigning " + d.mr_name + " to " + d.item_code + " (row " + cur_frm.doc.items[i].idx + ")");
|
||||
if (qty > 0)
|
||||
{
|
||||
frappe.msgprint("Splitting " + qty + " units of " + d.item_code);
|
||||
var newrow = frappe.model.add_child(cur_frm.doc, cur_frm.doc.items[i].doctype, "items");
|
||||
item_length++;
|
||||
|
||||
|
||||
for (var key in cur_frm.doc.items[i])
|
||||
{
|
||||
newrow[key] = cur_frm.doc.items[i][key];
|
||||
}
|
||||
|
||||
|
||||
newrow.idx = item_length;
|
||||
newrow["stock_qty"] = newrow.conversion_factor*qty;
|
||||
newrow["qty"] = qty;
|
||||
|
||||
|
||||
newrow["material_request"] = "";
|
||||
newrow["material_request_item"] = "";
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -309,7 +312,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
if (doc.auto_repeat) {
|
||||
frappe.call({
|
||||
method:"frappe.desk.doctype.auto_repeat.auto_repeat.update_reference",
|
||||
args:{
|
||||
args:{
|
||||
docname: doc.auto_repeat,
|
||||
reference:doc.name
|
||||
},
|
||||
@ -434,4 +437,3 @@ erpnext.buying.get_items_from_product_bundle = function(frm) {
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
|
@ -7,5 +7,5 @@ from erpnext import get_region
|
||||
|
||||
def check_deletion_permission(doc, method):
|
||||
region = get_region(doc.company)
|
||||
if region in ["Nepal", "France"]:
|
||||
if region in ["Nepal", "France"] and doc.docstatus != 0:
|
||||
frappe.throw(_("Deletion is not permitted for country {0}".format(region)))
|
||||
|
@ -126,6 +126,9 @@ def make_custom_fields(update=True):
|
||||
dict(fieldname='place_of_supply', label='Place of Supply',
|
||||
fieldtype='Data', insert_after='shipping_address',
|
||||
print_hide=1, read_only=0),
|
||||
]
|
||||
|
||||
purchase_invoice_itc_fields = [
|
||||
dict(fieldname='eligibility_for_itc', label='Eligibility For ITC',
|
||||
fieldtype='Select', insert_after='reason_for_issuing_document', print_hide=1,
|
||||
options='input\ninput service\ncapital goods\nineligible', default="ineligible"),
|
||||
@ -152,6 +155,9 @@ def make_custom_fields(update=True):
|
||||
dict(fieldname='company_gstin', label='Company GSTIN',
|
||||
fieldtype='Data', insert_after='company_address',
|
||||
fetch_from='company_address.gstin', print_hide=1),
|
||||
]
|
||||
|
||||
sales_invoice_shipping_fields = [
|
||||
dict(fieldname='port_code', label='Port Code',
|
||||
fieldtype='Data', insert_after='reason_for_issuing_document', print_hide=1,
|
||||
depends_on="eval:doc.invoice_type=='Export' "),
|
||||
@ -214,9 +220,12 @@ def make_custom_fields(update=True):
|
||||
dict(fieldname='gst_state_number', label='GST State Number',
|
||||
fieldtype='Data', insert_after='gst_state', read_only=1),
|
||||
],
|
||||
'Purchase Invoice': invoice_gst_fields + purchase_invoice_gst_fields,
|
||||
'Sales Invoice': invoice_gst_fields + sales_invoice_gst_fields,
|
||||
'Delivery Note': sales_invoice_gst_fields + ewaybill_fields,
|
||||
'Purchase Invoice': invoice_gst_fields + purchase_invoice_gst_fields + purchase_invoice_itc_fields,
|
||||
'Purchase Order': purchase_invoice_gst_fields,
|
||||
'Purchase Receipt': purchase_invoice_gst_fields,
|
||||
'Sales Invoice': invoice_gst_fields + sales_invoice_gst_fields + sales_invoice_shipping_fields,
|
||||
'Delivery Note': sales_invoice_gst_fields + ewaybill_fields + sales_invoice_shipping_fields,
|
||||
'Sales Order': sales_invoice_gst_fields,
|
||||
'Sales Taxes and Charges Template': inter_state_gst_field,
|
||||
'Purchase Taxes and Charges Template': inter_state_gst_field,
|
||||
'Item': [
|
||||
|
@ -31,6 +31,26 @@ class TestQuotation(unittest.TestCase):
|
||||
|
||||
self.assertFalse(sales_order.get('payment_schedule'))
|
||||
|
||||
def test_make_sales_order_with_different_currency(self):
|
||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||
|
||||
quotation = frappe.copy_doc(test_records[0])
|
||||
quotation.transaction_date = nowdate()
|
||||
quotation.valid_till = add_months(quotation.transaction_date, 1)
|
||||
quotation.insert()
|
||||
quotation.submit()
|
||||
|
||||
sales_order = make_sales_order(quotation.name)
|
||||
sales_order.currency = "USD"
|
||||
sales_order.conversion_rate = 20.0
|
||||
sales_order.delivery_date = "2019-01-01"
|
||||
sales_order.naming_series = "_T-Quotation-"
|
||||
sales_order.transaction_date = nowdate()
|
||||
sales_order.insert()
|
||||
|
||||
self.assertEquals(sales_order.currency, "USD")
|
||||
self.assertNotEqual(sales_order.currency, quotation.currency)
|
||||
|
||||
def test_make_sales_order(self):
|
||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||
|
||||
|
@ -17,6 +17,20 @@ frappe.ui.form.on("Sales Order", {
|
||||
// formatter for material request item
|
||||
frm.set_indicator_formatter('item_code',
|
||||
function(doc) { return (doc.stock_qty<=doc.delivered_qty) ? "green" : "orange" })
|
||||
|
||||
frm.set_query('company_address', function(doc) {
|
||||
if(!doc.company) {
|
||||
frappe.throw(__('Please set Company'));
|
||||
}
|
||||
|
||||
return {
|
||||
query: 'frappe.contacts.doctype.address.address.address_query',
|
||||
filters: {
|
||||
link_doctype: 'Company',
|
||||
link_name: doc.company
|
||||
}
|
||||
};
|
||||
})
|
||||
},
|
||||
refresh: function(frm) {
|
||||
if(frm.doc.docstatus == 1 && frm.doc.status == 'To Deliver and Bill') {
|
||||
|
@ -748,34 +748,99 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "col_break46",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company_address_display",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company_address",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company Address",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Address",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "col_break46",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
@ -1109,36 +1174,37 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Rate at which Price list currency is converted to company's base currency",
|
||||
"fieldname": "plc_conversion_rate",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Price List Exchange Rate",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "9",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Rate at which Price list currency is converted to company's base currency",
|
||||
"fieldname": "plc_conversion_rate",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Price List Exchange Rate",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "9",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -4003,23 +4069,23 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 105,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-01-07 16:51:50.857438",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 105,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-01-09 16:51:47.917329",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
|
@ -147,7 +147,7 @@ class SalesOrder(SellingController):
|
||||
super(SalesOrder, self).validate_with_previous_doc({
|
||||
"Quotation": {
|
||||
"ref_dn_field": "prevdoc_docname",
|
||||
"compare_fields": [["company", "="], ["currency", "="]]
|
||||
"compare_fields": [["company", "="]]
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
@ -352,7 +353,7 @@
|
||||
"fieldname": "to_emp",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_user_permissions": 1,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
@ -618,7 +619,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-08-21 16:15:42.627233",
|
||||
"modified": "2019-01-21 17:10:39.822125",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Authorization Rule",
|
||||
|
@ -150,7 +150,7 @@ def adjust_qty_for_expired_items(data):
|
||||
if item.get('has_batch_no') and item.get('website_warehouse'):
|
||||
stock_qty_dict = get_qty_in_stock(
|
||||
item.get('name'), 'website_warehouse', item.get('website_warehouse'))
|
||||
qty = stock_qty_dict.stock_qty[0][0]
|
||||
qty = stock_qty_dict.stock_qty[0][0] if stock_qty_dict.stock_qty else 0
|
||||
item['in_stock'] = 1 if qty else 0
|
||||
adjusted_data.append(item)
|
||||
|
||||
|
@ -66,7 +66,7 @@ def place_order():
|
||||
sales_order = frappe.get_doc(_make_sales_order(quotation.name, ignore_permissions=True))
|
||||
for item in sales_order.get("items"):
|
||||
item.reserved_warehouse, is_stock_item = frappe.db.get_value("Item",
|
||||
item.item_code, ["website_warehouse", "is_stock_item"]) or None, None
|
||||
item.item_code, ["website_warehouse", "is_stock_item"])
|
||||
|
||||
if is_stock_item:
|
||||
item_stock = get_qty_in_stock(item.item_code, "website_warehouse")
|
||||
|
@ -5,6 +5,7 @@ $.extend(cur_frm.cscript, {
|
||||
onload: function() {
|
||||
if(cur_frm.doc.__onload && cur_frm.doc.__onload.quotation_series) {
|
||||
cur_frm.fields_dict.quotation_series.df.options = cur_frm.doc.__onload.quotation_series;
|
||||
cur_frm.refresh_field("quotation_series");
|
||||
}
|
||||
},
|
||||
refresh: function(){
|
||||
|
@ -6,7 +6,7 @@ import unittest
|
||||
from frappe.utils import nowdate
|
||||
from erpnext.stock.doctype.item.test_item import create_item
|
||||
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
|
||||
from erpnext.controllers.stock_controller import QualityInspectionRejectedError, QualityInspectionRequiredError
|
||||
from erpnext.controllers.stock_controller import QualityInspectionRejectedError, QualityInspectionRequiredError, QualityInspectionNotSubmittedError
|
||||
|
||||
# test_records = frappe.get_test_records('Quality Inspection')
|
||||
|
||||
@ -19,7 +19,7 @@ class TestQualityInspection(unittest.TestCase):
|
||||
dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True)
|
||||
self.assertRaises(QualityInspectionRequiredError, dn.submit)
|
||||
|
||||
qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, status="Rejected")
|
||||
qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, status="Rejected", submit=True)
|
||||
dn.reload()
|
||||
self.assertRaises(QualityInspectionRejectedError, dn.submit)
|
||||
|
||||
@ -27,6 +27,12 @@ class TestQualityInspection(unittest.TestCase):
|
||||
dn.reload()
|
||||
dn.submit()
|
||||
|
||||
def test_qa_not_submit(self):
|
||||
dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True)
|
||||
qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, submit = False)
|
||||
dn.items[0].quality_inspection = qa.name
|
||||
self.assertRaises(QualityInspectionNotSubmittedError, dn.submit)
|
||||
|
||||
def create_quality_inspection(**args):
|
||||
args = frappe._dict(args)
|
||||
qa = frappe.new_doc("Quality Inspection")
|
||||
@ -42,6 +48,7 @@ def create_quality_inspection(**args):
|
||||
"status": args.status
|
||||
})
|
||||
qa.save()
|
||||
qa.submit()
|
||||
if args.submit:
|
||||
qa.submit()
|
||||
|
||||
return qa
|
||||
|
@ -302,6 +302,9 @@ def has_duplicate_serial_no(sn, sle):
|
||||
if sn.warehouse:
|
||||
return True
|
||||
|
||||
if sn.company != sle.company:
|
||||
return False
|
||||
|
||||
status = False
|
||||
if sn.purchase_document_no:
|
||||
if sle.voucher_type in ['Purchase Receipt', 'Stock Entry', "Purchase Invoice"] and \
|
||||
@ -357,6 +360,7 @@ def auto_make_serial_nos(args):
|
||||
sr.warehouse = args.get('warehouse') if args.get('actual_qty', 0) > 0 else None
|
||||
sr.batch_no = args.get('batch_no')
|
||||
sr.location = args.get('location')
|
||||
sr.company = args.get('company')
|
||||
if sr.sales_order and args.get('voucher_type') == "Stock Entry" \
|
||||
and not args.get('actual_qty', 0) > 0:
|
||||
sr.sales_order = None
|
||||
|
@ -7,6 +7,12 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe, unittest
|
||||
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
||||
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
|
||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||
|
||||
test_dependencies = ["Item"]
|
||||
test_records = frappe.get_test_records('Serial No')
|
||||
|
||||
@ -29,3 +35,21 @@ class TestSerialNo(unittest.TestCase):
|
||||
|
||||
sr.warehouse = "_Test Warehouse - _TC"
|
||||
self.assertTrue(SerialNoCannotCannotChangeError, sr.save)
|
||||
|
||||
def test_inter_company_transfer(self):
|
||||
se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
|
||||
serial_nos = get_serial_nos(se.get("items")[0].serial_no)
|
||||
|
||||
create_delivery_note(item_code="_Test Serialized Item With Series", qty=1, serial_no=serial_nos[0])
|
||||
|
||||
wh = create_warehouse("_Test Warehouse", company="_Test Company 1")
|
||||
make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1, serial_no=serial_nos[0],
|
||||
company="_Test Company 1", warehouse=wh)
|
||||
|
||||
serial_no = frappe.db.get_value("Serial No", serial_nos[0], ["warehouse", "company"], as_dict=1)
|
||||
|
||||
self.assertEqual(serial_no.warehouse, wh)
|
||||
self.assertEqual(serial_no.company, "_Test Company 1")
|
||||
|
||||
def tearDown(self):
|
||||
frappe.db.rollback()
|
@ -8,6 +8,7 @@ from erpnext import set_perpetual_inventory
|
||||
from frappe.test_runner import make_test_records
|
||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account
|
||||
|
||||
import erpnext
|
||||
import frappe
|
||||
import unittest
|
||||
test_records = frappe.get_test_records('Warehouse')
|
||||
@ -90,17 +91,24 @@ class TestWarehouse(unittest.TestCase):
|
||||
self.assertTrue(frappe.db.get_value("Warehouse",
|
||||
filters={"account": "Test Warehouse for Merging 2 - _TC"}))
|
||||
|
||||
def create_warehouse(warehouse_name, properties=None):
|
||||
if not frappe.db.exists("Warehouse", warehouse_name + " - _TC"):
|
||||
def create_warehouse(warehouse_name, properties=None, company=None):
|
||||
if not company:
|
||||
company = "_Test Company"
|
||||
|
||||
warehouse_id = erpnext.encode_company_abbr(warehouse_name, company)
|
||||
if not frappe.db.exists("Warehouse", warehouse_id):
|
||||
w = frappe.new_doc("Warehouse")
|
||||
w.warehouse_name = warehouse_name
|
||||
w.parent_warehouse = "_Test Warehouse Group - _TC"
|
||||
w.company = "_Test Company"
|
||||
w.company = company
|
||||
make_account_for_warehouse(warehouse_name, w)
|
||||
w.account = warehouse_name + " - _TC"
|
||||
w.account = warehouse_id
|
||||
if properties:
|
||||
w.update(properties)
|
||||
w.save()
|
||||
return w.name
|
||||
else:
|
||||
return warehouse_id
|
||||
|
||||
def make_account_for_warehouse(warehouse_name, warehouse_obj):
|
||||
if not frappe.db.exists("Account", warehouse_name + " - _TC"):
|
||||
|
46
erpnext/templates/emails/daily_project_summary.html
Normal file
46
erpnext/templates/emails/daily_project_summary.html
Normal file
@ -0,0 +1,46 @@
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<h3>{{ title }}</h3>
|
||||
</tr>
|
||||
</table>
|
||||
{% for user in users %}
|
||||
<table class="panel-header" border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr height="10"></tr>
|
||||
<tr>
|
||||
<td width="15"></td>
|
||||
<td valign="top" width="24">
|
||||
{% if user.image %}
|
||||
<img class="sender-avatar" width="24" height="24" embed="{{ user.image }}"/>
|
||||
{% else %}
|
||||
<div class="sender-avatar-placeholder">
|
||||
{{ user.full_name[0] }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td width="10"></td>
|
||||
<td>
|
||||
<div class="text-medium text-muted">
|
||||
<span>{{ user.full_name }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td width="15"></td>
|
||||
</tr>
|
||||
<tr height="10"></tr>
|
||||
</table>
|
||||
<table class="panel-body" border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr height="10"></tr>
|
||||
<tr>
|
||||
<td width="15"></td>
|
||||
<td>
|
||||
<div>
|
||||
{{ user.project_status }}
|
||||
</div>
|
||||
</td>
|
||||
<td width="15"></td>
|
||||
</tr>
|
||||
<tr height="10"></tr>
|
||||
</table>
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr height="20"></tr>
|
||||
</table>
|
||||
{% endfor %}
|
Loading…
x
Reference in New Issue
Block a user