Compare commits

...

80 Commits

Author SHA1 Message Date
Ameya Shenoy
29fe8ce114 Merge branch 'staging-fixes' into staging 2018-10-05 09:09:53 +00:00
Ameya Shenoy
538678afc4 bumped to version 11.0.3-beta.5 2018-10-05 09:09:53 +00:00
Ameya Shenoy
ad908779be Merge branch 'master' into staging-fixes 2018-10-05 08:54:58 +00:00
Ameya Shenoy
5eafa5a487 Merge branch 'hotfix' 2018-10-05 08:54:46 +00:00
Ameya Shenoy
97dbb4d125 bumped to version 10.1.56 2018-10-05 08:54:46 +00:00
Shreya Shah
5cff01634e Merge pull request #15593 from Zlash65/fix-mod
[Minor] Item master - get_query for deferred accounts
2018-10-05 14:14:46 +05:30
Shreya Shah
32206029ac Fix Codacy 2018-10-05 14:14:33 +05:30
Shreya Shah
deb9f0e03c Merge pull request #15594 from shreyashah115/tds-report
Handle IndexError if no data found
2018-10-05 14:11:43 +05:30
Shreya Shah
db5ffce742 Merge pull request #15592 from shreyashah115/jv
Allow Reverse JV for all submitted docs
2018-10-05 13:33:11 +05:30
Shreya
0d7bd43367 Handle IndexError if no data found 2018-10-05 13:22:09 +05:30
Zlash65
2123b97d31 add get_query for revenue and expense account 2018-10-05 12:26:32 +05:30
Shreya
4f5214a136 Allow reverse jv for all submitted docs 2018-10-05 12:19:09 +05:30
Saif
00a16a9337 set_item_default was referencing a variable company of "company" (#15576) 2018-10-05 11:54:03 +05:30
Shreya Shah
17ac38ff29 Enable save before saving to update form after save (#15579) 2018-10-05 11:51:13 +05:30
Jamsheer
be6e426fe0 Healthcare Service Unit - added company abbr as suffix (#15590) 2018-10-05 11:38:15 +05:30
Ranjith Kurungadam
dc2bab2b72 fix healthcare patch (#15584) 2018-10-05 11:36:58 +05:30
Valmik
4c61861163 Add Delivery Trip to Delivery Note dashboard (#15587) 2018-10-05 11:36:31 +05:30
Saif
4faea037bb Remove Test Letter Head from GSTR-1 (#15591) 2018-10-05 11:35:01 +05:30
Ameya Shenoy
c4ebbd1322 Merge branch 'staging-fixes' into staging 2018-10-04 13:14:29 +00:00
Ameya Shenoy
2291558c5f bumped to version 11.0.3-beta.4 2018-10-04 13:14:29 +00:00
rohitwaghchaure
d69dc954c7 Merge pull request #15580 from sagarvora/fix-TabError
fix TabError in install_fixtures.py
2018-10-04 17:22:44 +05:30
Ameya Shenoy
c6eac7c60b Merge branch 'staging-fixes' into staging 2018-10-04 11:42:56 +00:00
Ameya Shenoy
5ae344593e bumped to version 11.0.3-beta.3 2018-10-04 11:42:56 +00:00
Ameya Shenoy
6dc4cdca3a Merge pull request #15585 from rohitwaghchaure/fix_asset_depreciation_ledger_report
Fix issue after merging hotfix into staging-fixes
2018-10-04 16:47:43 +05:30
Rohit Waghchaure
18678696db Fix issue after merging hotfix into staging-fixes 2018-10-04 16:33:43 +05:30
Ameya Shenoy
7d929c508f Merge branch 'master' into staging-fixes 2018-10-04 09:25:07 +00:00
Ameya Shenoy
65652071ff Merge branch 'hotfix' 2018-10-04 09:11:50 +00:00
Ameya Shenoy
79dc8ac9cc bumped to version 10.1.55 2018-10-04 09:11:50 +00:00
rohitwaghchaure
8b42bf57cd Merge pull request #15581 from rohitwaghchaure/work_order_item_has_no
[Fix] WorkOrderItem object has no attribute operation
2018-10-04 13:27:00 +05:30
Rohit Waghchaure
9f2859701e [Fix] WorkOrderItem object has no attribute operation 2018-10-04 13:25:49 +05:30
Sagar Vora
b13b9b4ed3 fix TabError in install_fixtures.py 2018-10-04 11:39:20 +05:30
Zarrar
897d1baf74 Merge pull request #15577 from Zlash65/min-min
[Minor] Purchase Invoice - stop date editable after submit
2018-10-04 09:31:50 +05:30
Zlash65
6e3b1a58a1 service_stop_date should be editable after submit 2018-10-04 09:30:27 +05:30
rohitwaghchaure
f9930ff2a4 Merge pull request #15573 from rohitwaghchaure/cost_center_issue_while_saving
[Fix] Cost center issue
2018-10-03 18:47:28 +05:30
Shreya Shah
3204c94fdd Merge pull request #15570 from shreyashah115/fix-filter-error
[Bug] Item wise sales register filters
2018-10-03 17:38:41 +05:30
Shreya
cbb112f2db Fix filter error 2018-10-03 17:37:40 +05:30
rohitwaghchaure
15e7646edd Merge pull request #15569 from rohitwaghchaure/stock_adjustment_to_cost_of_goods_sold
Book cost of goods sold instead of stock adjustment
2018-10-03 17:36:29 +05:30
Rohit Waghchaure
8bf9f377dd [Fix] Cost center issue 2018-10-03 16:59:43 +05:30
Rohit Waghchaure
d1b87ba41c Book cost of goods sold instead of stock adjustment 2018-10-03 16:29:43 +05:30
rohitwaghchaure
d6cacbe565 Merge pull request #15567 from rohitwaghchaure/fix_payment_request
[Fix] Payment request not working
2018-10-03 16:03:48 +05:30
Rohit Waghchaure
210f4984f7 [Fix] Payment request not working 2018-10-03 15:55:51 +05:30
Charles-Henri Decultot
75fa6b3ee8 [Enhancement] Improvement to the sales pipeline (#15524)
* Additions to sales pipeline

* Codacy corrections

* Codacy corrections

* Codacy corrections

* Replace _ with dummy for unused variable

* Performance + dates corrections

* Itertuples modification

* Removing trailing whitespaces

* Sales stage doctype

* Divide sales stages fixtures in separate functions

* Remove duplicate fixtures

* Add newline after method

* Missing requirement
2018-10-03 10:41:40 +05:30
Charles-Henri Decultot
efd776da46 Events in timeline (#15485)
* Events in timeline

* Namespace correction

* Codacy correction

* Addition of sales partners in participants

* Correct json indent
2018-10-03 10:41:26 +05:30
rohitwaghchaure
a5576f5b21 [Fix] Stock difference between gl entry and stock ledger entry booked in stock adjustment (#15374) 2018-10-03 10:39:50 +05:30
deepeshgarg007
719701f2a4 Enhancement in Budget Variance and other reports (#15455)
* Enhanced Budget Variance report and added filters and columns in other reports

* Update budget_variance_report.js

* Changes in budget variance report

* Spacing in column names
2018-10-02 12:52:13 +05:30
Shreya Shah
7d115183e4 Improvise and fix indicators in Portal list (#15552) 2018-10-02 12:46:26 +05:30
Charles-Henri Decultot
3b11debcd2 Gocardless correction (#15554) 2018-10-02 12:46:15 +05:30
Charles-Henri Decultot
b2281cc1fd Lead to customer UX enhancement (#15525)
* Lead to customer UX enhancement

* Market segment

* Market Segment to DocType

* Specific function for fixtures

* Merge issue correction

* Doctype merge correction
2018-10-02 11:25:00 +05:30
Shreya Shah
5a2aced586 Merge pull request #15551 from Zlash65/minor-fix
[Minor] Delivery trip test fix
2018-10-02 11:12:51 +05:30
Rushabh Mehta
11e2119670 style(icon): revert to old icon 2018-10-02 11:06:55 +05:30
Zlash65
6a5e6ed2ff delivery trip notification to customer fix 2018-10-01 17:28:42 +05:30
Zlash65
9e67b8ec4d fix driver name selection 2018-10-01 17:27:12 +05:30
Zlash65
622bd10946 add date data [mandatory] 2018-10-01 15:37:31 +05:30
rohitwaghchaure
8976ad5ca1 Merge pull request #15523 from rohitwaghchaure/fix_attendance_tool_issue
[Fix] Attendance tool
2018-10-01 15:07:49 +05:30
Rohit Waghchaure
c7f8b82fff [Fix] Attendance tool 2018-10-01 12:30:58 +05:30
rohitwaghchaure
6b62b86bbf Merge pull request #15545 from rohitwaghchaure/salary_slip_not_creating_because_of_the_date_issue
[Fix] Salary slip
2018-10-01 12:03:26 +05:30
Rohit Waghchaure
8fbf856618 [Fix] Salary slip 2018-10-01 12:00:45 +05:30
Saif
90cf2ddc01 Make pricing rule from Supplier and Customer Doc (#15533)
* Make pricing rule from Supplier and Customer Doc

* Make sure the "+" button also works the same way as the "Make" button
2018-09-30 22:16:31 +05:30
Alchez
6ecb2556b7 Add Delivery Settings + improve 'Notify Customers' functionality (#15322)
* Add Delivery Settings + improve 'Notify Customers' functionality

* Minor improvements

* Add patch to create a default dispatch notification template

* Fix travis errors
2018-09-30 21:38:47 +05:30
Charles-Henri Decultot
4fd7a4e0d7 Lead notes (#15510)
* Notes field in Lead

* Add notes to lead details report
2018-09-30 21:20:55 +05:30
Zarrar
e4c9ac3961 [Minor] Cash Flow report - custom (#15522)
* python 2-3 fix for filter

* pass filters while fetching data to financial statement report
2018-09-30 21:19:01 +05:30
rohitwaghchaure
90f9f9d3d8 Code optimization for deferred revenue (#15527) 2018-09-30 21:12:50 +05:30
Faris Ansari
6575e52942 fix: Refactor Review Area according to new Text Editor (#15536)
- depends on https://github.com/frappe/frappe/pull/6159
2018-09-30 21:08:46 +05:30
rohitwaghchaure
1cf71d96b1 Merge pull request #15530 from rohitwaghchaure/consolidated_report_issue_v11
[Fix] Consolidated Financial Statement report
2018-09-28 17:06:57 +05:30
Rohit Waghchaure
ea0ef95539 [Fix] Consolidated Financial Statement report 2018-09-28 17:05:55 +05:30
Saif
c2dd9ab778 Fix the problem that naming series would remove trailing '-' from series prefix if ##### was not entered (#15514) 2018-09-27 15:48:04 +05:30
Shreya Shah
0fc4917d81 Merge pull request #15516 from shreyashah115/product-page
Fetch Item Group's name and image on website
2018-09-27 15:12:42 +05:30
Shreya
5c335550e3 Fetch item_group's name and image on website if children 2018-09-27 13:55:59 +05:30
Nabin Hait
7d6d678e8d purchase receipt return entry in dashboard 2018-09-26 19:04:11 +05:30
Nabin Hait
c22ba2ec26 fix(sales return): validation message fix 2018-09-26 18:56:45 +05:30
Nabin Hait
183972f58f fix(stock_entry): allow creating stock entry against work order even if item rate is zero 2018-09-26 18:34:07 +05:30
Nabin Hait
1e7c32b909 Payroll fixes and more (#15475)
* fix(payroll): multiple minor fixes related to salary structure

* Added GSTR-1 and GSTR-2 report in Accounts module page

* delete asset movement records on cancellation of Purchase Receipt

* Update consolidated_financial_statement.py

* minor fix

* minor fix

* add filters on item prices report (#15495)
2018-09-26 18:01:00 +05:30
deepeshgarg007
c3772f1ac4 minor fix (#15503) 2018-09-26 15:55:43 +05:30
Aditya Hase
e20b7cc47d fix(python3): super() backwards compatibility fix (#15498) 2018-09-26 15:39:02 +05:30
Shreya Shah
352e6494f3 Contact and email fields in Payment Entry (#15490)
* Add contact_person and contact_email fields to Payment Entry

* Minor fix

* Map contact details while making Payment Entry

* Update payment_entry.py
2018-09-26 15:38:34 +05:30
rohitwaghchaure
0cf0ebf08b [Refactored] Asset Depreciation Ledger report based on GL entries (#15415)
* [Refactored] Asset Depreciation Ledger report is based on GL entries

* Provision to make manual JV from the asset if Calculate Depreciation is disabled
2018-09-26 15:24:49 +05:30
Ameya Shenoy
a7ae06eadb Merge branch 'staging-fixes' into staging 2018-09-26 08:52:54 +00:00
Ameya Shenoy
90197dd341 bumped to version 11.0.3-beta.2 2018-09-26 08:52:54 +00:00
Ameya Shenoy
41d1982b90 Merge pull request #15501 from codingCoffee/qwe
fix(multiple): syntax and patch
2018-09-26 14:12:01 +05:30
Ameya Shenoy
12ec142a69 fix(multiple): syntax and patch
- syntax fix for using super class
- check "All Departments" in department name with translations
2018-09-26 14:05:48 +05:30
116 changed files with 11800 additions and 10079 deletions

View File

@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '10.1.54'
__version__ = '10.1.56'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -35,8 +35,8 @@ def validate_service_stop_date(doc):
def convert_deferred_expense_to_expense(start_date=None, end_date=None):
# check for the purchase invoice for which GL entries has to be done
invoices = frappe.db.sql_list('''
select parent from `tabPurchase Invoice Item` where service_start_date<=%s and service_end_date>=%s
and enable_deferred_expense = 1 and docstatus = 1
select distinct parent from `tabPurchase Invoice Item` where service_start_date<=%s and service_end_date>=%s
and enable_deferred_expense = 1 and docstatus = 1 and ifnull(amount, 0) > 0
''', (end_date or today(), start_date or add_months(today(), -1)))
# For each invoice, book deferred expense
@@ -47,8 +47,8 @@ def convert_deferred_expense_to_expense(start_date=None, end_date=None):
def convert_deferred_revenue_to_income(start_date=None, end_date=None):
# check for the sales invoice for which GL entries has to be done
invoices = frappe.db.sql_list('''
select parent from `tabSales Invoice Item` where service_start_date<=%s and service_end_date>=%s
and enable_deferred_revenue = 1 and docstatus = 1
select distinct parent from `tabSales Invoice Item` where service_start_date<=%s and service_end_date>=%s
and enable_deferred_revenue = 1 and docstatus = 1 and ifnull(amount, 0) > 0
''', (end_date or today(), start_date or add_months(today(), -1)))
# For each invoice, book deferred revenue

View File

@@ -16,7 +16,7 @@ class Account(NestedSet):
if frappe.local.flags.ignore_on_update:
return
else:
super().on_update()
super(Account, self).on_update()
def onload(self):
frozen_accounts_modifier = frappe.db.get_value("Accounts Settings", "Accounts Settings",

View File

@@ -58,7 +58,6 @@ class CostCenter(NestedSet):
# Validate properties before merging
super(CostCenter, self).before_rename(olddn, new_cost_center, merge, "is_group")
if not merge:
from erpnext.accounts.doctype.account.account import get_name_with_number
new_cost_center = get_name_with_number(new_cost_center, self.cost_center_number)
return new_cost_center
@@ -89,3 +88,8 @@ class CostCenter(NestedSet):
def on_doctype_update():
frappe.db.add_index("Cost Center", ["lft", "rgt"])
def get_name_with_number(new_account, account_number):
if account_number and not new_account[0].isdigit():
new_account = account_number + " - " + new_account
return new_account

View File

@@ -24,7 +24,7 @@ frappe.ui.form.on("Journal Entry", {
}, "fa fa-table");
}
if(frm.doc.docstatus==1 && frm.doc.naming_series=="JV-") {
if(frm.doc.docstatus==1) {
frm.add_custom_button(__('Reverse Journal Entry'), function() {
return erpnext.journal_entry.reverse_journal_entry(frm);
});

View File

@@ -23,7 +23,6 @@ frappe.ui.form.on('Payment Entry', {
}
}
});
frm.set_query("party_type", function() {
return{
"filters": {
@@ -31,7 +30,17 @@ frappe.ui.form.on('Payment Entry', {
}
}
});
frm.set_query("contact_person", function() {
if (frm.doc.party) {
return {
query: 'frappe.contacts.doctype.contact.contact.contact_query',
filters: {
link_doctype: frm.doc.party_type,
link_name: frm.doc.party
}
};
}
});
frm.set_query("paid_to", function() {
var account_types = in_list(["Receive", "Internal Transfer"], frm.doc.payment_type) ?
["Bank", "Cash"] : [frappe.boot.party_account_types[frm.doc.party_type]];
@@ -114,6 +123,11 @@ frappe.ui.form.on('Payment Entry', {
frm.events.set_dynamic_labels(frm);
},
contact_person: function(frm) {
frm.set_value("contact_email", "");
erpnext.utils.get_contact_details(frm);
},
hide_unhide_fields: function(frm) {
var company_currency = frm.doc.company? frappe.get_doc(":Company", frm.doc.company).default_currency: "";
@@ -146,7 +160,7 @@ frappe.ui.form.on('Payment Entry', {
frm.toggle_display("set_exchange_gain_loss",
(frm.doc.paid_amount && frm.doc.received_amount && frm.doc.difference_amount &&
((frm.doc.paid_from_account_currency != company_currency ||
frm.doc.paid_to_account_currency != company_currency) &&
frm.doc.paid_to_account_currency != company_currency) &&
frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency)));
frm.refresh_fields();
@@ -208,7 +222,7 @@ frappe.ui.form.on('Payment Entry', {
});
} else {
if(frm.doc.party) {
frm.events.party(frm);
frm.events.party(frm);
}
if(frm.doc.mode_of_payment) {
@@ -230,13 +244,16 @@ frappe.ui.form.on('Payment Entry', {
},
party: function(frm) {
if (frm.doc.contact_email || frm.doc.contact_person) {
frm.set_value("contact_email", "");
frm.set_value("contact_person", "");
}
if(frm.doc.payment_type && frm.doc.party_type && frm.doc.party) {
if(!frm.doc.posting_date) {
frappe.msgprint(__("Please select Posting Date before selecting Party"))
frm.set_value("party", "");
return ;
}
frm.set_party_account_based_on_party = true;
return frappe.call({
@@ -302,7 +319,7 @@ frappe.ui.form.on('Payment Entry', {
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
}
frm.set_value("received_amount", frm.doc.paid_amount);
} else {
frm.events.received_amount(frm);
}
@@ -350,7 +367,7 @@ frappe.ui.form.on('Payment Entry', {
]);
}
}
});
});
}
},
@@ -402,7 +419,7 @@ frappe.ui.form.on('Payment Entry', {
}
})
},
posting_date: function(frm) {
frm.events.paid_from_account_currency(frm);
},
@@ -415,7 +432,7 @@ frappe.ui.form.on('Payment Entry', {
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
}
frm.events.set_unallocated_amount(frm);
}
@@ -425,17 +442,17 @@ frappe.ui.form.on('Payment Entry', {
target_exchange_rate: function(frm) {
frm.set_paid_amount_based_on_received_amount = true;
if (frm.doc.received_amount) {
frm.set_value("base_received_amount",
flt(frm.doc.received_amount) * flt(frm.doc.target_exchange_rate));
if(!frm.doc.source_exchange_rate &&
if(!frm.doc.source_exchange_rate &&
(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) {
frm.set_value("source_exchange_rate", frm.doc.target_exchange_rate);
frm.set_value("base_paid_amount", frm.doc.base_received_amount);
}
frm.events.set_unallocated_amount(frm);
}
frm.set_paid_amount_based_on_received_amount = false;
@@ -468,14 +485,14 @@ frappe.ui.form.on('Payment Entry', {
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
else
frm.events.set_unallocated_amount(frm);
frm.set_paid_amount_based_on_received_amount = false;
},
reset_received_amount: function(frm) {
if(!frm.set_paid_amount_based_on_received_amount &&
(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) {
frm.set_value("received_amount", frm.doc.paid_amount);
if(frm.doc.source_exchange_rate) {
@@ -483,7 +500,7 @@ frappe.ui.form.on('Payment Entry', {
}
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
}
if(frm.doc.payment_type == "Receive")
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.paid_amount);
else
@@ -549,7 +566,7 @@ frappe.ui.form.on('Payment Entry', {
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Customer") ||
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Supplier") ||
(frm.doc.payment_type=="Pay" && frm.doc.party_type=="Employee") ||
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student")
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student")
) {
if(total_positive_outstanding > total_negative_outstanding)
frm.set_value("paid_amount",
@@ -694,7 +711,7 @@ frappe.ui.form.on('Payment Entry', {
frm.set_value("unallocated_amount", unallocated_amount);
frm.trigger("set_difference_amount");
},
set_difference_amount: function(frm) {
var difference_amount = 0;
var base_unallocated_amount = flt(frm.doc.unallocated_amount) *
@@ -753,7 +770,7 @@ frappe.ui.form.on('Payment Entry', {
frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Purchase Order, Purchase Invoice or Journal Entry", [row.idx]));
return false;
}
if(frm.doc.party_type=="Employee" &&
!in_list(["Expense Claim", "Journal Entry"], row.reference_doctype)
) {

View File

@@ -376,6 +376,40 @@
"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": "party",
"fieldname": "contact_person",
"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": "Contact",
"length": 0,
"no_copy": 0,
"options": "Contact",
"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,
@@ -441,6 +475,40 @@
"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": "contact_person",
"fieldname": "contact_email",
"fieldtype": "Data",
"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,
"options": "Email",
"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,
@@ -1972,7 +2040,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-09-11 15:44:28.647566",
"modified": "2018-09-25 14:38:48.312629",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",

View File

@@ -299,12 +299,12 @@ class PaymentEntry(AccountsController):
if self.payment_type == "Receive" \
and self.base_total_allocated_amount < self.base_received_amount + total_deductions \
and self.total_allocated_amount < self.paid_amount + (total_deductions / self.source_exchange_rate):
self.unallocated_amount = (self.base_received_amount + total_deductions -
self.unallocated_amount = (self.base_received_amount + total_deductions -
self.base_total_allocated_amount) / self.source_exchange_rate
elif self.payment_type == "Pay" \
and self.base_total_allocated_amount < (self.base_paid_amount - total_deductions) \
and self.total_allocated_amount < self.received_amount + (total_deductions / self.target_exchange_rate):
self.unallocated_amount = (self.base_paid_amount - (total_deductions +
self.unallocated_amount = (self.base_paid_amount - (total_deductions +
self.base_total_allocated_amount)) / self.target_exchange_rate
def set_difference_amount(self):
@@ -790,7 +790,6 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
@frappe.whitelist()
def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=None):
doc = frappe.get_doc(dt, dn)
if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) > 0:
frappe.throw(_("Can only make payment against unbilled {0}").format(dt))
@@ -877,7 +876,8 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
pe.mode_of_payment = doc.get("mode_of_payment")
pe.party_type = party_type
pe.party = doc.get(scrub(party_type))
pe.contact_person = doc.get("contact_person")
pe.contact_email = doc.get("contact_email")
pe.ensure_supplier_is_not_blocked()
pe.paid_from = party_account if payment_type=="Receive" else bank.account

View File

@@ -116,6 +116,18 @@ frappe.ui.form.on('Pricing Rule', {
};
},
onload: function(frm) {
if(frm.doc.__islocal && !frm.doc.applicable_for && (frm.doc.customer || frm.doc.supplier)) {
if(frm.doc.customer) {
frm.doc.applicable_for = "Customer";
frm.doc.selling = 1
} else {
frm.doc.applicable_for = "Supplier";
frm.doc.buying = 1
}
}
},
refresh: function(frm) {
var help_content =
`<table class="table table-bordered" style="background-color: #f9f9f9;">

View File

@@ -384,3 +384,13 @@ def set_transaction_type(args):
args.transaction_type = "selling"
else:
args.transaction_type = "buying"
@frappe.whitelist()
def make_pricing_rule(doctype, docname):
doc = frappe.new_doc("Pricing Rule")
doc.applicable_for = doctype
doc.set(frappe.scrub(doctype), docname)
doc.selling = 1 if doctype == "Customer" else 0
doc.buying = 1 if doctype == "Supplier" else 0
return doc

View File

@@ -77,8 +77,9 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
}
if (doc.outstanding_amount > 0 && !cint(doc.is_return)) {
cur_frm.add_custom_button(__('Payment Request'),
this.make_payment_request, __("Make"));
cur_frm.add_custom_button(__('Payment Request'), function() {
me.make_payment_request()
}, __("Make"));
}
if(doc.docstatus===0) {

View File

@@ -403,16 +403,20 @@ class PurchaseInvoice(BuyingController):
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
warehouse_account = get_warehouse_account_map()
voucher_wise_stock_value = {}
if self.update_stock:
for d in frappe.get_all('Stock Ledger Entry',
fields = ["voucher_detail_no", "stock_value_difference"], filters={'voucher_no': self.name}):
voucher_wise_stock_value.setdefault(d.voucher_detail_no, d.stock_value_difference)
for item in self.get("items"):
if flt(item.base_net_amount):
account_currency = get_account_currency(item.expense_account)
if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items:
val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
# warehouse account
warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision)
* flt(item.qty) * flt(item.conversion_factor), item.precision("base_net_amount"))
warehouse_debit_amount = self.make_stock_adjustment_entry(gl_entries,
item, voucher_wise_stock_value, account_currency)
gl_entries.append(
self.get_gl_dict({
@@ -552,6 +556,36 @@ class PurchaseInvoice(BuyingController):
return gl_entries
def make_stock_adjustment_entry(self, gl_entries, item, voucher_wise_stock_value, account_currency):
net_amt_precision = item.precision("base_net_amount")
val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision)
* flt(item.qty) * flt(item.conversion_factor), net_amt_precision)
# Stock ledger value is not matching with the warehouse amount
if (self.update_stock and voucher_wise_stock_value.get(item.name) and
warehouse_debit_amount != flt(voucher_wise_stock_value.get(item.name), net_amt_precision)):
cost_of_goods_sold_account = self.get_company_default("default_expense_account")
stock_amount = flt(voucher_wise_stock_value.get(item.name), net_amt_precision)
stock_adjustment_amt = warehouse_debit_amount - stock_amount
gl_entries.append(
self.get_gl_dict({
"account": cost_of_goods_sold_account,
"against": item.expense_account,
"debit": stock_adjustment_amt,
"remarks": self.get("remarks") or _("Stock Adjustment"),
"cost_center": item.cost_center,
"project": item.project
}, account_currency)
)
warehouse_debit_amount = stock_amount
return warehouse_debit_amount
def make_tax_gl_entries(self, gl_entries):
# tax table gl entries
valuation_tax = {}

View File

@@ -1742,7 +1742,7 @@
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
@@ -2544,7 +2544,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-09-04 10:11:28.246395",
"modified": "2018-10-04 09:05:43.166721",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -35,6 +35,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
},
refresh: function(doc, dt, dn) {
const me = this;
this._super();
if(cur_frm.msgbox && cur_frm.msgbox.$wrapper.is(":visible")) {
// hide new msgbox
@@ -82,9 +83,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
}
if(doc.outstanding_amount>0 && !cint(doc.is_return)) {
cur_frm.add_custom_button(__('Payment Request'),
this.make_payment_request, __("Make"));
if (doc.outstanding_amount>0 && !cint(doc.is_return)) {
cur_frm.add_custom_button(__('Payment Request'), function() {
me.make_payment_request();
}, __("Make"));
}
if(!doc.auto_repeat) {
@@ -102,7 +104,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
this.set_default_print_format();
var me = this;
if (doc.docstatus == 1 && !doc.inter_company_invoice_reference) {
frappe.model.with_doc("Customer", me.frm.doc.customer, function() {
var customer = frappe.model.get_doc("Customer", me.frm.doc.customer);

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe, erpnext
import frappe.defaults
from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr
from frappe.utils import cint, flt, add_months, today, date_diff, getdate, add_days, cstr, nowdate
from frappe import _, msgprint, throw
from erpnext.accounts.party import get_party_account, get_due_date
from erpnext.controllers.stock_controller import update_gl_entries_after
@@ -54,9 +54,18 @@ class SalesInvoice(SellingController):
def set_indicator(self):
"""Set indicator for portal"""
if self.outstanding_amount > 0:
if cint(self.is_return) == 1:
self.indicator_title = _("Return")
self.indicator_color = "darkgrey"
elif self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()):
self.indicator_color = "orange"
self.indicator_title = _("Unpaid")
elif self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()):
self.indicator_color = "red"
self.indicator_title = _("Overdue")
elif self.outstanding_amount < 0:
self.indicator_title = _("Credit Note Issued")
self.indicator_color = "darkgrey"
else:
self.indicator_color = "green"
self.indicator_title = _("Paid")

View File

@@ -3,55 +3,82 @@
from __future__ import unicode_literals
import frappe, erpnext
from frappe.utils import flt
from frappe import _
def execute(filters=None):
columns, data = get_columns(), get_data(filters)
return columns, data
def get_data(filters):
data = frappe.db.sql("""
select
a.name as asset, a.asset_category, a.status,
ds.depreciation_method, a.purchase_date, a.gross_purchase_amount,
ds.schedule_date as depreciation_date, ds.depreciation_amount,
ds.accumulated_depreciation_amount,
(a.gross_purchase_amount - ds.accumulated_depreciation_amount) as amount_after_depreciation,
ds.journal_entry as depreciation_entry
from
`tabAsset` a, `tabDepreciation Schedule` ds
where
a.name = ds.parent
and a.docstatus=1
and ifnull(ds.journal_entry, '') != ''
and ds.schedule_date between %(from_date)s and %(to_date)s
and a.company = %(company)s
{conditions}
order by
a.name asc, ds.schedule_date asc
""".format(conditions=get_filter_conditions(filters)), filters, as_dict=1)
data = []
depreciation_accounts = frappe.db.sql_list(""" select name from tabAccount
where ifnull(account_type, '') = 'Depreciation' """)
filters_data = [["company", "=", filters.get('company')],
["posting_date", ">=", filters.get('from_date')],
["posting_date", "<=", filters.get('to_date')],
["against_voucher_type", "=", "Asset"],
["account", "in", depreciation_accounts]]
if filters.get("asset"):
filters_data.append(["against_voucher", "=", filters.get("asset")])
if filters.get("asset_category"):
assets = frappe.db.sql_list("""select name from tabAsset
where asset_category = %s and docstatus=1""", filters.get("asset_category"))
filters_data.append(["against_voucher", "in", assets])
company_finance_book = erpnext.get_default_finance_book(filters.get("company"))
if (not filters.get('finance_book') or (filters.get('finance_book') == company_finance_book)):
filters_data.append(["finance_book", "in", ['', filters.get('finance_book')]])
elif filters.get("finance_book"):
filters_data.append(["finance_book", "=", filters.get('finance_book')])
gl_entries = frappe.get_all('GL Entry',
filters= filters_data,
fields = ["against_voucher", "debit_in_account_currency as debit", "voucher_no", "posting_date"],
order_by= "against_voucher, posting_date")
if not gl_entries:
return data
assets = [d.against_voucher for d in gl_entries]
assets_details = get_assets_details(assets)
for d in gl_entries:
asset_data = assets_details.get(d.against_voucher)
if not asset_data.get("accumulated_depreciation_amount"):
asset_data.accumulated_depreciation_amount = d.debit
else:
asset_data.accumulated_depreciation_amount += d.debit
row = frappe._dict(asset_data)
row.update({
"depreciation_amount": d.debit,
"depreciation_date": d.posting_date,
"amount_after_depreciation": (flt(row.gross_purchase_amount) -
flt(row.accumulated_depreciation_amount)),
"depreciation_entry": d.voucher_no
})
data.append(row)
return data
def get_filter_conditions(filters):
conditions = ""
if filters.get("asset"):
conditions += " and a.name = %(asset)s"
if filters.get("asset_category"):
conditions += " and a.asset_category = %(asset_category)s"
company_finance_book = erpnext.get_default_finance_book(filters.get("company"))
def get_assets_details(assets):
assets_details = {}
if (not filters.get('finance_book') or (filters.get('finance_book') == company_finance_book)):
filters['finance_book'] = company_finance_book
conditions += " and ifnull(ds.finance_book, '') in (%(finance_book)s, '') "
elif filters.get("finance_book"):
conditions += " and ifnull(ds.finance_book, '') = %(finance_book)s"
fields = ["name as asset", "gross_purchase_amount",
"asset_category", "status", "depreciation_method", "purchase_date"]
for d in frappe.get_all("Asset", fields = fields, filters = {'name': ('in', assets)}):
assets_details.setdefault(d.asset, d)
return assets_details
return conditions
def get_columns():
return [
{

View File

@@ -4,8 +4,16 @@
frappe.query_reports["Budget Variance Report"] = {
"filters": [
{
fieldname: "fiscal_year",
label: __("Fiscal Year"),
fieldname: "from_fiscal_year",
label: __("From Fiscal Year"),
fieldtype: "Link",
options: "Fiscal Year",
default: frappe.sys_defaults.fiscal_year,
reqd: 1
},
{
fieldname: "to_fiscal_year",
label: __("To Fiscal Year"),
fieldtype: "Link",
options: "Fiscal Year",
default: frappe.sys_defaults.fiscal_year,
@@ -21,7 +29,7 @@ frappe.query_reports["Budget Variance Report"] = {
{ "value": "Half-Yearly", "label": __("Half-Yearly") },
{ "value": "Yearly", "label": __("Yearly") }
],
default: "Monthly",
default: "Yearly",
reqd: 1
},
{
@@ -46,5 +54,11 @@ frappe.query_reports["Budget Variance Report"] = {
fieldtype: "Link",
options: "Cost Center"
},
{
fieldname:"show_cumulative",
label: __("Show Cumulative Amount"),
fieldtype: "Check",
default: 0,
},
]
}

View File

@@ -9,7 +9,7 @@ from frappe.utils import formatdate
from erpnext.controllers.trends import get_period_date_ranges, get_period_month_ranges
from six import iteritems
from pprint import pprint
def execute(filters=None):
if not filters: filters = {}
validate_filters(filters)
@@ -19,7 +19,7 @@ def execute(filters=None):
else:
cost_centers = get_cost_centers(filters)
period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"])
period_month_ranges = get_period_month_ranges(filters["period"], filters["from_fiscal_year"])
cam_map = get_cost_center_account_month_map(filters)
data = []
@@ -29,18 +29,28 @@ def execute(filters=None):
for account, monthwise_data in iteritems(cost_center_items):
row = [cost_center, account]
totals = [0, 0, 0]
for relevant_months in period_month_ranges:
period_data = [0, 0, 0]
for month in relevant_months:
month_data = monthwise_data.get(month, {})
for i, fieldname in enumerate(["target", "actual", "variance"]):
value = flt(month_data.get(fieldname))
period_data[i] += value
totals[i] += value
period_data[2] = period_data[0] - period_data[1]
row += period_data
for year in get_fiscal_years(filters):
last_total = 0
for relevant_months in period_month_ranges:
period_data = [0, 0, 0]
for month in relevant_months:
if monthwise_data.get(year[0]):
month_data = monthwise_data.get(year[0]).get(month, {})
for i, fieldname in enumerate(["target", "actual", "variance"]):
value = flt(month_data.get(fieldname))
period_data[i] += value
totals[i] += value
period_data[0] += last_total
if(filters.get("show_cumulative")):
last_total = period_data[0] - period_data[1]
period_data[2] = period_data[0] - period_data[1]
row += period_data
totals[2] = totals[0] - totals[1]
row += totals
if filters["period"] != "Yearly" :
row += totals
data.append(row)
return columns, data
@@ -50,21 +60,32 @@ def validate_filters(filters):
frappe.throw(_("Filter based on Cost Center is only applicable if Budget Against is selected as Cost Center"))
def get_columns(filters):
columns = [_(filters.get("budget_against")) + ":Link/%s:120"%(filters.get("budget_against")), _("Account") + ":Link/Account:120"]
columns = [_(filters.get("budget_against")) + ":Link/%s:80"%(filters.get("budget_against")), _("Account") + ":Link/Account:80"]
group_months = False if filters["period"] == "Monthly" else True
for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]):
for label in [_("Target") + " (%s)", _("Actual") + " (%s)", _("Variance") + " (%s)"]:
if group_months:
label = label % (formatdate(from_date, format_string="MMM") + " - " + formatdate(to_date, format_string="MMM"))
fiscal_year = get_fiscal_years(filters)
for year in fiscal_year:
for from_date, to_date in get_period_date_ranges(filters["period"], year[0]):
if filters["period"] == "Yearly":
labels = [_("Budget") + " " + str(year[0]), _("Actual ") + " " + str(year[0]), _("Varaiance ") + " " + str(year[0])]
for label in labels:
columns.append(label+":Float:80")
else:
label = label % formatdate(from_date, format_string="MMM")
for label in [_("Budget") + " (%s)" + " " + str(year[0]), _("Actual") + " (%s)" + " " + str(year[0]), _("Variance") + " (%s)" + " " + str(year[0])]:
if group_months:
label = label % (formatdate(from_date, format_string="MMM") + "-" + formatdate(to_date, format_string="MMM"))
else:
label = label % formatdate(from_date, format_string="MMM")
columns.append(label+":Float:120")
columns.append(label+":Float:80")
return columns + [_("Total Target") + ":Float:120", _("Total Actual") + ":Float:120",
_("Total Variance") + ":Float:120"]
if filters["period"] != "Yearly" :
return columns + [_("Total Budget") + ":Float:80", _("Total Actual") + ":Float:80",
_("Total Variance") + ":Float:80"]
else:
return columns
def get_cost_centers(filters):
cond = "and 1=1"
@@ -81,21 +102,23 @@ def get_cost_center_target_details(filters):
cond += " and b.cost_center='%s'" % frappe.db.escape(filters.get("cost_center"))
return frappe.db.sql("""
select b.{budget_against} as budget_against, b.monthly_distribution, ba.account, ba.budget_amount
select b.{budget_against} as budget_against, b.monthly_distribution, ba.account, ba.budget_amount,b.fiscal_year
from `tabBudget` b, `tabBudget Account` ba
where b.name=ba.parent and b.docstatus = 1 and b.fiscal_year=%s
and b.budget_against = %s and b.company=%s {cond}
where b.name=ba.parent and b.docstatus = 1 and b.fiscal_year between %s and %s
and b.budget_against = %s and b.company=%s {cond} order by b.fiscal_year
""".format(budget_against=filters.get("budget_against").replace(" ", "_").lower(), cond=cond),
(filters.fiscal_year, filters.budget_against, filters.company), as_dict=True)
(filters.from_fiscal_year,filters.to_fiscal_year,filters.budget_against, filters.company), as_dict=True)
#Get target distribution details of accounts of cost center
def get_target_distribution_details(filters):
target_details = {}
for d in frappe.db.sql("""select md.name, mdp.month, mdp.percentage_allocation
from `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md
where mdp.parent=md.name and md.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
where mdp.parent=md.name and md.fiscal_year between %s and %s order by md.fiscal_year""",(filters.from_fiscal_year, filters.to_fiscal_year), as_dict=1):
target_details.setdefault(d.name, {}).setdefault(d.month, flt(d.percentage_allocation))
return target_details
#Get actual details from gl entry
@@ -107,7 +130,7 @@ def get_actual_details(name, filters):
cc_lft, cc_rgt = frappe.db.get_value("Cost Center", name, ["lft", "rgt"])
cond = "lft>='{lft}' and rgt<='{rgt}'".format(lft = cc_lft, rgt=cc_rgt)
ac_details = frappe.db.sql("""select gl.account, gl.debit, gl.credit,
ac_details = frappe.db.sql("""select gl.account, gl.debit, gl.credit,gl.fiscal_year,
MONTHNAME(gl.posting_date) as month_name, b.{budget_against} as budget_against
from `tabGL Entry` gl, `tabBudget Account` ba, `tabBudget` b
where
@@ -115,11 +138,11 @@ def get_actual_details(name, filters):
and b.docstatus = 1
and ba.account=gl.account
and b.{budget_against} = gl.{budget_against}
and gl.fiscal_year=%s
and gl.fiscal_year between %s and %s
and b.{budget_against}=%s
and exists(select name from `tab{tab}` where name=gl.{budget_against} and {cond}) group by gl.name
""".format(tab = filters.budget_against, budget_against = budget_against, cond = cond),
(filters.fiscal_year, name), as_dict=1)
and exists(select name from `tab{tab}` where name=gl.{budget_against} and {cond}) group by gl.name order by gl.fiscal_year
""".format(tab = filters.budget_against, budget_against = budget_against, cond = cond,from_year=filters.from_fiscal_year,to_year=filters.to_fiscal_year),
(filters.from_fiscal_year, filters.to_fiscal_year, name), as_dict=1)
cc_actual_details = {}
for d in ac_details:
@@ -139,13 +162,12 @@ def get_cost_center_account_month_map(filters):
for month_id in range(1, 13):
month = datetime.date(2013, month_id, 1).strftime('%B')
cam_map.setdefault(ccd.budget_against, {}).setdefault(ccd.account, {})\
cam_map.setdefault(ccd.budget_against, {}).setdefault(ccd.account, {}).setdefault(ccd.fiscal_year,{})\
.setdefault(month, frappe._dict({
"target": 0.0, "actual": 0.0
}))
tav_dict = cam_map[ccd.budget_against][ccd.account][month]
tav_dict = cam_map[ccd.budget_against][ccd.account][ccd.fiscal_year][month]
month_percentage = tdd.get(ccd.monthly_distribution, {}).get(month, 0) \
if ccd.monthly_distribution else 100.0/12
@@ -156,3 +178,11 @@ def get_cost_center_account_month_map(filters):
tav_dict.actual += flt(ad.debit) - flt(ad.credit)
return cam_map
def get_fiscal_years(filters):
fiscal_year = frappe.db.sql("""select name from `tabFiscal Year` where
name between %(from_fiscal_year)s and %(to_fiscal_year)s""",
{'from_fiscal_year': filters["from_fiscal_year"], 'to_fiscal_year': filters["to_fiscal_year"]})
return fiscal_year

View File

@@ -10,7 +10,7 @@ from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement
def get_mapper_for(mappers, position):
mapper_list = filter(lambda x: x['position'] == position, mappers)
mapper_list = list(filter(lambda x: x['position'] == position, mappers))
return mapper_list[0] if mapper_list else []
@@ -345,13 +345,13 @@ def execute(filters=None):
# compute net profit / loss
income = get_data(
filters.company, "Income", "Credit", period_list,
filters.company, "Income", "Credit", period_list, filters=filters,
accumulated_values=filters.accumulated_values, ignore_closing_entries=True,
ignore_accumulated_values_for_fy=True
)
expense = get_data(
filters.company, "Expense", "Debit", period_list,
filters.company, "Expense", "Debit", period_list, filters=filters,
accumulated_values=filters.accumulated_values, ignore_closing_entries=True,
ignore_accumulated_values_for_fy=True
)

View File

@@ -238,6 +238,9 @@ def accumulate_values_into_parents(accounts, accounts_by_name, companies):
for d in reversed(accounts):
if d.parent_account:
account = d.parent_account.split('-')[0].strip()
if not accounts_by_name.get(account):
continue
for company in companies:
accounts_by_name[account][company] = \
accounts_by_name[account].get(company, 0.0) + d.get(company, 0.0)
@@ -268,8 +271,7 @@ def get_companies(filters):
return all_companies, companies
def get_subsidiary_companies(company):
lft, rgt = frappe.get_cached_value('Company',
company, ["lft", "rgt"])
lft, rgt = frappe.db.get_value('Company', company, ["lft", "rgt"])
return frappe.db.sql_list("""select name from `tabCompany`
where lft >= {0} and rgt <= {1} order by lft, rgt""".format(lft, rgt))

View File

@@ -28,6 +28,24 @@ frappe.query_reports["Item-wise Sales Register"] = {
"label": __("Mode of Payment"),
"fieldtype": "Link",
"options": "Mode of Payment"
},
{
"fieldname":"warehouse",
"label": __("Warehouse"),
"fieldtype": "Link",
"options": "Warehouse"
},
{
"fieldname":"brand",
"label": __("Brand"),
"fieldtype": "Link",
"options": "Brand"
},
{
"fieldname":"item_group",
"label": __("Item Group"),
"fieldtype": "Link",
"options": "Item Group"
}
]
}

View File

@@ -14,10 +14,10 @@ def execute(filters=None):
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
if not filters: filters = {}
filters.update({"from_date": filters.get("date_range")[0], "to_date": filters.get("date_range")[1]})
filters.update({"from_date": filters.get("date_range") and filters.get("date_range")[0], "to_date": filters.get("date_range") and filters.get("date_range")[1]})
columns = get_columns(additional_table_columns)
company_currency = erpnext.get_company_currency(filters.company)
company_currency = erpnext.get_company_currency(filters.get('company'))
item_list = get_items(filters, additional_query_columns)
if item_list:
@@ -108,6 +108,23 @@ def get_conditions(filters):
conditions += """ and exists(select name from `tabSales Invoice Payment`
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
if filters.get("warehouse"):
conditions += """ and exists(select name from `tabSales Invoice Item`
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s)"""
if filters.get("brand"):
conditions += """ and exists(select name from `tabSales Invoice Item`
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s)"""
if filters.get("item_group"):
conditions += """ and exists(select name from `tabSales Invoice Item`
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s)"""
return conditions

View File

@@ -52,6 +52,18 @@ frappe.query_reports["Sales Register"] = {
"label": __("Warehouse"),
"fieldtype": "Link",
"options": "Warehouse"
},
{
"fieldname":"brand",
"label": __("Brand"),
"fieldtype": "Link",
"options": "Brand"
},
{
"fieldname":"item_group",
"label": __("Item Group"),
"fieldtype": "Link",
"options": "Item Group"
}
]
}

View File

@@ -153,6 +153,16 @@ def get_conditions(filters):
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s)"""
if filters.get("brand"):
conditions += """ and exists(select name from `tabSales Invoice Item`
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s)"""
if filters.get("item_group"):
conditions += """ and exists(select name from `tabSales Invoice Item`
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s)"""
return conditions
def get_invoices(filters, additional_query_columns):

View File

@@ -8,6 +8,7 @@ frappe.query_reports["TDS Computation Summary"] = {
"fieldname":"company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_default('company')
},
{

View File

@@ -41,8 +41,10 @@ def get_result(filters):
for supplier in filters.supplier:
tds = frappe.get_doc("Tax Withholding Category", supplier.tax_withholding_category)
rate = [d.tax_withholding_rate for d in tds.rates if d.fiscal_year == filters.fiscal_year][0]
account = [d.account for d in tds.accounts if d.company == filters.company][0]
try:
account = [d.account for d in tds.accounts if d.company == filters.company][0]
except IndexError:
account = []
total_invoiced_amount, tds_deducted = get_invoice_and_tds_amount(supplier.name, account,
filters.company, filters.from_date, filters.to_date)

View File

@@ -94,6 +94,12 @@ frappe.ui.form.on('Asset', {
}, __("Make"));
}
if (!frm.doc.calculate_depreciation) {
frm.add_custom_button(__("Depreciation Entry"), function() {
frm.trigger("make_journal_entry");
}, __("Make"));
}
frm.page.set_inner_btn_group_as_primary(__("Make"));
frm.trigger("setup_chart");
}
@@ -103,6 +109,21 @@ frappe.ui.form.on('Asset', {
}
},
make_journal_entry: function(frm) {
frappe.call({
method: "erpnext.assets.doctype.asset.asset.make_journal_entry",
args: {
asset_name: frm.doc.name
},
callback: function(r) {
if (r.message) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
}
})
},
setup_chart: function(frm) {
var x_intervals = [frm.doc.purchase_date];
var asset_values = [frm.doc.gross_purchase_amount];

View File

@@ -511,3 +511,34 @@ def get_asset_account(account_name, asset=None, asset_category=None, company=Non
.format(account_name.replace('_', ' ').title(), asset_category, company))
return account
@frappe.whitelist()
def make_journal_entry(asset_name):
asset = frappe.get_doc("Asset", asset_name)
fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \
get_depreciation_accounts(asset)
depreciation_cost_center, depreciation_series = frappe.db.get_value("Company", asset.company,
["depreciation_cost_center", "series_for_depreciation_entry"])
depreciation_cost_center = asset.cost_center or depreciation_cost_center
je = frappe.new_doc("Journal Entry")
je.voucher_type = "Depreciation Entry"
je.naming_series = depreciation_series
je.company = asset.company
je.remark = "Depreciation Entry against asset {0}".format(asset_name)
je.append("accounts", {
"account": depreciation_expense_account,
"reference_type": "Asset",
"reference_name": asset.name,
"cost_center": depreciation_cost_center
})
je.append("accounts", {
"account": accumulated_depreciation_account,
"reference_type": "Asset",
"reference_name": asset.name
})
return je

View File

@@ -9,8 +9,9 @@ from frappe.utils import flt, today, getdate, cint
def post_depreciation_entries(date=None):
# Return if automatic booking of asset depreciation is disabled
if not frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically"):
if not cint(frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically")):
return
if not date:
date = today()
for asset in get_depreciable_assets(date):
@@ -197,4 +198,4 @@ def get_disposal_account_and_cost_center(company):
if not depreciation_cost_center:
frappe.throw(_("Please set 'Asset Depreciation Cost Center' in Company {0}").format(company))
return disposal_account, depreciation_cost_center
return disposal_account, depreciation_cost_center

View File

@@ -49,6 +49,10 @@ frappe.ui.form.on("Supplier", {
erpnext.utils.make_bank_account(frm.doc.doctype, frm.doc.name);
}, __("Make"));
frm.add_custom_button(__('Pricing Rule'), function () {
erpnext.utils.make_pricing_rule(frm.doc.doctype, frm.doc.name);
}, __("Make"));
// indicators
erpnext.utils.set_party_dashboard_indicators(frm);
}

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,10 @@ def get_data():
{
'label': _('Orders'),
'items': ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
},
{
'label': _('Pricing'),
'items': ['Pricing Rule']
}
]
}

View File

@@ -235,6 +235,16 @@ def get_data():
"type": "doctype",
"name": "GST HSN Code",
},
{
"type": "report",
"name": "GSTR-1",
"is_query_report": True
},
{
"type": "report",
"name": "GSTR-2",
"is_query_report": True
},
{
"type": "report",
"name": "GST Sales Register",

View File

@@ -661,7 +661,7 @@ class BuyingController(StockController):
if self.doctype == 'Purchase Invoice' and not self.get('update_stock'):
return
frappe.db.sql("delete from `tabAsset Movement` where reference_name=%s and docstatus = 0", self.name)
frappe.db.sql("delete from `tabAsset Movement` where reference_name=%s", self.name)
frappe.db.sql("delete from `tabSerial No` where purchase_document_no=%s", self.name)
def validate_schedule_date(self):

View File

@@ -137,7 +137,7 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
.format(args.item_code), StockOverReturnError)
elif abs(current_stock_qty) > max_returnable_qty:
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
.format(args.idx, reference_qty, args.item_code), StockOverReturnError)
.format(args.idx, max_returnable_qty, args.item_code), StockOverReturnError)
def get_ref_item_dict(valid_items, ref_item_row):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Market Segment', {
refresh: function(frm) {
}
});

View File

@@ -0,0 +1,96 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:market_segment",
"beta": 0,
"creation": "2018-10-01 09:59:14.479509",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"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,
"fieldname": "market_segment",
"fieldtype": "Data",
"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": "Market Segment",
"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": 1
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-10-01 09:59:14.479509",
"modified_by": "Administrator",
"module": "CRM",
"name": "Market Segment",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class MarketSegment(Document):
pass

View File

@@ -0,0 +1,23 @@
/* eslint-disable */
// rename this file from _test_[name] to test_[name] to activate
// and remove above this line
QUnit.test("test: Market Segment", function (assert) {
let done = assert.async();
// number of asserts
assert.expect(1);
frappe.run_serially([
// insert a new Market Segment
() => frappe.tests.make('Market Segment', [
// values to be set
{key: 'value'}
]),
() => {
assert.equal(cur_frm.doc.key, 'value');
},
() => done()
]);
});

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
class TestMarketSegment(unittest.TestCase):
pass

View File

@@ -107,6 +107,8 @@ erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({
if(!this.frm.doc.company && frappe.defaults.get_user_default("Company"))
set_multiple(this.frm.doc.doctype, this.frm.doc.name,
{ company:frappe.defaults.get_user_default("Company") });
if(!this.frm.doc.currency)
set_multiple(this.frm.doc.doctype, this.frm.doc.name, { currency:frappe.defaults.get_user_default("Currency") });
this.setup_queries();
},

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Sales Stage', {
refresh: function(frm) {
}
});

View File

@@ -0,0 +1,96 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:stage_name",
"beta": 0,
"creation": "2018-10-01 09:28:16.399518",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"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,
"fieldname": "stage_name",
"fieldtype": "Data",
"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": "Stage 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": 1
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-10-01 09:29:43.230378",
"modified_by": "Administrator",
"module": "CRM",
"name": "Sales Stage",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class SalesStage(Document):
pass

View File

@@ -0,0 +1,23 @@
/* eslint-disable */
// rename this file from _test_[name] to test_[name] to activate
// and remove above this line
QUnit.test("test: Sales Stage", function (assert) {
let done = assert.async();
// number of asserts
assert.expect(1);
frappe.run_serially([
// insert a new Sales Stage
() => frappe.tests.make('Sales Stage', [
// values to be set
{key: 'value'}
]),
() => {
assert.equal(cur_frm.doc.key, 'value');
},
() => done()
]);
});

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
class TestSalesStage(unittest.TestCase):
pass

View File

@@ -1,18 +1,18 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2013-10-22 11:58:16",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 3,
"is_standard": "Yes",
"modified": "2017-02-24 20:20:28.725080",
"modified": "2018-09-26 18:59:46.520731",
"modified_by": "Administrator",
"module": "Selling",
"module": "CRM",
"name": "Lead Details",
"owner": "Administrator",
"query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabDynamic Link` on (\n\t\t`tabDynamic Link`.link_name=`tabLead`.name\n\t)\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.name=`tabDynamic Link`.parent\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
"prepared_report": 0,
"query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n\t`tabLead`.notes as \"Notes::360\",\n `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabDynamic Link` on (\n\t\t`tabDynamic Link`.link_name=`tabLead`.name\n\t)\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.name=`tabDynamic Link`.parent\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
"ref_doctype": "Lead",
"report_name": "Lead Details",
"report_type": "Query Report",

View File

@@ -5,10 +5,19 @@
from __future__ import unicode_literals
from frappe.utils.nestedset import NestedSet
import frappe
class HealthcareServiceUnit(NestedSet):
nsm_parent_field = 'parent_healthcare_service_unit'
def autoname(self):
if self.company:
suffix = " - " + frappe.get_cached_value('Company', self.company, "abbr")
if not self.healthcare_service_unit_name.endswith(suffix):
self.name = self.healthcare_service_unit_name + suffix
else:
self.name = self.healthcare_service_unit_name
def on_update(self):
super(HealthcareServiceUnit, self).on_update()
self.validate_one_root()

View File

@@ -142,6 +142,7 @@ frappe.ui.form.on('Patient Appointment', {
frm.set_value('service_unit', btn_selected.attr('data-service-unit') || '');
frm.set_value('duration', btn_selected.attr('data-duration'));
d.hide();
frm.enable_save();
frm.save();
frm.enable_save();
}

View File

@@ -12,7 +12,7 @@ app_license = "GNU General Public License (v3)"
source_link = "https://github.com/frappe/erpnext"
develop_version = '11.x.x-develop'
staging_version = '11.0.3'
staging_version = '11.0.3-beta.5'
error_report_email = "support@erpnext.com"
@@ -25,6 +25,7 @@ web_include_css = "assets/css/erpnext-web.css"
doctype_js = {
"Communication": "public/js/communication.js",
"Event": "public/js/event.js"
}
welcome_email = "erpnext.setup.utils.welcome_email"

File diff suppressed because it is too large Load Diff

View File

@@ -651,6 +651,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "salary_slip",
"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": "Salary Slip",
"length": 0,
"no_copy": 0,
"options": "Salary Slip",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"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,
@@ -916,7 +949,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 3,
"modified": "2018-08-21 14:44:42.766422",
"modified": "2018-09-21 15:53:11.935416",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Application",

View File

@@ -770,7 +770,7 @@
"collapsible": 1,
"collapsible_depends_on": "",
"columns": 0,
"depends_on": "eval:doc.is_flexible_benefit != 1 && doc.variable_based_on_taxable_salary != 1 && doc.is_additional_component != 1",
"depends_on": "eval:doc.is_flexible_benefit != 1 && doc.variable_based_on_taxable_salary != 1",
"fieldname": "condition_and_formula",
"fieldtype": "Section Break",
"hidden": 0,
@@ -835,7 +835,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"default": "",
"fieldname": "amount_based_on_formula",
"fieldtype": "Check",
"hidden": 0,
@@ -1003,7 +1003,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-07-02 16:55:44.467519",
"modified": "2018-09-20 16:44:58.876044",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Component",
@@ -1056,5 +1056,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
"track_seen": 0,
"track_views": 0
}

View File

@@ -385,7 +385,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "1",
"default": "0",
"depends_on": "eval:doc.parenttype=='Salary Structure'",
"fetch_from": "",
"fieldname": "amount_based_on_formula",
@@ -692,7 +692,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-07-04 16:28:32.314907",
"modified": "2018-09-20 16:59:33.622652",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Detail",
@@ -706,5 +706,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
"track_seen": 0,
"track_views": 0
}

View File

@@ -122,16 +122,14 @@ frappe.ui.form.on('Salary Slip Timesheet', {
// Get leave details
//---------------------------------------------------------------------
var get_emp_and_leave_details = function(doc, dt, dn) {
if(!doc.start_date){
return frappe.call({
method: 'get_emp_and_leave_details',
doc: locals[dt][dn],
callback: function(r, rt) {
cur_frm.refresh();
calculate_all(doc, dt, dn);
}
});
}
return frappe.call({
method: 'get_emp_and_leave_details',
doc: locals[dt][dn],
callback: function(r, rt) {
cur_frm.refresh();
calculate_all(doc, dt, dn);
}
});
}
cur_frm.cscript.employee = function(doc,dt,dn){

View File

@@ -384,8 +384,8 @@ class SalarySlip(TransactionBase):
and t2.is_lwp = 1
and t1.docstatus = 1
and t1.employee = %(employee)s
and CASE WHEN t2.include_holiday != 1 THEN %(dt)s not in ('{0}') and %(dt)s between from_date and to_date
WHEN t2.include_holiday THEN %(dt)s between from_date and to_date
and CASE WHEN t2.include_holiday != 1 THEN %(dt)s not in ('{0}') and %(dt)s between from_date and to_date and ifnull(t1.salary_slip, '') = ''
WHEN t2.include_holiday THEN %(dt)s between from_date and to_date and ifnull(t1.salary_slip, '') = ''
END
""".format(holidays), {"employee": self.employee, "dt": dt})
if leave:

View File

@@ -323,11 +323,12 @@ def make_salary_component(salary_components, test_tax):
def get_salary_component_account(sal_comp):
company = erpnext.get_default_company()
sal_comp = frappe.get_doc("Salary Component", sal_comp)
sal_comp.append("accounts", {
"company": company,
"default_account": create_account(company)
})
sal_comp.save()
if not sal_comp.get("accounts"):
sal_comp.append("accounts", {
"company": company,
"default_account": create_account(company)
})
sal_comp.save()
def create_account(company):
salary_account = frappe.db.get_value("Account", "Salary - " + frappe.get_cached_value('Company', company, 'abbr'))
@@ -347,7 +348,8 @@ def make_earning_salary_component(setup=False, test_tax=False):
"abbr":'BS',
"condition": 'base > 10000',
"formula": 'base*.5',
"type": "Earning"
"type": "Earning",
"amount_based_on_formula": 1
},
{
"salary_component": 'HRA',
@@ -360,7 +362,8 @@ def make_earning_salary_component(setup=False, test_tax=False):
"abbr":'SA',
"condition": 'H < 10000',
"formula": 'BS*.5',
"type": "Earning"
"type": "Earning",
"amount_based_on_formula": 1
},
{
"salary_component": "Leave Encashment",
@@ -401,7 +404,8 @@ def make_earning_salary_component(setup=False, test_tax=False):
"abbr":'BS',
"condition": 'base < 10000',
"formula": 'base*.2',
"type": "Earning"
"type": "Earning",
"amount_based_on_formula": 1
})
return data
@@ -412,13 +416,15 @@ def make_deduction_salary_component(setup=False, test_tax=False):
"abbr":'PT',
"condition": 'base > 10000',
"formula": 'base*.1',
"type": "Deduction"
"type": "Deduction",
"amount_based_on_formula": 1
},
{
"salary_component": 'TDS',
"abbr":'T',
"formula": 'base*.1',
"type": "Deduction"
"type": "Deduction",
"amount_based_on_formula": 1
}
]
if not test_tax:
@@ -427,7 +433,8 @@ def make_deduction_salary_component(setup=False, test_tax=False):
"abbr":'T',
"condition": 'employment_type=="Intern"',
"formula": 'base*.1',
"type": "Deduction"
"type": "Deduction",
"amount_based_on_formula": 1
})
if setup or test_tax:
make_salary_component(data, test_tax)

View File

@@ -18,14 +18,21 @@ class SalaryStructure(Document):
self.validate_max_benefits_with_flexi()
def set_missing_values(self):
fields = ["depends_on_lwp", "variable_based_on_taxable_salary", "is_tax_applicable", "is_flexible_benefit"]
overwritten_fields = ["depends_on_lwp", "variable_based_on_taxable_salary", "is_tax_applicable", "is_flexible_benefit"]
overwritten_fields_if_missing = ["amount_based_on_formula", "formula", "amount"]
for table in ["earnings", "deductions"]:
for d in self.get(table):
component_default_value = frappe.db.get_value("Salary Component", str(d.salary_component), fields, as_dict=1)
component_default_value = frappe.db.get_value("Salary Component", str(d.salary_component),
overwritten_fields + overwritten_fields_if_missing, as_dict=1)
if component_default_value:
for fieldname, value in iteritems(component_default_value):
for fieldname in overwritten_fields:
value = component_default_value.get(fieldname)
if d.get(fieldname) != value:
d[fieldname] = value
d.set(fieldname, value)
if not (d.get("amount") or d.get("formula")):
for fieldname in overwritten_fields_if_missing:
d.set(fieldname, component_default_value.get(fieldname))
def validate_amount(self):
if flt(self.net_pay) < 0 and self.salary_slip_based_on_timesheet:

View File

@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, add_days, date_diff
from frappe.utils import cstr, add_days, date_diff, getdate
from frappe import _
from frappe.utils.csvutils import UnicodeWriter
from frappe.model.document import Document
@@ -48,8 +48,9 @@ def add_data(w, args):
for employee in employees:
existing_attendance = {}
if existing_attendance_records \
and tuple([date, employee.name]) in existing_attendance_records:
existing_attendance = existing_attendance_records[tuple([date, employee.name])]
and tuple([getdate(date), employee.name]) in existing_attendance_records:
existing_attendance = existing_attendance_records[tuple([getdate(date), employee.name])]
row = [
existing_attendance and existing_attendance.name or "",
employee.name, employee.employee_name, date,
@@ -114,6 +115,7 @@ def upload():
if not row: continue
row_idx = i + 5
d = frappe._dict(zip(columns, row))
d["doctype"] = "Attendance"
if d.name:
d["docstatus"] = frappe.db.get_value("Attendance", d.name, "docstatus")
@@ -121,6 +123,8 @@ def upload():
try:
check_record(d)
ret.append(import_doc(d, "Attendance", 1, row_idx, submit=True))
except AttributeError:
pass
except Exception as e:
error = True
ret.append('Error for row (#%d) %s : %s' % (row_idx,

View File

@@ -506,7 +506,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-07-12 16:16:54.237829",
"modified": "2018-10-04 16:16:54.237829",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Work Order Item",

View File

@@ -566,3 +566,6 @@ erpnext.patches.v11_0.redesign_healthcare_billing_work_flow
erpnext.patches.v10_0.delete_hub_documents # 12-08-2018
erpnext.patches.v11_0.rename_healthcare_fields
erpnext.patches.v11_0.remove_land_unit_icon
erpnext.patches.v11_0.add_default_dispatch_notification_template
erpnext.patches.v11_0.add_market_segments
erpnext.patches.v11_0.add_sales_stages

View File

@@ -0,0 +1,25 @@
import os
import frappe
from frappe import _
def execute():
frappe.reload_doc("email", "doctype", "email_template")
frappe.reload_doc("stock", "doctype", "delivery_settings")
if not frappe.db.exists("Email Template", _("Dispatch Notification")):
base_path = frappe.get_app_path("erpnext", "stock", "doctype")
response = frappe.read_file(os.path.join(base_path, "delivery_trip/dispatch_notification_template.html"))
frappe.get_doc({
"doctype": "Email Template",
"name": _("Dispatch Notification"),
"response": response,
"subject": _("Your order is out for delivery!"),
"owner": frappe.session.user,
}).insert(ignore_permissions=True)
delivery_settings = frappe.get_doc("Delivery Settings")
delivery_settings.dispatch_template = _("Dispatch Notification")
delivery_settings.save()

View File

@@ -0,0 +1,11 @@
import frappe
from frappe import _
from erpnext.setup.setup_wizard.operations.install_fixtures import add_market_segments
def execute():
frappe.reload_doc('crm', 'doctype', 'market_segment')
frappe.local.lang = frappe.db.get_default("lang") or 'en'
add_market_segments()

View File

@@ -0,0 +1,10 @@
import frappe
from frappe import _
from erpnext.setup.setup_wizard.operations.install_fixtures import add_sale_stages
def execute():
frappe.reload_doc('crm', 'doctype', 'sales_stage')
frappe.local.lang = frappe.db.get_default("lang") or 'en'
add_sale_stages()

View File

@@ -18,7 +18,7 @@ def execute():
for department in departments:
# skip root node
if department.name == _("All Departments"):
if _(department.name) == _("All Departments"):
continue
# for each company, create a copy of the doc

View File

@@ -15,7 +15,7 @@ def execute():
frappe.reload_doc('accounts', 'doctype', 'loyalty_program')
frappe.reload_doc('accounts', 'doctype', 'sales_invoice_item')
if "healthcare" not in frappe.get_active_domains():
if "Healthcare" not in frappe.get_active_domains():
return
healthcare_custom_field_in_sales_invoice()
@@ -34,24 +34,25 @@ def execute():
frappe.reload_doc(get_doctype_module("Sales Invoice"), 'doctype', 'sales_invoice')
for doc_id in doc_list:
invoice_id = frappe.db.get_value(si_ref_doc, doc_id[0], sales_invoice_referenced_doc[si_ref_doc])
invoice = frappe.get_doc("Sales Invoice", invoice_id)
if invoice.items:
marked = False
if not marked:
if frappe.db.exists("Sales Invoice", invoice_id):
if si_ref_doc == "Lab Test":
template = frappe.db.get_value("Lab Test", doc_id[0], "template")
if template:
item = frappe.db.get_value("Lab Test Template", template, "item")
if item:
frappe.db.sql("""update `tabSales Invoice Item` set reference_dt = '{0}',
reference_dn = '{1}' where parent = '{2}' and item_code='{3}'""".format\
(si_ref_doc, doc_id[0], invoice_id, item))
else:
invoice = frappe.get_doc("Sales Invoice", invoice_id)
for item_line in invoice.items:
marked = True
frappe.db.sql("""
update `tabSales Invoice Item`
set reference_dt = '{0}', reference_dn = '{1}'
where name = '{2}'
""".format(si_ref_doc, doc_id[0], item_line.name))
if not item_line.reference_dn:
item_line.db_set({"reference_dt":si_ref_doc, "reference_dn": doc_id[0]})
break
# Documents mark invoiced for submitted sales invoice
frappe.db.sql("""
update `tab{0}` doc, `tabSales Invoice` si
set doc.invoiced = 1
where si.docstatus = 1 and doc.{1} = si.name
""".format(si_ref_doc, sales_invoice_referenced_doc[si_ref_doc]))
frappe.db.sql("""update `tab{0}` doc, `tabSales Invoice` si
set doc.invoiced = 1 where si.docstatus = 1 and doc.{1} = si.name
""".format(si_ref_doc, sales_invoice_referenced_doc[si_ref_doc]))
def healthcare_custom_field_in_sales_invoice():
frappe.reload_doc('healthcare', 'doctype', 'patient')

View File

@@ -1,80 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xml:space="preserve"
enable-background="new 0 0 512 512"
viewBox="0 0 512 512"
height="512px"
width="512px"
y="0px"
x="0px"
id="Layer_1"
version="1.1"><metadata
id="metadata45"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title><cc:license
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" /></cc:Work><cc:License
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"><cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:requires
rdf:resource="http://creativecommons.org/ns#Notice" /><cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution" /><cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /><cc:requires
rdf:resource="http://creativecommons.org/ns#ShareAlike" /></cc:License></rdf:RDF></metadata><defs
id="defs43" /><g
id="g8"><path
id="path6"
d="M150.483,371.684V141.15c0-15.167,9.534-25.133,23.833-25.133h162.5c13.866,0,20.8,6.933,20.8,18.633v2.6 c0,12.133-6.934,18.633-20.8,18.633h-141.7v78.434h109.634c14.3,0,20.8,6.066,20.8,17.767v1.3c0,12.133-6.934,18.633-20.8,18.633 H195.117v84.934h144.3c13.867,0,20.367,6.066,20.367,17.767v2.167c0,12.566-6.5,19.5-20.367,19.5h-165.1 C160.017,396.384,150.483,386.851,150.483,371.684z"
fill="#FFFFFF" /></g><g
id="g10" /><g
id="g12" /><g
id="g14" /><g
id="g16" /><g
id="g18" /><g
id="g20" /><g
id="g22" /><g
id="g24" /><g
id="g26" /><g
id="g28" /><g
id="g30" /><g
id="g32" /><g
id="g34" /><g
id="g36" /><g
id="g38" /><g
style="stroke-width:0.64453173"
transform="matrix(5.8639898,0,0,5.8639898,-9653.0918,-3338.6848)"
id="g1446-4-5"><g
style="stroke-width:0.64453214"
transform="matrix(0.9999989,0,0,0.99999981,279.19167,438.7826)"
id="g1422-7-2"><g
style="stroke-width:0.64453214"
id="g1418-4-6"
transform="translate(-25.731002,-0.1322636)"><g
style="stroke-width:0.64453214"
transform="translate(-95.250002)"
id="g1416-4-9"><path
style="opacity:1;vector-effect:none;fill:#7574ff;fill-opacity:1;stroke:none;stroke-width:2.55798697;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
d="m 1501.1846,130.70348 h 60.8542 c 7.329,0 13.2292,5.9002 13.2292,13.22916 v 60.85419 c 0,7.32896 -5.9002,13.22917 -13.2292,13.22917 h -60.8542 c -7.3289,0 -13.2292,-5.90021 -13.2292,-13.22917 v -60.85419 c 0,-7.32896 5.9003,-13.22916 13.2292,-13.22916 z"
id="path1414-3-4" /></g></g><g
id="g1420-0-4"
transform="matrix(1.0131472,0,0,1.0131472,-144.01349,-2.2905938)"
style="stroke-width:0.63616848" /></g><path
id="circle1424-7-6"
transform="matrix(0.26458333,0,0,0.26458333,1646.1645,569.35379)"
d="M 164.92578,228.00977 A 412.60453,412.60453 0 0 0 0,262.94922 V 280 c 0,27.70001 22.30022,50 50,50 h 230 c 27.69978,0 50,-22.29999 50,-50 V 262.70508 A 412.60453,412.60453 0 0 0 164.92578,228.00977 Z"
clip-path="none"
style="opacity:1;vector-effect:none;fill:#6564f9;fill-opacity:1;stroke:none;stroke-width:9.66797638;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /><g
style="fill:#4a15c6;fill-opacity:1;stroke-width:0.64453173"
transform="translate(2.8144523,0.84784259)"
id="g1434-8-0" /><g
style="stroke-width:0.64453173"
id="g1444-6-7"
transform="translate(3.8727857,-0.32524952)"><path
style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:9.66797638;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
d="m 3738.9473,951.78516 c -1.0388,0 -2.0511,0.10552 -3.0293,0.30468 -0.9783,0.19916 -1.9225,0.49258 -2.8203,0.8711 -0.449,0.18926 -0.8854,0.40047 -1.3106,0.63086 -0.8503,0.46076 -1.6504,1.00091 -2.3906,1.61132 -3.3312,2.74687 -5.4492,6.90766 -5.4492,11.58204 v 0.91406 133.17378 0.9122 c 0,8.31 6.69,15 15,15 h 104.9082 c 8.31,0 15,-6.69 15,-15 v -0.9122 c 0,-8.31 -6.69,-15 -15,-15 h -88.9942 v -37.3613 h 66.1699 c 8.31,0 15,-6.69 15,-15 v -0.9121 c 0,-8.31 -6.69,-15 -15,-15 h -66.1699 v -34.90038 h 88.9942 c 8.31,0 15,-6.69 15,-15 v -0.91406 c 0,-8.31 -6.69,-15 -15,-15 z"
transform="matrix(0.26458334,0,0,0.26458334,682.80626,339.68051)"
id="rect1436-8-4" /></g></g></svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg width="88px" height="88px" viewBox="0 0 88 88" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 44.1 (41455) - http://www.bohemiancoding.com/sketch -->
<title>erpnext-logo</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="erpnext-logo" transform="translate(-2.000000, -2.000000)" fill-rule="nonzero">
<g id="g1422-7-2" transform="translate(0.025630, 0.428785)" fill="#5E64FF">
<g id="g1418-4-6" transform="translate(0.268998, 0.867736)">
<g id="g1416-4-9" transform="translate(0.749997, 0.000000)">
<path d="M14.1845844,0.703479866 L75.0387175,0.703479866 C82.3677094,0.703479866 88.2679029,6.60367875 88.2679029,13.9326374 L88.2679029,74.7868158 C88.2679029,82.1157744 82.3677094,88.0159833 75.0387175,88.0159833 L14.1845844,88.0159833 C6.85569246,88.0159833 0.955398949,82.1157744 0.955398949,74.7868158 L0.955398949,13.9326374 C0.955398949,6.60367875 6.85569246,0.703479866 14.1845844,0.703479866 L14.1845844,0.703479866 Z" id="path1414-3-4"></path>
</g>
</g>
</g>
<g id="g1444-6-7" transform="translate(27.708247, 23.320960)" fill="#FFFFFF">
<path d="M4.06942472,0.507006595 C3.79457554,0.507006595 3.52673783,0.534925429 3.26792241,0.587619847 C3.00908052,0.640314265 2.75926093,0.717948309 2.52171801,0.818098395 C2.40292009,0.868173438 2.28745592,0.924056085 2.17495509,0.985013441 C1.94997987,1.10692286 1.73828674,1.24983755 1.54244215,1.41134187 C0.661062132,2.13811791 0.100674618,3.23899362 0.100674618,4.4757567 L0.100674618,4.71760174 L0.100674618,39.9531653 L0.100674618,40.1945182 C0.100674618,42.3932057 1.87073716,44.1632683 4.06942472,44.1632683 L31.8263867,44.1632683 C34.0250742,44.1632683 35.7951368,42.3932057 35.7951368,40.1945182 L35.7951368,39.9531653 C35.7951368,37.7544777 34.0250742,35.9844152 31.8263867,35.9844152 L8.28000399,35.9844152 L8.28000399,26.0992376 L25.7874571,26.0992376 C27.9861447,26.0992376 29.7562072,24.3291751 29.7562072,22.1304875 L29.7562072,21.8891611 C29.7562072,19.6904735 27.9861447,17.920411 25.7874571,17.920411 L8.28000399,17.920411 L8.28000399,8.68635184 L31.8263867,8.68635184 C34.0250742,8.68635184 35.7951368,6.9162893 35.7951368,4.71760174 L35.7951368,4.4757567 C35.7951368,2.27706914 34.0250742,0.507006595 31.8263867,0.507006595 L4.06942472,0.507006595 Z" id="rect1436-8-4"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -211,8 +211,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
},
make_payment_request: function() {
const me = this;
const payment_request_type = (in_list(['Sales Order', 'Sales Invoice'], me.frm.doc.doctype))
var me = this;
const payment_request_type = (in_list(['Sales Order', 'Sales Invoice'], this.frm.doc.doctype))
? "Inward" : "Outward";
frappe.call({

View File

@@ -0,0 +1,35 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt
frappe.provide("frappe.desk");
frappe.ui.form.on("Event", {
refresh: function(frm) {
frm.set_query('reference_doctype', "event_participants", function() {
return {
"filters": {
"name": ["in", ["Contact", "Lead", "Customer", "Supplier", "Employee", "Sales Partner"]]
}
};
});
frm.add_custom_button(__('Add Leads'), function() {
new frappe.desk.eventParticipants(frm, "Lead");
}, __("Add Participants"));
frm.add_custom_button(__('Add Customers'), function() {
new frappe.desk.eventParticipants(frm, "Customer");
}, __("Add Participants"));
frm.add_custom_button(__('Add Suppliers'), function() {
new frappe.desk.eventParticipants(frm, "Supplier");
}, __("Add Participants"));
frm.add_custom_button(__('Add Employees'), function() {
new frappe.desk.eventParticipants(frm, "Employee");
}, __("Add Participants"));
frm.add_custom_button(__('Add Sales Partners'), function() {
new frappe.desk.eventParticipants(frm, "Sales Partners");
}, __("Add Participants"));
}
});

View File

@@ -18,18 +18,19 @@ export default {
},
methods: {
make_input() {
this.message_input = new frappe.ui.CommentArea({
this.message_input = frappe.ui.form.make_control({
parent: this.$refs['comment-input'],
on_submit: (message) => {
this.message_input.reset();
this.$emit('change', message);
},
only_input: true,
no_wrapper: true
});
},
submit_input() {
if (!this.message_input) return;
const value = this.message_input.val();
const value = this.message_input.get_value();
if (!value) return;
this.message_input.submit();
}

View File

@@ -1,6 +1,44 @@
<template>
<div>
<div ref="review-area" class="timeline-head"></div>
<div class="timeline-head">
<div class="comment-input-wrapper">
<div class="comment-input-header">
<span class="text-muted">{{ __('Add your review') }}</span>
<div class="btn btn-default btn-xs pull-right"
@click="on_submit_review"
:disabled="!(user_review.rating && user_review.subject)"
>
{{ __('Submit Review') }}
</div>
</div>
<div class="comment-input-container">
<div class="rating-area text-muted">
<span>{{ __('Your rating:') }}</span>
<div
v-for="i in [1, 2, 3, 4, 5]"
:key="i"
:class="['fa fa-fw', user_review.rating < i ? 'fa-star-o' : 'fa-star']"
:data-index="i"
@click="set_rating(i)"
>
</div>
</div>
<div class="comment-input-body margin-top" v-show="user_review.rating">
<input
type="text"
placeholder="Subject"
class="form-control margin-bottom"
style="border-color: #ebeff2"
v-model="user_review.subject"
>
<div ref="review-content"></div>
<div>
<span class="text-muted text-small">{{ __('Ctrl+Enter to submit') }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="timeline-items">
<review-timeline-item v-for="review in reviews"
:key="review.user"
@@ -22,6 +60,11 @@ export default {
props: ['hub_item_name'],
data() {
return {
user_review: {
rating: 0,
subject: '',
content: ''
},
reviews: []
}
},
@@ -35,6 +78,10 @@ export default {
this.make_input();
},
methods: {
set_rating(i) {
this.user_review.rating = i;
},
when(datetime) {
return comment_when(datetime);
},
@@ -48,21 +95,37 @@ export default {
},
make_input() {
this.review_area = new frappe.ui.ReviewArea({
parent: this.$refs['review-area'],
mentions: [],
on_submit: this.on_submit_review.bind(this)
this.review_content = frappe.ui.form.make_control({
parent: this.$refs['review-content'],
on_submit: this.on_submit_review.bind(this),
no_wrapper: true,
only_input: true,
render_input: true,
df: {
fieldtype: 'Comment',
fieldname: 'comment'
}
});
},
on_submit_review(values) {
this.review_area.reset();
on_submit_review() {
const review = Object.assign({}, this.user_review, {
content: this.review_content.get_value()
});
hub.call('add_item_review', {
hub_item_name: this.hub_item_name,
review: JSON.stringify(values)
review: JSON.stringify(review)
})
.then(this.push_review.bind(this));
this.reset_user_review();
},
reset_user_review() {
this.user_review.rating = 0;
this.user_review.subject = '';
this.review_content.set_value('');
},
push_review(review){
@@ -70,4 +133,4 @@ export default {
}
}
}
</script>
</script>

View File

@@ -173,6 +173,20 @@ $.extend(erpnext.utils, {
})
},
make_pricing_rule: function(doctype, docname) {
frappe.call({
method: "erpnext.accounts.doctype.pricing_rule.pricing_rule.make_pricing_rule",
args: {
doctype: doctype,
docname: docname
},
callback: function(r) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
})
},
/**
* Checks if the first row of a given child table is empty
* @param child_table - Child table Doctype

View File

@@ -7,7 +7,6 @@
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"letter_head": "test",
"modified": "2018-01-02 17:56:15.379347",
"modified_by": "Administrator",
"module": "Regional",
@@ -27,4 +26,4 @@
"role": "Auditor"
}
]
}
}

View File

@@ -106,6 +106,10 @@ frappe.ui.form.on("Customer", {
frappe.set_route('query-report', 'Accounts Receivable', {customer:frm.doc.name});
});
frm.add_custom_button(__('Pricing Rule'), function () {
erpnext.utils.make_pricing_rule(frm.doc.doctype, frm.doc.name);
}, __("Make"));
// indicator
erpnext.utils.set_party_dashboard_indicators(frm);

File diff suppressed because it is too large Load Diff

View File

@@ -21,6 +21,10 @@ def get_data():
{
'label': _('Projects'),
'items': ['Project']
},
{
'label': _('Pricing'),
'items': ['Pricing Rule']
}
]
}

View File

@@ -13,23 +13,34 @@ frappe.pages['sales-funnel'].on_page_load = function(wrapper) {
frappe.breadcrumbs.add("Selling");
}
erpnext.SalesFunnel = Class.extend({
init: function(wrapper) {
erpnext.SalesFunnel = class SalesFunnel {
constructor(wrapper) {
var me = this;
// 0 setTimeout hack - this gives time for canvas to get width and height
setTimeout(function() {
me.setup(wrapper);
me.get_data();
}, 0);
},
}
setup: function(wrapper) {
setup(wrapper) {
var me = this;
this.company_field = wrapper.page.add_field({"fieldtype": "Link", "fieldname": "company", "options": "Company",
"label": __("Company"), "reqd": 1, "default": frappe.defaults.get_user_default('company'),
change: function() {
me.company = this.value || frappe.defaults.get_user_default('company');
me.get_data();
}
}),
this.elements = {
layout: $(wrapper).find(".layout-main"),
from_date: wrapper.page.add_date(__("From Date")),
to_date: wrapper.page.add_date(__("To Date")),
chart: wrapper.page.add_select(__("Chart"), [{value: 'sales_funnel', label:__("Sales Funnel")},
{value: 'sales_pipeline', label:__("Sales Pipeline")},
{value: 'opp_by_lead_source', label:__("Opportunities by lead source")}]),
refresh_btn: wrapper.page.set_primary_action(__("Refresh"),
function() { me.get_data(); }, "fa fa-refresh"),
};
@@ -41,16 +52,27 @@ erpnext.SalesFunnel = Class.extend({
this.elements.funnel_wrapper = $('<div class="funnel-wrapper text-center"></div>')
.appendTo(this.elements.layout);
this.company = frappe.defaults.get_user_default('company');
this.options = {
from_date: frappe.datetime.add_months(frappe.datetime.get_today(), -1),
to_date: frappe.datetime.get_today()
to_date: frappe.datetime.get_today(),
chart: 'sales_funnel'
};
// set defaults and bind on change
$.each(this.options, function(k, v) {
me.elements[k].val(frappe.datetime.str_to_user(v));
if (['from_date', 'to_date'].includes(k)) {
me.elements[k].val(frappe.datetime.str_to_user(v));
} else {
me.elements[k].val(v);
}
me.elements[k].on("change", function() {
me.options[k] = frappe.datetime.user_to_str($(this).val());
if (['from_date', 'to_date'].includes(k)) {
me.options[k] = frappe.datetime.user_to_str($(this).val()) != 'Invalid date' ? frappe.datetime.user_to_str($(this).val()) : frappe.datetime.get_today();
} else {
me.options.chart = $(this).val();
}
me.get_data();
});
});
@@ -64,29 +86,90 @@ erpnext.SalesFunnel = Class.extend({
$(window).resize(function() {
me.render();
});
},
}
get_data: function(btn) {
get_data(btn) {
var me = this;
frappe.call({
method: "erpnext.selling.page.sales_funnel.sales_funnel.get_funnel_data",
args: {
from_date: this.options.from_date,
to_date: this.options.to_date
},
btn: btn,
callback: function(r) {
if(!r.exc) {
me.options.data = r.message;
me.render();
if (me.options.chart == 'sales_funnel'){
frappe.call({
method: "erpnext.selling.page.sales_funnel.sales_funnel.get_funnel_data",
args: {
from_date: this.options.from_date,
to_date: this.options.to_date,
company: this.company
},
btn: btn,
callback: function(r) {
if(!r.exc) {
me.options.data = r.message;
if (me.options.data=='empty') {
const $parent = me.elements.funnel_wrapper;
$parent.html(__('No data for this period'));
} else {
me.render_funnel();
}
}
}
}
});
},
});
} else if (me.options.chart == 'opp_by_lead_source'){
frappe.call({
method: "erpnext.selling.page.sales_funnel.sales_funnel.get_opp_by_lead_source",
args: {
from_date: this.options.from_date,
to_date: this.options.to_date,
company: this.company
},
btn: btn,
callback: function(r) {
if(!r.exc) {
me.options.data = r.message;
if (me.options.data=='empty') {
const $parent = me.elements.funnel_wrapper;
$parent.html(__('No data for this period'));
} else {
me.render_opp_by_lead_source();
}
}
}
});
} else if (me.options.chart == 'sales_pipeline'){
frappe.call({
method: "erpnext.selling.page.sales_funnel.sales_funnel.get_pipeline_data",
args: {
from_date: this.options.from_date,
to_date: this.options.to_date,
company: this.company
},
btn: btn,
callback: function(r) {
if(!r.exc) {
me.options.data = r.message;
if (me.options.data=='empty') {
const $parent = me.elements.funnel_wrapper;
$parent.html(__('No data for this period'));
} else {
me.render_pipeline();
}
}
}
});
}
}
render: function() {
render() {
let me = this;
if (me.options.chart == 'sales_funnel'){
me.render_funnel();
} else if (me.options.chart == 'opp_by_lead_source'){
me.render_opp_by_lead_source();
} else if (me.options.chart == 'sales_pipeline'){
me.render_pipeline();
}
}
render_funnel() {
var me = this;
this.prepare();
this.prepare_funnel();
var context = this.elements.context,
x_start = 0.0,
@@ -119,9 +202,9 @@ erpnext.SalesFunnel = Class.extend({
me.draw_legend(x_mid, y_mid, me.options.width, me.options.height, d.value + " - " + d.title);
});
},
}
prepare: function() {
prepare_funnel() {
var me = this;
this.elements.no_data.toggle(false);
@@ -147,9 +230,9 @@ erpnext.SalesFunnel = Class.extend({
.attr("height", this.options.height);
this.elements.context = this.elements.canvas.get(0).getContext("2d");
},
}
draw_triangle: function(x_start, x_mid, x_end, y, height) {
draw_triangle(x_start, x_mid, x_end, y, height) {
var context = this.elements.context;
context.beginPath();
context.moveTo(x_start, y);
@@ -158,9 +241,9 @@ erpnext.SalesFunnel = Class.extend({
context.lineTo(x_start, y);
context.closePath();
context.fill();
},
}
draw_legend: function(x_mid, y_mid, width, height, title) {
draw_legend(x_mid, y_mid, width, height, title) {
var context = this.elements.context;
if(y_mid == 0) {
@@ -186,4 +269,44 @@ erpnext.SalesFunnel = Class.extend({
context.font = "1.1em sans-serif";
context.fillText(__(title), width + 20, y_mid);
}
});
render_opp_by_lead_source() {
let me = this;
let currency = frappe.defaults.get_default("currency");
let chart_data = me.options.data ? me.options.data : null;
const parent = me.elements.funnel_wrapper[0];
this.chart = new Chart(parent, {
title: __("Sales Opportunities by Source"),
height: 400,
data: chart_data,
type: 'bar',
barOptions: {
stacked: 1
},
tooltipOptions: {
formatTooltipY: d => format_currency(d, currency),
}
});
}
render_pipeline() {
let me = this;
let currency = frappe.defaults.get_default("currency");
let chart_data = me.options.data ? me.options.data : null;
const parent = me.elements.funnel_wrapper[0];
this.chart = new Chart(parent, {
title: __("Sales Pipeline by Stage"),
height: 400,
data: chart_data,
type: 'bar',
tooltipOptions: {
formatTooltipY: d => format_currency(d, currency),
},
colors: ['light-green', 'green']
});
}
};

View File

@@ -1,16 +1,18 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from erpnext.accounts.report.utils import convert
import pandas as pd
@frappe.whitelist()
def get_funnel_data(from_date, to_date):
def get_funnel_data(from_date, to_date, company):
active_leads = frappe.db.sql("""select count(*) from `tabLead`
where (date(`modified`) between %s and %s)
and status != "Do Not Contact" """, (from_date, to_date))[0][0]
and status != "Do Not Contact" and company=%s""", (from_date, to_date, company))[0][0]
active_leads += frappe.db.sql("""select count(distinct contact.name) from `tabContact` contact
left join `tabDynamic Link` dl on (dl.parent=contact.name) where dl.link_doctype='Customer'
@@ -18,14 +20,14 @@ def get_funnel_data(from_date, to_date):
opportunities = frappe.db.sql("""select count(*) from `tabOpportunity`
where (date(`creation`) between %s and %s)
and status != "Lost" """, (from_date, to_date))[0][0]
and status != "Lost" and company=%s""", (from_date, to_date, company))[0][0]
quotations = frappe.db.sql("""select count(*) from `tabQuotation`
where docstatus = 1 and (date(`creation`) between %s and %s)
and status != "Lost" """, (from_date, to_date))[0][0]
and status != "Lost" and company=%s""", (from_date, to_date, company))[0][0]
sales_orders = frappe.db.sql("""select count(*) from `tabSales Order`
where docstatus = 1 and (date(`creation`) between %s and %s)""", (from_date, to_date))[0][0]
where docstatus = 1 and (date(`creation`) between %s and %s) and company=%s""", (from_date, to_date, company))[0][0]
return [
{ "title": _("Active Leads / Customers"), "value": active_leads, "color": "#B03B46" },
@@ -33,3 +35,54 @@ def get_funnel_data(from_date, to_date):
{ "title": _("Quotations"), "value": quotations, "color": "#006685" },
{ "title": _("Sales Orders"), "value": sales_orders, "color": "#00AD65" }
]
@frappe.whitelist()
def get_opp_by_lead_source(from_date, to_date, company):
opportunities = frappe.get_all("Opportunity", filters=[['status', 'in', ['Open', 'Quotation', 'Replied']], ['company', '=', company], ['transaction_date', 'Between', [from_date, to_date]]], fields=['currency', 'sales_stage', 'opportunity_amount', 'probability', 'source'])
if opportunities:
default_currency = frappe.get_cached_value('Global Defaults', 'None', 'default_currency')
cp_opportunities = [dict(x, **{'compound_amount': (convert(x['opportunity_amount'], x['currency'], default_currency, to_date) * x['probability']/100)}) for x in opportunities]
df = pd.DataFrame(cp_opportunities).groupby(['source', 'sales_stage'], as_index=False).agg({'compound_amount': 'sum'})
result = {}
result['labels'] = list(set(df.source.values))
result['datasets'] = []
for s in set(df.sales_stage.values):
result['datasets'].append({'name': s, 'values': [0]*len(result['labels']), 'chartType': 'bar'})
for row in df.itertuples():
source_index = result['labels'].index(row.source)
for dataset in result['datasets']:
if dataset['name'] == row.sales_stage:
dataset['values'][source_index] = row.compound_amount
return result
else:
return 'empty'
@frappe.whitelist()
def get_pipeline_data(from_date, to_date, company):
opportunities = frappe.get_all("Opportunity", filters=[['status', 'in', ['Open', 'Quotation', 'Replied']], ['company', '=', company], ['transaction_date', 'Between', [from_date, to_date]]], fields=['currency', 'sales_stage', 'opportunity_amount', 'probability'])
if opportunities:
default_currency = frappe.get_cached_value('Global Defaults', 'None', 'default_currency')
cp_opportunities = [dict(x, **{'compound_amount': (convert(x['opportunity_amount'], x['currency'], default_currency, to_date) * x['probability']/100)}) for x in opportunities]
df = pd.DataFrame(cp_opportunities).groupby(['sales_stage'], as_index=True).agg({'compound_amount': 'sum'}).to_dict()
result = {}
result['labels'] = df['compound_amount'].keys()
result['datasets'] = []
result['datasets'].append({'name': _("Total Amount"), 'values': df['compound_amount'].values(), 'chartType': 'bar'})
return result
else:
return 'empty'

View File

@@ -29,9 +29,9 @@ def execute(filters=None):
if customer_naming_type == "Naming Series":
row = [d.name, d.customer_name, credit_limit, outstanding_amt, bal,
d.bypass_credit_limit_check_at_sales_order]
d.bypass_credit_limit_check_at_sales_order, d.disabled]
else:
row = [d.name, credit_limit, outstanding_amt, bal, d.bypass_credit_limit_check_at_sales_order]
row = [d.name, credit_limit, outstanding_amt, bal, d.bypass_credit_limit_check_at_sales_order, d.disabled]
if credit_limit:
data.append(row)
@@ -40,11 +40,13 @@ def execute(filters=None):
def get_columns(customer_naming_type):
columns = [
_("Name") + ":Link/Customer:120",
_("Customer") + ":Link/Customer:120",
_("Credit Limit") + ":Currency:120",
_("Outstanding Amt") + ":Currency:100",
_("Credit Balance") + ":Currency:120",
_("Bypass credit check at Sales Order ") + ":Check:240"
_("Bypass credit check at Sales Order ") + ":Check:240",
_("Is Disabled ") + ":Check:240"
]
if customer_naming_type == "Naming Series":
@@ -59,5 +61,5 @@ def get_details(filters):
conditions += " where name = %(customer)s"
return frappe.db.sql("""select name, customer_name,
bypass_credit_limit_check_at_sales_order from `tabCustomer` %s
bypass_credit_limit_check_at_sales_order,disabled from `tabCustomer` %s
""" % conditions, filters, as_dict=1)

View File

@@ -17,7 +17,7 @@ def execute(filters=None):
for d in entries:
if d.stock_qty > 0 or filters.get('show_return_entries', 0):
data.append([
d.name, d.customer, d.territory, d.posting_date, d.item_code,
d.name, d.customer, d.territory, item_details.get(d.item_code, {}).get("website_warehouse"), d.posting_date, d.item_code,
item_details.get(d.item_code, {}).get("item_group"), item_details.get(d.item_code, {}).get("brand"),
d.stock_qty, d.base_net_amount, d.sales_person, d.allocated_percentage, d.contribution_amt
])
@@ -33,7 +33,8 @@ def get_columns(filters):
msgprint(_("Please select the document type first"), raise_exception=1)
return [filters["doc_type"] + ":Link/" + filters["doc_type"] + ":140",
_("Customer") + ":Link/Customer:140", _("Territory") + ":Link/Territory:100", _("Posting Date") + ":Date:100",
_("Customer") + ":Link/Customer:140", _("Territory") + ":Link/Territory:100", _("Warehouse") + ":Link/Warehouse:100",
_("Posting Date") + ":Date:100",
_("Item Code") + ":Link/Item:120", _("Item Group") + ":Link/Item Group:120",
_("Brand") + ":Link/Brand:120", _("Qty") + ":Float:100", _("Amount") + ":Currency:120",
_("Sales Person") + ":Link/Sales Person:140", _("Contribution %") + "::110",
@@ -115,7 +116,7 @@ def get_items(filters):
def get_item_details():
item_details = {}
for d in frappe.db.sql("""select name, item_group, brand from `tabItem`""", as_dict=1):
for d in frappe.db.sql("""select name, item_group, brand, website_warehouse from `tabItem`""", as_dict=1):
item_details.setdefault(d.name, d)
return item_details

View File

@@ -264,7 +264,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
{
row.incentives = flt(
row.allocated_amount * row.commission_rate / 100.0,
precision("incentives", sales_person));
precision("incentives", row));
}
},

View File

@@ -166,13 +166,12 @@ class NamingSeries(Document):
def parse_naming_series(self):
parts = self.prefix.split('.')
# If series contain date format like INV.YYYY.MM.#####
if len(parts) > 2:
del parts[-1] # Removed ### from the series
prefix = parse_naming_series(parts)
else:
prefix = parts[0]
# Remove ### from the end of series
if parts[-1] == "#" * len(parts[-1]):
del parts[-1]
prefix = parse_naming_series(parts)
return prefix
def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True):

View File

@@ -55,6 +55,10 @@ def set_default_settings(args):
buying_settings.allow_multiple_items = 1
buying_settings.save()
delivery_settings = frappe.get_doc("Delivery Settings")
delivery_settings.dispatch_template = _("Dispatch Notification")
delivery_settings.save()
hr_settings = frappe.get_doc("HR Settings")
hr_settings.emp_created_by = "Naming Series"
hr_settings.leave_approval_notification_template = _("Leave Approval Notification")

View File

@@ -231,7 +231,7 @@ def install(country=None):
# Share Management
{"doctype": "Share Type", "title": _("Equity")},
{"doctype": "Share Type", "title": _("Preference")},
{"doctype": "Share Type", "title": _("Preference")}
]
from erpnext.setup.setup_wizard.data.industry_type import get_industry_types
@@ -250,6 +250,12 @@ def install(country=None):
records += [{'doctype': 'Email Template', 'name': _("Leave Status Notification"), 'response': response,\
'subject': _("Leave Status Notification"), 'owner': frappe.session.user}]
base_path = frappe.get_app_path("erpnext", "stock", "doctype")
response = frappe.read_file(os.path.join(base_path, "delivery_trip/dispatch_notification_template.html"))
records += [{'doctype': 'Email Template', 'name': _("Dispatch Notification"), 'response': response,\
'subject': _("Your order is out for delivery!"), 'owner': frappe.session.user}]
# Records for the Supplier Scorecard
from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import make_default_records
make_default_records()
@@ -292,6 +298,30 @@ def add_uom_data():
"value": d.get("value")
}).insert(ignore_permissions=True)
def add_market_segments():
records = [
# Market Segments
{"doctype": "Market Segment", "market_segment": _("Lower Income")},
{"doctype": "Market Segment", "market_segment": _("Middle Income")},
{"doctype": "Market Segment", "market_segment": _("Upper Income")}
]
make_fixture_records(records)
def add_sale_stages():
# Sale Stages
records = [
{"doctype": "Sales Stage", "stage_name": _("Prospecting")},
{"doctype": "Sales Stage", "stage_name": _("Qualification")},
{"doctype": "Sales Stage", "stage_name": _("Needs Analysis")},
{"doctype": "Sales Stage", "stage_name": _("Value Proposition")},
{"doctype": "Sales Stage", "stage_name": _("Identifying Decision Makers")},
{"doctype": "Sales Stage", "stage_name": _("Perception Analysis")},
{"doctype": "Sales Stage", "stage_name": _("Proposal/Price Quote")},
{"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")}
]
make_fixture_records(records)
def make_fixture_records(records):
from frappe.modules import scrub
for r in records:
@@ -332,4 +362,4 @@ def install_post_company_fixtures(company=None):
{'doctype': 'Department', 'department_name': _('Legal'), 'parent_department': _('All Departments'), 'company': company},
]
make_fixture_records(records)
make_fixture_records(records)

View File

@@ -104,6 +104,8 @@ def setup_complete(args=None):
def stage_fixtures(args):
install_fixtures.install(args.get("country"))
install_fixtures.add_market_segments()
install_fixtures.add_sale_stages()
def setup_company(args):
defaults_setup.create_price_lists(args)

View File

@@ -460,6 +460,7 @@ def make_delivery_trip(source_name, target_doc=None):
target_doc.customer_address = source_parent.shipping_address
target_doc.contact = source_parent.contact_person
target_doc.customer_contact = source_parent.contact_display
target_doc.grand_total = source_parent.grand_total
# Append unique Delivery Notes in Delivery Trip
delivery_notes.append(target_doc.delivery_note)

View File

@@ -14,7 +14,7 @@ def get_data():
'transactions': [
{
'label': _('Related'),
'items': ['Sales Invoice', 'Packing Slip']
'items': ['Sales Invoice', 'Packing Slip', 'Delivery Trip']
},
{
'label': _('Reference'),

View File

@@ -0,0 +1,8 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Delivery Settings', {
refresh: function(frm) {
}
});

View File

@@ -0,0 +1,194 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2018-09-04 23:01:34.458550",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"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,
"fieldname": "sb_dispatch",
"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,
"label": "Dispatch Settings",
"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": "dispatch_template",
"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": "Dispatch Notification Template",
"length": 0,
"no_copy": 0,
"options": "Email Template",
"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": "send_with_attachment",
"description": "Leave blank to use the standard Delivery Note format",
"fieldname": "dispatch_attachment",
"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": "Dispatch Notification Attachment",
"length": 0,
"no_copy": 0,
"options": "Print Format",
"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": "send_with_attachment",
"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": "Send with Attachment",
"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,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2018-09-05 00:16:23.569855",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Settings",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 0,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class DeliverySettings(Document):
pass

View File

@@ -0,0 +1,23 @@
/* eslint-disable */
// rename this file from _test_[name] to test_[name] to activate
// and remove above this line
QUnit.test("test: Delivery Settings", function (assert) {
let done = assert.async();
// number of asserts
assert.expect(1);
frappe.run_serially([
// insert a new Delivery Settings
() => frappe.tests.make('Delivery Settings', [
// values to be set
{key: 'value'}
]),
() => {
assert.equal(cur_frm.doc.key, 'value');
},
() => done()
]);
});

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
class TestDeliverySettings(unittest.TestCase):
pass

View File

@@ -18,7 +18,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"columns": 2,
"fieldname": "customer",
"fieldtype": "Link",
"hidden": 0,
@@ -78,6 +78,38 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "lock",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Lock",
"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,
@@ -148,7 +180,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_7",
"fieldname": "order_information_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -157,6 +189,135 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Order Information",
"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": "delivery_note",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Delivery Note",
"length": 0,
"no_copy": 1,
"options": "Delivery Note",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"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": "cb_order",
"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,
"fieldname": "grand_total",
"fieldtype": "Currency",
"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": "Grand Total",
"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": "section_break_7",
"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,
"label": "Contact Information",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -186,7 +347,7 @@
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Contact Name",
"length": 0,
@@ -205,6 +366,38 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "email_sent_to",
"fieldtype": "Data",
"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 sent to",
"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,
@@ -284,6 +477,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Dispatch Information",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -362,196 +556,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,
"fieldname": "section_break_12",
"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,
"fieldname": "delivery_note",
"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": "Delivery Note",
"length": 0,
"no_copy": 1,
"options": "Delivery Note",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"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": "section_break_14",
"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": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "notified_by_email",
"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": "Notified by Email",
"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": "column_break_18",
"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,
"fieldname": "email_sent_to",
"fieldtype": "Data",
"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 sent to",
"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
}
],
"has_web_view": 0,
@@ -564,7 +568,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-08-21 22:25:53.276548",
"modified": "2018-09-05 00:51:55.275009",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Stop",

Some files were not shown because too many files have changed in this diff Show More