Compare commits

...

28 Commits

Author SHA1 Message Date
Nabin Hait
c4894a5287 Merge branch 'hotfix' 2017-03-30 13:14:34 +05:30
Nabin Hait
a9bef56a94 bumped to version 7.2.32 2017-03-30 13:44:34 +06:00
mbauskar
07e6bdd4f2 [minor] check employee date of joining before marking the employee attendance 2017-03-30 12:52:29 +05:30
mbauskar
de98ff6bb9 [minor] hide the stock details section if update_stock is unchecked 2017-03-29 17:29:58 +05:30
Nabin Hait
da749f716b Merge pull request #8172 from rohitwaghchaure/credit_note_serial_no_issue
[fix] During making credit note from sales invoice, system fetching new serial no instead of old serial no from the sales invoice
2017-03-28 13:49:32 +05:30
Nabin Hait
2cf5ca28f6 Merge pull request #8173 from nabinhait/hotfix
In gross profit report, if incoming rate not found from last sle, consider average valuation rate
2017-03-28 13:49:09 +05:30
Nabin Hait
95db9f9e09 Merge pull request #8175 from rohitwaghchaure/production_planning_issue
[fix] sales order with status closed fetching on production planning tool
2017-03-28 13:48:42 +05:30
Rohit Waghchaure
d7908f8e3a [fix] sales order with status closed fetching on production planning tool 2017-03-28 12:30:23 +05:30
Nabin Hait
77c970549b In gross profit report, if incoming rate not found from last sle, consider average valuation rate 2017-03-28 12:20:31 +05:30
Rohit Waghchaure
5ecbaa408b [fix] During making credit note from sales invoice, system fetching new serial no instead of old serial no from the sales invoice 2017-03-28 12:09:07 +05:30
Nabin Hait
3e43f275a0 Merge branch 'hotfix' 2017-03-27 12:27:38 +05:30
Nabin Hait
70c3f79d12 bumped to version 7.2.31 2017-03-27 12:57:38 +06:00
Nabin Hait
d25e314ccb Merge pull request #8054 from rohitwaghchaure/purchase_return_issue_invoice
[fix] Quantity is not copying in the Received Qty during making of debit note from the purchase invoice
2017-03-23 17:01:58 +05:30
Nabin Hait
c7dc838306 Merge pull request #8068 from rohitwaghchaure/asset_depreciation_issue
[fix] Precision issue during making of depreciation schedule
2017-03-23 16:59:12 +05:30
Nabin Hait
1775a3db38 Merge pull request #8115 from rohitwaghchaure/setup_wizard_unpickle_issue
[fix] UnpickleError, removed _ method from the argument of the function
2017-03-23 16:14:52 +05:30
Rohit Waghchaure
57f35a25a1 [fix] UnpickleError, removed _ method from the argument of the function 2017-03-23 14:55:52 +05:30
Rohit Waghchaure
b69d311268 [fix] precision issue during making of depreciation schedule 2017-03-20 16:30:34 +05:30
Rohit Waghchaure
414c0ab3bb [fix] Quantity is not copying in the Received Qty during making of debit note 2017-03-17 17:19:17 +05:30
Nabin Hait
f494626ce4 Merge pull request #8034 from mbauskar/hotfix
[minor] make item code mandatory if update_stock is selected
2017-03-15 19:40:20 +05:30
mbauskar
27efc91db0 [minor] make item code mandatory if update_stock is selected 2017-03-15 18:57:18 +05:30
Nabin Hait
c1a5b348b5 Merge branch 'hotfix' 2017-03-15 11:28:06 +05:30
Nabin Hait
1157ee365b bumped to version 7.2.30 2017-03-15 11:58:06 +06:00
Nabin Hait
fd9b2467d6 Merge pull request #7966 from rohitwaghchaure/item_variant_issue_for_nuermic
[Fix] Item variants broken when using naming series for items and vriants of numeric value
2017-03-12 16:34:40 +05:30
Rohit Waghchaure
0169341917 [Fix] Item variants broken when using naming series for items and vriants of numeric value 2017-03-10 19:40:08 +05:30
Nabin Hait
e7e82fe477 Merge pull request #7970 from rmehta/sample-tasks
Descriptions on sample tasks
2017-03-10 14:58:52 +05:30
Rushabh Mehta
83aa5ee3df [messages] cleanup 2017-03-10 12:47:29 +05:30
Rushabh Mehta
868bb26e24 [sample] add help for sample tasks and make them into notifications 2017-03-09 18:11:11 +05:30
Rushabh Mehta
aea1c2a1e3 [minor] allow sales order delivery date before order date 2017-03-09 12:46:51 +05:30
30 changed files with 224 additions and 59 deletions

View File

@@ -2,7 +2,7 @@
from __future__ import unicode_literals
import frappe
__version__ = '7.2.29'
__version__ = '7.2.32'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -112,8 +112,8 @@ class Asset(Document):
def set_accumulated_depreciation(self):
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
for d in self.get("schedules"):
accumulated_depreciation += flt(d.depreciation_amount)
d.accumulated_depreciation_amount = accumulated_depreciation
accumulated_depreciation += flt(d.depreciation_amount, d.precision("depreciation_amount"))
d.accumulated_depreciation_amount = flt(accumulated_depreciation, d.precision("accumulated_depreciation_amount"))
def get_depreciation_amount(self, depreciable_value):
if self.depreciation_method in ("Straight Line", "Manual"):

View File

@@ -117,7 +117,7 @@ def apply_pricing_rule(args):
args_copy = copy.deepcopy(args)
args_copy.update(item)
out.append(get_pricing_rule_for_item(args_copy))
if set_serial_nos_based_on_fifo:
if set_serial_nos_based_on_fifo and not args.get('is_return'):
out.append(get_serial_no_for_item(args_copy))
return out

View File

@@ -205,6 +205,7 @@ function hide_fields(doc) {
cur_frm.cscript.update_stock = function(doc, dt, dn) {
hide_fields(doc, dt, dn);
this.frm.fields_dict.items.grid.toggle_reqd("item_code", doc.update_stock? true: false)
}
cur_frm.fields_dict.cash_bank_account.get_query = function(doc) {

View File

@@ -156,6 +156,12 @@ class PurchaseInvoice(BuyingController):
super(PurchaseInvoice, self).validate_warehouse()
def validate_item_code(self):
for d in self.get('items'):
if not d.item_code:
frappe.msgprint(_("Item Code required at Row No {0}").format(d.idx), raise_exception=True)
def set_expense_account(self, for_validate=False):
auto_accounting_for_stock = cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
@@ -164,6 +170,7 @@ class PurchaseInvoice(BuyingController):
stock_items = self.get_stock_items()
if self.update_stock:
self.validate_item_code()
self.validate_warehouse()
warehouse_account = get_warehouse_account()

View File

@@ -321,6 +321,7 @@ cur_frm.cscript.hide_fields = function(doc) {
cur_frm.cscript.update_stock = function(doc, dt, dn) {
cur_frm.cscript.hide_fields(doc, dt, dn);
this.frm.fields_dict.items.grid.toggle_reqd("item_code", doc.update_stock? true: false)
}
cur_frm.cscript['Make Delivery Note'] = function() {

View File

@@ -1216,6 +1216,7 @@
"collapsible": 1,
"collapsible_depends_on": "eval:doc.serial_no || doc.batch_no",
"columns": 0,
"depends_on": "eval: parent.update_stock",
"fieldname": "warehouse_and_reference",
"fieldtype": "Section Break",
"hidden": 0,
@@ -1910,7 +1911,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-02-07 01:21:47.142162",
"modified": "2017-03-29 16:26:36.507924",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe import _, scrub
from erpnext.stock.utils import get_incoming_rate
from erpnext.stock.stock_ledger import get_valuation_rate
from frappe.utils import flt
@@ -220,7 +221,10 @@ class GrossProfitGenerator(object):
from `tabPurchase Invoice Item`
where item_code = %s and docstatus=1""", item_code)[0][0])
else:
self.average_buying_rate[item_code] = get_incoming_rate(row)
average_buying_rate = get_incoming_rate(row)
if not average_buying_rate:
average_buying_rate = get_valuation_rate(item_code, row.warehouse, allow_zero_rate=True)
self.average_buying_rate[item_code] = average_buying_rate
return self.average_buying_rate[item_code]

View File

@@ -44,8 +44,8 @@ def get_fiscal_years(transaction_date=None, fiscal_year=None, label="Date", verb
raise FiscalYearError, error_msg
return fy
def validate_fiscal_year(date, fiscal_year, label=_("Date"), doc=None):
years = [f[0] for f in get_fiscal_years(date, label=label)]
def validate_fiscal_year(date, fiscal_year, label="Date", doc=None):
years = [f[0] for f in get_fiscal_years(date, label=_(label))]
if fiscal_year not in years:
if doc:
doc.fiscal_year = years[0]

View File

@@ -139,7 +139,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
qty: function(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
if ((doc.doctype == "Purchase Receipt") || (doc.doctype == "Purchase Invoice" && doc.update_stock)) {
if ((doc.doctype == "Purchase Receipt") || (doc.doctype == "Purchase Invoice" && (doc.update_stock || doc.is_return))) {
frappe.model.round_floats_in(item, ["qty", "received_qty"]);
if(!item.rejected_qty && item.qty) {
item.received_qty = item.qty;

View File

@@ -169,7 +169,7 @@ def make_variant_item_code(template_item_code, variant):
item_attribute = frappe.db.sql("""select i.numeric_values, v.abbr
from `tabItem Attribute` i left join `tabItem Attribute Value` v
on (i.name=v.parent)
where i.name=%(attribute)s and v.attribute_value=%(attribute_value)s""", {
where i.name=%(attribute)s and (v.attribute_value=%(attribute_value)s or i.numeric_values = 1)""", {
"attribute": attr.attribute,
"attribute_value": attr.attribute_value
}, as_dict=True)
@@ -180,11 +180,8 @@ def make_variant_item_code(template_item_code, variant):
# frappe.bold(attr.attribute_value)), title=_('Invalid Attribute'),
# exc=InvalidItemAttributeValueError)
if item_attribute[0].numeric_values:
# don't generate item code if one of the attributes is numeric
return
abbreviations.append(item_attribute[0].abbr)
abbr_or_value = cstr(attr.attribute_value) if item_attribute[0].numeric_values else item_attribute[0].abbr
abbreviations.append(abbr_or_value)
if abbreviations:
variant.item_code = "{0}-{1}".format(template_item_code, "-".join(abbreviations))

View File

@@ -32,6 +32,8 @@ class Attendance(Document):
def validate_att_date(self):
if getdate(self.att_date) > getdate(nowdate()):
frappe.throw(_("Attendance can not be marked for future dates"))
elif getdate(self.att_date) < frappe.db.get_value("Employee", self.employee, "date_of_joining"):
frappe.throw(_("Attendance date can not be less than employee's joining date"))
def validate_employee(self):
emp = frappe.db.sql("select name from `tabEmployee` where name = %s and status = 'Active'",

View File

@@ -42,7 +42,7 @@ class ProductionPlanningTool(Document):
select distinct so.name, so.transaction_date, so.customer, so.base_grand_total
from `tabSales Order` so, `tabSales Order Item` so_item
where so_item.parent = so.name
and so.docstatus = 1 and so.status != "Stopped"
and so.docstatus = 1 and so.status not in ("Stopped", "Closed")
and so.company = %(company)s
and so_item.qty > so_item.delivered_qty {0} {1}
and (exists (select name from `tabBOM` bom where bom.item=so_item.item_code

View File

@@ -728,7 +728,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
"sales_partner": me.frm.doc.sales_partner,
"ignore_pricing_rule": me.frm.doc.ignore_pricing_rule,
"doctype": me.frm.doc.doctype,
"name": me.frm.doc.name
"name": me.frm.doc.name,
"is_return": cint(me.frm.doc.is_return)
};
},
@@ -1047,5 +1048,4 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
return method
},
});

View File

@@ -50,7 +50,9 @@ class SalesOrder(SellingController):
# validate transaction date v/s delivery date
if self.delivery_date:
if getdate(self.transaction_date) > getdate(self.delivery_date):
frappe.throw(_("Expected Delivery Date cannot be before Sales Order Date"))
frappe.msgprint(_("Expected Delivery Date is be before Sales Order Date"),
indicator='orange',
title=_('Warning'))
def validate_po(self):
# validate p.o date v/s delivery date
@@ -81,7 +83,8 @@ class SalesOrder(SellingController):
unique_chk_list = set(check_list)
if len(unique_chk_list) != len(check_list) and \
not cint(frappe.db.get_single_value("Selling Settings", "allow_multiple_items")):
frappe.msgprint(_("Warning: Same item has been entered multiple times."))
frappe.msgprint(_("Same item has been entered multiple times"),
title=_("Warning"), indicator='orange')
def product_bundle_has_stock_item(self, product_bundle):
"""Returns true if product bundle has stock item"""
@@ -442,7 +445,7 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
target.amount = flt(source.amount) - flt(source.billed_amt)
target.base_amount = target.amount * flt(source_parent.conversion_rate)
target.qty = target.amount / flt(source.rate) if (source.rate and source.billed_amt) else source.qty
item = frappe.db.get_value("Item", target.item_code, ["item_group", "selling_cost_center"], as_dict=1)
target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center") \
or item.selling_cost_center \

View File

@@ -22,8 +22,8 @@ def get_domain(domain):
},
'Retail': {
'desktop_icons': ['POS', 'Item', 'Customer', 'Sales Invoice', 'Purchase Order', 'Warranty Claim',
'Accounts', 'Buying', 'ToDo'],
'desktop_icons': ['POS', 'Item', 'Customer', 'Sales Invoice', 'Purchase Order',
'Warranty Claim', 'Accounts', 'Task', 'Buying', 'ToDo'],
'remove_roles': ['Manufacturing User', 'Manufacturing Manager', 'Academics User'],
'properties': [
{'doctype': 'Item', 'fieldname': 'manufacturing', 'property': 'hidden', 'value': 1},
@@ -36,7 +36,7 @@ def get_domain(domain):
},
'Distribution': {
'desktop_icons': ['Item', 'Customer', 'Supplier', 'Lead', 'Sales Order',
'desktop_icons': ['Item', 'Customer', 'Supplier', 'Lead', 'Sales Order', 'Task',
'Sales Invoice', 'CRM', 'Selling', 'Buying', 'Stock', 'Accounts', 'HR', 'ToDo'],
'remove_roles': ['Manufacturing User', 'Manufacturing Manager', 'Academics User'],
'set_value': [
@@ -46,8 +46,8 @@ def get_domain(domain):
},
'Services': {
'desktop_icons': ['Project', 'Timesheet', 'Customer', 'Sales Order', 'Sales Invoice', 'Lead', 'Opportunity',
'Expense Claim', 'Employee', 'HR', 'ToDo'],
'desktop_icons': ['Project', 'Timesheet', 'Customer', 'Sales Order', 'Sales Invoice',
'Lead', 'Opportunity', 'Task', 'Expense Claim', 'Employee', 'HR', 'ToDo'],
'remove_roles': ['Manufacturing User', 'Manufacturing Manager', 'Academics User'],
'properties': [
{'doctype': 'Item', 'fieldname': 'is_stock_item', 'property': 'default', 'value': 0},
@@ -59,10 +59,10 @@ def get_domain(domain):
},
'Education': {
'desktop_icons': ['Student', 'Program', 'Course', 'Student Group', 'Instructor',
'Fees', 'ToDo', 'Schools'],
'Fees', 'Task', 'ToDo', 'Schools'],
'allow_roles': ['Academics User', 'Accounts User', 'Accounts Manager', 'Item Manager',
'Website Manager', 'HR User', 'HR Manager', 'Purchase User', 'Purchase Manager',
'Student'],
'Student', 'Projects User'],
'default_portal_role': 'Student'
},
}

View File

@@ -6,9 +6,11 @@ from __future__ import unicode_literals
import frappe
from frappe.utils.make_random import add_random_children
import frappe.utils
import random
import random, os, json
from frappe import _
from markdown2 import markdown
def make_sample_data():
def make_sample_data(args):
"""Create a few opportunities, quotes, material requests, issues, todos, projects
to help the user get started"""
items = frappe.get_all("Item", {'is_sales_item': 1})
@@ -22,7 +24,8 @@ def make_sample_data():
make_opportunity(items, customer)
make_quote(items, customer)
make_projects()
make_projects(args.get('domain'))
import_email_alert()
if items and warehouses:
make_material_request(frappe.get_all("Item"))
@@ -84,42 +87,91 @@ def make_material_request(items):
def make_issue():
pass
def make_projects():
def make_projects(domain):
current_date = frappe.utils.nowdate()
project = frappe.get_doc({
"doctype": "Project",
"project_name": "ERPNext Implementation",
})
current_date = frappe.utils.nowdate()
project.set("tasks", [
tasks = [
{
"title": "Explore ERPNext",
"start_date": current_date,
"end_date": current_date,
"file": "explore.md"
}]
if domain == 'Education':
tasks += [
{
"title": "Explore ERPNext",
"start_date": frappe.utils.add_days(current_date, 1),
"end_date": frappe.utils.add_days(current_date, 2)
"title": _("Setup your School in ERPNext"),
"start_date": current_date,
"end_date": frappe.utils.add_days(current_date, 1),
"file": "school_masters.md"
},
{
"title": "Run Sales Cycle",
"start_date": frappe.utils.add_days(current_date, 2),
"end_date": frappe.utils.add_days(current_date, 3)
"title": "Setup Master Data",
"start_date": current_date,
"end_date": frappe.utils.add_days(current_date, 1),
"file": "school_masters.md"
}]
else:
tasks += [
{
"title": "Setup Your Company",
"start_date": current_date,
"end_date": frappe.utils.add_days(current_date, 1),
"file": "masters.md"
},
{
"title": "Run Billing Cycle",
"start_date": frappe.utils.add_days(current_date, 3),
"end_date": frappe.utils.add_days(current_date, 4)
"title": "Start Tracking your Sales",
"start_date": current_date,
"end_date": frappe.utils.add_days(current_date, 2),
"file": "sales.md"
},
{
"title": "Run Purchase Cycle",
"start_date": frappe.utils.add_days(current_date, 4),
"end_date": frappe.utils.add_days(current_date, 5)
"title": "Start Managing Purchases",
"start_date": current_date,
"end_date": frappe.utils.add_days(current_date, 3),
"file": "purchase.md"
},
{
"title": "Import Data",
"start_date": frappe.utils.add_days(current_date, 5),
"end_date": frappe.utils.add_days(current_date, 6)
"start_date": current_date,
"end_date": frappe.utils.add_days(current_date, 4),
"file": "import_data.md"
},
{
"title": "Go Live!",
"start_date": frappe.utils.add_days(current_date, 6),
"end_date": frappe.utils.add_days(current_date, 7)
}])
"start_date": current_date,
"end_date": frappe.utils.add_days(current_date, 5),
"file": "go_live.md"
}]
for t in tasks:
with open (os.path.join(os.path.dirname(__file__), "tasks", t['file'])) as f:
t['description'] = markdown(f.read())
del t['file']
project.append('tasks', t)
project.insert(ignore_permissions=True)
def import_email_alert():
'''Import email alert for task start'''
with open (os.path.join(os.path.dirname(__file__), "tasks/task_alert.json")) as f:
email_alert = frappe.get_doc(json.loads(f.read())[0])
email_alert.insert()
# trigger the first message!
from frappe.email.doctype.email_alert.email_alert import trigger_daily_alerts
trigger_daily_alerts()
def test_sample():
frappe.db.sql('delete from `tabEmail Alert`')
frappe.db.sql('delete from tabProject')
frappe.db.sql('delete from tabTask')
make_projects('Education')
import_email_alert()

View File

@@ -60,7 +60,7 @@ def setup_complete(args=None):
if args.get("add_sample_data"):
try:
make_sample_data()
make_sample_data(args)
frappe.clear_cache()
except:
# clear message

View File

@@ -0,0 +1,7 @@
Thanks for checking this out! ❤️
If you are evaluating an ERP system for the first time, this is going to be quite a task! But don't worry, ERPNext is awesome.
First, get familiar with the surroundings. ERPNext covers a *lot of features*, go to the home page and click on the "Explore" icon.
All the best!

View File

@@ -0,0 +1,18 @@
Ready to go live with ERPNext? 🏁🏁🏁
Here are the steps:
1. Sync up your **Chart of Accounts**
3. Add your opening stock using **Stock Reconciliation**
4. Add your open invoices (both sales and purchase)
3. Add your opening account balances by making a **Journal Entry**
If you need help for going live, sign up for an account at erpnext.com or find a partner to help you with this.
Or you can watch these videos 📺:
Setup your chart of accounts: https://www.youtube.com/watch?v=AcfMCT7wLLo
Add Open Stock: https://www.youtube.com/watch?v=nlHX0ZZ84Lw
Add Opening Balances: https://www.youtube.com/watch?v=nlHX0ZZ84Lw

View File

@@ -0,0 +1,5 @@
Lets import some data! 💪💪
If you are already running a business, you most likely have your Items, Customers or Suppliers in some spreadsheet file somewhere, import it into ERPNext with the Data Import Tool.
Watch this video to get started: https://www.youtube.com/watch?v=Ta2Xx3QoK3E

View File

@@ -0,0 +1,7 @@
Start building a model of your business in ERPNext by adding your Items and Customers.
These videos 📺 will help you get started:
Adding Customers and Suppliers: https://www.youtube.com/watch?v=zsrrVDk6VBs
Adding Items and Prices: https://www.youtube.com/watch?v=FcOsV-e8ymE

View File

@@ -0,0 +1,10 @@
How to manage your purchasing in ERPNext 🛒🛒🛒:
1. Add a few **Suppliers**
2. Find out what you need by making **Material Requests**.
3. Now start placing orders via **Purchase Order**.
4. When your suppliers deliver, make **Purchase Receipts**
Now never run out of stock again! 😎
Watch this video 📺 to get an overview: https://www.youtube.com/watch?v=4TN9kPyfIqM

View File

@@ -0,0 +1,8 @@
Start managing your sales with ERPNext 🔔🔔🔔:
1. Add potential business contacts as **Leads**
2. Udpate your deals in pipeline in **Opportunities**
3. Send proposals to your leads or customers with **Quotations**
4. Track confirmed orders with **Sales Orders**
Watch this video 📺 to get an overview: https://www.youtube.com/watch?v=o9XCSZHJfpA

View File

@@ -0,0 +1,5 @@
Lets import some data! 💪💪
If you are already running a school, you most likely have your Students in some spreadsheet file somewhere. Import it into ERPNext with the Data Import Tool.
Watch this video to get started: https://www.youtube.com/watch?v=Ta2Xx3QoK3E

View File

@@ -0,0 +1,9 @@
Lets start making things in ERPNext that are representative of your institution.
1. Make a list of **Programs** that you offer
1. Add a few **Courses** that your programs cover
1. Create **Academic Terms** and **Academic Years**
1. Start adding **Students**
1. Group your students into **Batches**
Watch this video to learn more about ERPNext Schools: https://www.youtube.com/watch?v=f6foQOyGzdA

View File

@@ -0,0 +1,28 @@
[
{
"attach_print": 0,
"condition": "doc.status in ('Open', 'Overdue')",
"date_changed": "exp_end_date",
"days_in_advance": 0,
"docstatus": 0,
"doctype": "Email Alert",
"document_type": "Task",
"enabled": 1,
"event": "Days After",
"is_standard": 0,
"message": "<p>Task due today:</p>\n\n<div>\n{{ doc.description }}\n</div>\n\n<hr>\n<p style=\"font-size: 85%\">\nThis is a notification for a task that is due today, and a sample <b>Email Alert</b>. In ERPNext you can setup email alerts on anything, Invoices, Orders, Leads, Opportunities, so you never miss a thing.\n<br>To edit this, and setup other alerts, just type <b>Email Alert</b> in the search bar.</p>",
"method": null,
"modified": "2017-03-09 07:34:58.168370",
"module": null,
"name": "Task Due Alert",
"recipients": [
{
"cc": null,
"condition": null,
"email_by_document_field": "owner"
}
],
"subject": "{{ doc.subject }}",
"value_changed": null
}
]

View File

@@ -8,7 +8,7 @@ def get_notification_config():
{
"Issue": {"status": "Open"},
"Warranty Claim": {"status": "Open"},
"Task": {"status": "Overdue"},
"Task": {"status": ("in", ("Open", "Overdue"))},
"Project": {"status": "Open"},
"Item": {"total_projected_qty": ("<", 0)},
"Customer": {"status": "Open"},
@@ -23,11 +23,11 @@ def get_notification_config():
},
"Journal Entry": {"docstatus": 0},
"Sales Invoice": {
"outstanding_amount": (">", 0),
"docstatus": ("<", 2)
"outstanding_amount": (">", 0),
"docstatus": ("<", 2)
},
"Purchase Invoice": {
"outstanding_amount": (">", 0),
"outstanding_amount": (">", 0),
"docstatus": ("<", 2)
},
"Payment Entry": {"docstatus": 0},

View File

@@ -68,7 +68,7 @@ frappe.ui.form.on("Item", {
frm.set_intro(__("This Item is a Variant of {0} (Template). Attributes will be copied over from the template unless 'No Copy' is set", [frm.doc.variant_of]), true);
}
if (frappe.defaults.get_default("item_naming_by")!="Naming Series") {
if (frappe.defaults.get_default("item_naming_by")!="Naming Series" || frm.doc.variant_of) {
frm.toggle_display("naming_series", false);
} else {
erpnext.toggle_naming_series();

View File

@@ -162,14 +162,14 @@ class TestItem(unittest.TestCase):
variant = create_variant("_Test Numeric Template Item",
{"Test Size": "Large", "Test Item Length": 1.1})
self.assertEquals(variant.item_code, None)
self.assertEquals(variant.item_code, "_Test Numeric Template Item-L-1.1")
variant.item_code = "_Test Numeric Variant-L-1.1"
variant.item_name = "_Test Numeric Variant Large 1.1m"
self.assertRaises(InvalidItemAttributeValueError, variant.save)
variant = create_variant("_Test Numeric Template Item",
{"Test Size": "Large", "Test Item Length": 1.5})
self.assertEquals(variant.item_code, None)
self.assertEquals(variant.item_code, "_Test Numeric Template Item-L-1.5")
variant.item_code = "_Test Numeric Variant-L-1.5"
variant.item_name = "_Test Numeric Variant Large 1.5m"
variant.save()