Compare commits

..

75 Commits

Author SHA1 Message Date
Nabin Hait
bdfc074a7d Merge branch 'hotfix' 2017-10-25 14:02:33 +05:30
Nabin Hait
c7bd77111e bumped to version 9.1.8 2017-10-25 14:32:32 +06:00
rohitwaghchaure
4a60554b91 Green indicator in the cart for non stock item (#11325) 2017-10-25 13:59:29 +05:30
rohitwaghchaure
3dc21b099d [Fix] Translation issue (#11323) 2017-10-25 12:38:17 +05:30
tundebabzy
40a02769c5 Error in the Address fetched in Sales Order.(#11129) (#11145)
* add new function - `get_party_shipping_address`

* `swap `get_default_address` with `get_party_shipping_address`

* test cases

* properly sets order by direction

* move `get_party_shipping_address` to party.py

* fix test module import
2017-10-25 12:24:34 +05:30
Makarand Bauskar
e6712c129c [hotfix] fixed Permissions Error while fetching allow_stale field value from Accounts Settings (#11182)
* [hotfix] fixed Permissions Error while fetching allow_stale field value from Accounts Settings

* [minor] renamed the allow_stale_rate method to stale_rate_allowed
2017-10-25 12:17:40 +05:30
Manas Solanki
464289b726 copy the older total amount field and corrsp. changes in report (#11322) 2017-10-25 12:13:42 +05:30
Nabin Hait
1c1237537b Subscription fixes (#11292)
* Subscription fixes

* Removed recurring fields, cleanup code
2017-10-25 12:10:44 +05:30
Nabin Hait
b7483f6dfd Update item.json 2017-10-25 11:58:02 +05:30
tundebabzy
cba7a11d75 Make Variant does not copy UOM properties (#10887) (#11261)
* add `uoms` to Item Variant Settings if not already added

* add new patch to patch list

* change uoms field to no_copy:0
2017-10-25 11:57:10 +05:30
rohitwaghchaure
2672c331af Validation for duplicate offline pos (#11281) 2017-10-25 11:47:18 +05:30
Nabin Hait
f4283a3ebf Moved company field to the top in BOM (#11283) 2017-10-25 11:46:47 +05:30
Nabin Hait
8a0943ead7 Unlink reference doc on Journal Cancellation only if advance (#11285) 2017-10-25 11:46:35 +05:30
Nabin Hait
82c9352d53 Update variant description based on attribute if not already there (#11302) 2017-10-25 11:46:20 +05:30
rohitwaghchaure
311823aca1 Validate stock exists against template item (#11305) 2017-10-25 11:45:51 +05:30
Nabin Hait
6c06e700d6 [Fix] Unallocated amount considering deductions (#11314) 2017-10-25 11:42:05 +05:30
Nabin Hait
b88b7eaf5b Merge branch 'hotfix' 2017-10-21 11:29:40 +05:30
Nabin Hait
e7eda65968 bumped to version 9.1.7 2017-10-21 11:59:39 +06:00
rohitwaghchaure
5fdd26f1e7 [fix] Discount amount not reset for new order in offline pos (#11258) 2017-10-21 11:23:45 +05:30
Nabin Hait
c44290955e Minor fix in patches (#11268) 2017-10-21 11:20:18 +05:30
Saurabh
12e817bad6 Merge branch 'hotfix' 2017-10-18 16:23:43 +05:30
Saurabh
47e405516b bumped to version 9.1.6 2017-10-18 16:53:43 +06:00
Saurabh
4272483f2d Merge pull request #11246 from saurabh6790/item_variant_description_fix
[minor-fix] patch fix
2017-10-18 16:15:43 +05:30
Saurabh
3173be9b17 [minor-fix] patch fix 2017-10-18 16:14:20 +05:30
Saurabh
9cb817874d Merge pull request #11245 from saurabh6790/item_variant_description_fix
[fix] remove explicit variant save
2017-10-18 16:08:23 +05:30
Saurabh
8227422124 [fix] remove explicit variant save 2017-10-18 16:03:40 +05:30
Saurabh
a7d5f94d4a [fix] Do not append description to variant if description already exists (#11204) 2017-10-18 16:02:08 +05:30
Ranjith Kurungadam
7624e7bf85 [hot-fix] sql getting translated (#11243)
* fix remove _ in frappe.sql

* use %s replacement for sql
2017-10-18 15:48:12 +05:30
Makarand Bauskar
3e4ca4219f [hotfix] fixed 'ValueError: Unknown string format' error if the from_time value is null (#11162) 2017-10-18 11:16:47 +05:30
Nabin Hait
5ab6ff2470 [fix] Fetch raw material rate based on last purchase rate (#11205)
* [fix] Fetch raw material rate based on last purchase rate

* Don't fetch sub-assembly item rate from BOM if not mentioned by the user
2017-10-18 11:09:11 +05:30
rohitwaghchaure
a516856c32 [Fix] Getting an error duplicate name while making an invoice in draft mode (#11230) 2017-10-18 11:05:10 +05:30
rohitwaghchaure
a3fe5b8528 [Fix] Disable desk access view to supplier (#11234) 2017-10-18 10:53:34 +05:30
Nabin Hait
45a640df08 Update payment_entry_reference.json 2017-10-16 12:58:32 +05:30
Makarand Bauskar
80f333950b [minor] fixed AttributeError: 'GrossProfitGenerator' object has no attribute 'grouped_data' (#11195) 2017-10-16 11:27:22 +05:30
mbauskar
d3214fed57 Merge branch 'hotfix' 2017-10-15 19:10:55 +05:30
mbauskar
bbbce58884 bumped to version 9.1.5 2017-10-15 19:40:55 +06:00
rohitwaghchaure
8bf7230fcc [Fix] New invoice showing old paid amount if POS Profile is not created (#11160) 2017-10-15 19:09:14 +05:30
rohitwaghchaure
496174bbdf [Fix] Naming series not copy from referebce document to new document in subscription (#11196) 2017-10-15 19:08:42 +05:30
Saurabh
8854438830 Merge branch 'hotfix' 2017-10-11 14:39:10 +05:30
Saurabh
15411fcf70 bumped to version 9.1.4 2017-10-11 15:09:10 +06:00
rohitwaghchaure
76a9cefc9c Merge pull request #11151 from rohitwaghchaure/minor_fix_title
[minor] Title not showing in payment modal
2017-10-11 12:05:29 +05:30
Rohit Waghchaure
4f7873b9df [minor] Title not showing in payment modal 2017-10-11 12:03:49 +05:30
Saurabh
ad9afe68f3 Merge pull request #11119 from rohitwaghchaure/default_company_pos
[enhance] Provision to select company in the POS screen if company is not defined in the global defaults
2017-10-11 12:00:56 +05:30
Saurabh
41e2b98b63 Merge pull request #11137 from mbauskar/healthcare
[hotfix] passed localise item_group value for create_lab_test_itemsfield
2017-10-11 12:00:12 +05:30
rohitwaghchaure
4eb5286c4b Merge pull request #11147 from rohitwaghchaure/total_amount_and_barcode_issue_pos
[Fix] Barcode and total amount issue in online POS
2017-10-11 11:13:30 +05:30
Rohit Waghchaure
3f309e1c20 Multiple items showing for single barcode 2017-10-11 02:14:56 +05:30
Rohit Waghchaure
9bb81ee1cb [fix] Total amount showing wrong in the payment modal if user has changed the qty after payment 2017-10-11 01:54:36 +05:30
Makarand Bauskar
4cdb9dee09 [minor] changed the modified date for the subscription doctype (#11142) 2017-10-10 18:41:00 +05:30
mbauskar
ee9da67173 [hotfix] passed localize item_group value for create_lab_test_itemsfield 2017-10-10 12:20:45 +05:30
Saurabh
e78601b040 Merge branch 'hotfix' 2017-10-10 11:22:38 +05:30
Saurabh
47b2a5f7d1 bumped to version 9.1.3 2017-10-10 11:52:38 +06:00
Saurabh
5ba4c4c49c Merge pull request #11132 from saurabh6790/upload_attendance_tool
[fix] upload attendance with with no_socketio param
2017-10-10 11:15:27 +05:30
Saurabh
f347e23556 [fix] upload attendacne with with no_socketio param 2017-10-09 16:13:21 +05:30
mbauskar
fbbb8695f3 Merge branch 'hotfix' 2017-10-09 15:18:52 +05:30
mbauskar
f9577652a0 bumped to version 9.1.2 2017-10-09 15:48:51 +06:00
Rohit Waghchaure
d270748eea [Fix] Provision to select company in the POS screen if company is not defined in the global defaults 2017-10-09 12:54:26 +05:30
tundebabzy
2622d370c6 deal zero division possibility (#11098) 2017-10-09 12:44:24 +05:30
rohitwaghchaure
e181dd4c24 [patch] To add healthcare domain (#11105) 2017-10-09 12:43:36 +05:30
tundebabzy
7f9d75521e Confirmation desired before cancelling appointment (#10996) (#11106)
* shows confirm dialog when user clicks cancel

* indentation and frm as per review
2017-10-09 12:43:18 +05:30
Makarand Bauskar
eaf0abedd4 [hotfix] ignore if student email address field value is None (#11116) 2017-10-09 12:42:18 +05:30
rohitwaghchaure
6f5853b97a Merge pull request #11092 from rohitwaghchaure/pos_total_issue
Show total instead of net total
2017-10-06 11:17:24 +05:30
Rohit Waghchaure
62ce218fc2 Show total instead of net total 2017-10-06 11:16:46 +05:30
rohitwaghchaure
1b0f3ec666 Merge pull request #11089 from rohitwaghchaure/offline_pos_v9
[Fix] Discount field not displaying in offline POS
2017-10-06 09:51:30 +05:30
Rohit Waghchaure
beeba8b37a [Fix] Discount field not displaying in offline POS 2017-10-06 09:50:43 +05:30
rohitwaghchaure
d7636b2b19 Merge pull request #11083 from rohitwaghchaure/pos_print_format_issue
[fix] Online print format in pos profile field not displaying
2017-10-06 09:44:27 +05:30
Rohit Waghchaure
b870d0081b [fix] Online print format in pos profile field not displaying 2017-10-06 09:31:40 +05:30
rohitwaghchaure
e0dfd1608e [Fix] Auto add item in the cart if sinfle items found in the serach (#11072) 2017-10-05 18:30:51 +05:30
rohitwaghchaure
607b5d4985 [Fix] Negative qty issue in POS (#11070)
* [Fix] Negative qty issue in POS

* Update point_of_sale.js
2017-10-05 15:57:58 +05:30
Makarand Bauskar
f23788bb7d [hotfix] Show Make button only for Email communication (#10876) 2017-10-05 14:19:45 +05:30
mbauskar
671c6610de Merge branch 'hotfix' 2017-10-05 13:36:49 +05:30
mbauskar
8c3d19e2ab bumped to version 9.1.1 2017-10-05 14:06:49 +06:00
rohitwaghchaure
4a5ac7cea6 Merge pull request #11066 from rohitwaghchaure/pos_loading_issue
[Fix] Rate not fetched in the POS, User trying to add an item in the cart before loading of frm
2017-10-05 13:34:22 +05:30
Rohit Waghchaure
f7a856b913 [Fix] Rate not fetched in the POS, User trying to add an item in the cart before loading of frm 2017-10-05 13:31:29 +05:30
Nabin Hait
7d4fd35aa3 Add POS Settings link in Accounts module (#11060) 2017-10-05 12:20:33 +05:30
rohitwaghchaure
e87a076f1d Update link in the pos for offline and online mode from pos settings (#11061) 2017-10-05 12:20:20 +05:30
58 changed files with 912 additions and 2033 deletions

View File

@@ -4,7 +4,7 @@ import inspect
import frappe
from erpnext.hooks import regional_overrides
__version__ = '9.1.0'
__version__ = '9.1.8'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -54,7 +54,7 @@ class JournalEntry(AccountsController):
def update_advance_paid(self):
advance_paid = frappe._dict()
for d in self.get("accounts"):
if d.is_advance:
if d.is_advance == "Yes":
if d.reference_type in ("Sales Order", "Purchase Order"):
advance_paid.setdefault(d.reference_type, []).append(d.reference_name)
@@ -76,7 +76,7 @@ class JournalEntry(AccountsController):
def unlink_advance_entry_reference(self):
for d in self.get("accounts"):
if d.is_advance and d.reference_type in ("Sales Invoice", "Purchase Invoice"):
if d.is_advance == "Yes" and d.reference_type in ("Sales Invoice", "Purchase Invoice"):
doc = frappe.get_doc(d.reference_type, d.reference_name)
doc.delink_advance_entries(self.name)
d.reference_type = ''

View File

@@ -405,11 +405,7 @@ frappe.ui.form.on('Payment Entry', {
}
// Make read only if Accounts Settings doesn't allow stale rates
frappe.model.get_value("Accounts Settings", null, "allow_stale",
function(d){
frm.set_df_property("source_exchange_rate", "read_only", cint(d.allow_stale) ? 0 : 1);
}
);
frm.set_df_property("source_exchange_rate", "read_only", erpnext.stale_rate_allowed());
},
target_exchange_rate: function(frm) {
@@ -430,11 +426,7 @@ frappe.ui.form.on('Payment Entry', {
frm.set_paid_amount_based_on_received_amount = false;
// Make read only if Accounts Settings doesn't allow stale rates
frappe.model.get_value("Accounts Settings", null, "allow_stale",
function(d){
frm.set_df_property("target_exchange_rate", "read_only", cint(d.allow_stale) ? 0 : 1);
}
);
frm.set_df_property("target_exchange_rate", "read_only", erpnext.stale_rate_allowed());
},
paid_amount: function(frm) {
@@ -660,8 +652,15 @@ frappe.ui.form.on('Payment Entry', {
var party_amount = frm.doc.payment_type=="Receive" ?
frm.doc.paid_amount : frm.doc.received_amount;
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
function(d) { return flt(d.amount) }));
if(frm.doc.total_allocated_amount < party_amount) {
unallocated_amount = party_amount - frm.doc.total_allocated_amount;
if(frm.doc.payment_type == "Receive") {
unallocated_amount = party_amount - (frm.doc.total_allocated_amount - total_deductions);
} else {
unallocated_amount = party_amount - (frm.doc.total_allocated_amount + total_deductions);
}
}
}
frm.set_value("unallocated_amount", unallocated_amount);
@@ -680,9 +679,6 @@ frappe.ui.form.on('Payment Entry', {
difference_amount = flt(frm.doc.base_paid_amount) - flt(frm.doc.base_received_amount);
}
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
function(d) { return flt(d.amount) }));
frm.set_value("difference_amount", difference_amount - total_deductions);
frm.events.hide_unhide_fields(frm);

View File

@@ -285,8 +285,13 @@ class PaymentEntry(AccountsController):
if self.party:
party_amount = self.paid_amount if self.payment_type=="Receive" else self.received_amount
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
if self.total_allocated_amount < party_amount:
self.unallocated_amount = party_amount - self.total_allocated_amount
if self.payment_type == "Receive":
self.unallocated_amount = party_amount - (self.total_allocated_amount - total_deductions)
else:
self.unallocated_amount = party_amount - (self.total_allocated_amount + total_deductions)
def set_difference_amount(self):
base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)

View File

@@ -296,7 +296,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-09-04 17:37:01.192312",
"modified": "2017-10-16 17:37:01.192312",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry Reference",
@@ -311,4 +311,4 @@
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}
}

View File

@@ -37,10 +37,10 @@ frappe.ui.form.on('POS Profile', {
return { filters: { doc_type: "Sales Invoice", print_format_type: "Js"} };
});
frappe.db.get_value('POS Settings', {name: 'POS Settings'}, 'is_online', (r) => {
is_online = r && cint(r.is_online)
frm.toggle_display('offline_pos_section', !is_online);
frm.toggle_display('print_format_for_online', is_online);
frappe.db.get_value('POS Settings', {name: 'POS Settings'}, 'use_pos_in_offline_mode', (r) => {
is_offline = r && cint(r.use_pos_in_offline_mode)
frm.toggle_display('offline_pos_section', is_offline);
frm.toggle_display('print_format_for_online', !is_offline);
});
},

View File

@@ -3,7 +3,17 @@
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class POSSettings(Document):
pass
def validate(self):
self.set_link_for_pos()
def set_link_for_pos(self):
link = 'pos' if self.use_pos_in_offline_mode else 'point-of-sale'
desktop_icon = frappe.db.get_value('Desktop Icon',
{'standard': 1, 'module_name': 'POS'}, 'name')
if desktop_icon:
frappe.db.set_value('Desktop Icon', desktop_icon, 'link', link)

View File

@@ -3440,139 +3440,13 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "subscription",
"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": "Subscription",
"length": 0,
"no_copy": 1,
"options": "Subscription",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"collapsible_depends_on": "is_recurring",
"columns": 0,
"depends_on": "eval:doc.docstatus<2 && !doc.__islocal",
"fieldname": "recurring_invoice",
"fieldtype": "Section Break",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Recurring Invoice",
"length": 0,
"no_copy": 0,
"options": "fa fa-time",
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.docstatus<2",
"description": "",
"fieldname": "is_recurring",
"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": "Is Recurring",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring==1",
"description": "Select the period when the invoice will be generated automatically",
"fieldname": "recurring_type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Recurring Type",
"length": 0,
"no_copy": 1,
"options": "Monthly\nQuarterly\nHalf-yearly\nYearly",
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring==1",
"depends_on": "",
"description": "Start date of current invoice's period",
"fieldname": "from_date",
"fieldtype": "Date",
@@ -3603,7 +3477,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring==1",
"depends_on": "",
"description": "End date of current invoice's period",
"fieldname": "to_date",
"fieldtype": "Date",
@@ -3628,138 +3502,13 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"fieldname": "submit_on_creation",
"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": "Submit on creation",
"length": 0,
"no_copy": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "notify_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": "Notify by email",
"length": 0,
"no_copy": 1,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring==1",
"description": "The day of the month on which auto invoice will be generated e.g. 05, 28 etc",
"fieldname": "repeat_on_day_of_month",
"fieldtype": "Int",
"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": "Repeat on Day of Month",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring==1",
"description": "The date on which recurring invoice will be stop",
"fieldname": "end_date",
"fieldtype": "Date",
"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": "End Date",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_82",
"fieldname": "column_break_114",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -3771,101 +3520,8 @@
"length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
"unique": 0,
"width": "50%"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring==1",
"description": "The date on which next invoice will be generated. It is generated on submit.",
"fieldname": "next_date",
"fieldtype": "Date",
"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": "Next Date",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring==1",
"description": "The unique id for tracking all recurring invoices. It is generated on submit.",
"fieldname": "recurring_id",
"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": "Recurring Id",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring==1",
"description": "Enter Email Address separated by commas, invoice will be mailed automatically on particular date",
"fieldname": "notification_email_address",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Notification Email Address",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"print_hide": 1,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
@@ -3881,8 +3537,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring==1",
"fieldname": "recurring_print_format",
"fieldname": "subscription",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -3891,15 +3546,15 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Recurring Print Format",
"label": "Subscription",
"length": 0,
"no_copy": 0,
"options": "Print Format",
"no_copy": 1,
"options": "Subscription",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -3920,7 +3575,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2017-09-19 11:22:47.074420",
"modified": "2017-10-24 12:51:51.199594",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",

View File

@@ -88,7 +88,7 @@ def update_pos_profile_data(doc, pos_profile, company_data):
doc.naming_series = pos_profile.get('naming_series') or 'SINV-'
doc.letter_head = pos_profile.get('letter_head') or company_data.default_letter_head
doc.ignore_pricing_rule = pos_profile.get('ignore_pricing_rule') or 0
doc.apply_discount_on = pos_profile.get('apply_discount_on') if pos_profile.get('apply_discount') else ''
doc.apply_discount_on = pos_profile.get('apply_discount_on') or 'Grand Total'
doc.customer_group = pos_profile.get('customer_group') or get_root('Customer Group')
doc.territory = pos_profile.get('territory') or get_root('Territory')
doc.terms = frappe.db.get_value('Terms and Conditions', pos_profile.get('tc_name'), 'terms') or doc.terms or ''
@@ -486,17 +486,21 @@ def submit_invoice(si_doc, name, doc, name_list):
if frappe.message_log: frappe.message_log.pop()
frappe.db.rollback()
frappe.log_error(frappe.get_traceback())
name_list = save_invoice(e, si_doc, name, name_list)
name_list = save_invoice(doc, name, name_list)
return name_list
def save_invoice(e, si_doc, name, name_list):
def save_invoice(doc, name, name_list):
try:
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
si_doc.docstatus = 0
si_doc.flags.ignore_mandatory = True
si_doc.due_date = si_doc.posting_date
si_doc.insert()
si = frappe.new_doc('Sales Invoice')
si.update(doc)
si.set_posting_time = 1
si.customer = get_customer_id(doc)
si.due_date = doc.get('posting_date')
si.flags.ignore_mandatory = True
si.insert(ignore_permissions=True)
frappe.db.commit()
name_list.append(name)
except Exception:
frappe.log_error(frappe.get_traceback())

View File

@@ -4273,414 +4273,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "subscription",
"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": "Subscription",
"length": 0,
"no_copy": 1,
"options": "Subscription",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"collapsible_depends_on": "is_recurring",
"columns": 0,
"depends_on": "eval:doc.docstatus<2 && !doc.__islocal",
"fieldname": "recurring_invoice",
"fieldtype": "Section Break",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Recurring Invoice",
"length": 0,
"no_copy": 0,
"options": "fa fa-time",
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break11",
"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,
"label": "Settings",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
"unique": 0,
"width": "50%"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.docstatus<2",
"description": "",
"fieldname": "is_recurring",
"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": "Is Recurring",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_recurring",
"description": "",
"fieldname": "recurring_id",
"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": "Reference Document",
"length": 0,
"no_copy": 1,
"options": "Sales Invoice",
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "recurring_type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Frequency",
"length": 0,
"no_copy": 1,
"options": "\nMonthly\nQuarterly\nHalf-yearly\nYearly",
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "repeat_on_day_of_month",
"fieldtype": "Int",
"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": "Repeat on Day of Month",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "end_date",
"fieldtype": "Date",
"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": "End Date",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"fieldname": "submit_on_creation",
"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": "Submit on creation",
"length": 0,
"no_copy": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "notify_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": "Notify by email",
"length": 0,
"no_copy": 1,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.notify_by_email && doc.recurring_id === doc.name",
"description": "",
"fieldname": "notification_email_address",
"fieldtype": "Code",
"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": "Notification Email Address",
"length": 0,
"no_copy": 1,
"options": "Email",
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.notify_by_email && doc.recurring_id === doc.name",
"fieldname": "recurring_print_format",
"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": "Recurring Print Format",
"length": 0,
"no_copy": 0,
"options": "Print Format",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break12",
"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,
"label": "This Document",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
"unique": 0,
"width": "50%"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_recurring",
"depends_on": "",
"description": "",
"fieldname": "from_date",
"fieldtype": "Date",
@@ -4711,7 +4304,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_recurring",
"depends_on": "",
"description": "",
"fieldname": "to_date",
"fieldtype": "Date",
@@ -4742,10 +4335,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_recurring",
"description": "",
"fieldname": "next_date",
"fieldtype": "Date",
"fieldname": "column_break_140",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -4753,11 +4344,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Next Date",
"length": 0,
"no_copy": 1,
"no_copy": 0,
"permlevel": 0,
"print_hide": 1,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
@@ -4767,6 +4358,37 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "subscription",
"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": "Subscription",
"length": 0,
"no_copy": 1,
"options": "Subscription",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@@ -4811,7 +4433,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2017-09-19 11:23:08.675028",
"modified": "2017-10-24 12:46:48.331723",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -70,6 +70,7 @@ class SalesInvoice(SellingController):
self.clear_unallocated_advances("Sales Invoice Advance", "advances")
self.add_remarks()
self.validate_write_off_account()
self.validate_duplicate_offline_pos_entry()
self.validate_account_for_change_amount()
self.validate_fixed_asset()
self.set_income_account_for_fixed_assets()
@@ -462,6 +463,12 @@ class SalesInvoice(SellingController):
if flt(self.write_off_amount) and not self.write_off_account:
msgprint(_("Please enter Write Off Account"), raise_exception=1)
def validate_duplicate_offline_pos_entry(self):
if self.is_pos and self.offline_pos_name \
and frappe.db.get_value('Sales Invoice',
{'offline_pos_name': self.offline_pos_name, 'docstatus': 1}):
frappe.throw(_("Duplicate offline pos sales invoice {0}").format(self.offline_pos_name))
def validate_account_for_change_amount(self):
if flt(self.change_amount) and not self.account_for_change_amount:
msgprint(_("Please enter Account for Change Amount"), raise_exception=1)

View File

@@ -3,8 +3,8 @@
from __future__ import unicode_literals
import frappe
import unittest, copy
from frappe.utils import nowdate, add_days, flt
import unittest, copy, time
from frappe.utils import nowdate, add_days, flt, cint
from frappe.model.dynamic_links import get_dynamic_link_map
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
@@ -665,6 +665,47 @@ class TestSalesInvoice(unittest.TestCase):
self.pos_gl_entry(si, pos, 330)
def test_make_pos_invoice_in_draft(self):
from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
from erpnext.stock.doctype.item.test_item import make_item
set_perpetual_inventory()
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
if allow_negative_stock:
frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 0)
make_pos_profile()
timestamp = cint(time.time())
item = make_item("_Test POS Item")
pos = copy.deepcopy(test_records[1])
pos['items'][0]['item_code'] = item.name
pos["is_pos"] = 1
pos["offline_pos_name"] = timestamp
pos["update_stock"] = 1
pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300},
{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 330}]
invoice_data = [{timestamp: pos}]
si = make_invoice(invoice_data).get('invoice')
self.assertEquals(si[0], timestamp)
sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp})
self.assertEquals(sales_invoice[0].docstatus, 0)
timestamp = cint(time.time())
pos["offline_pos_name"] = timestamp
invoice_data = [{timestamp: pos}]
si1 = make_invoice(invoice_data).get('invoice')
self.assertEquals(si1[0], timestamp)
sales_invoice1 = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp})
self.assertEquals(sales_invoice1[0].docstatus, 0)
if allow_negative_stock:
frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 1)
def pos_gl_entry(self, si, pos, cash_amount):
# check stock ledger entries
sle = frappe.db.sql("""select * from `tabStock Ledger Entry`

View File

@@ -12,7 +12,8 @@ frappe.ui.form.on('Subscription', {
frm.fields_dict['reference_document'].get_query = function() {
return {
filters: {
"docstatus": 1
"docstatus": 1,
"subscription": ''
}
};
};

View File

@@ -315,22 +315,23 @@
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "from_date",
"fieldtype": "Date",
"fieldname": "frequency",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "From Date",
"label": "Frequency",
"length": 0,
"no_copy": 0,
"options": "\nDaily\nWeekly\nMonthly\nQuarterly\nHalf-yearly\nYearly",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -338,37 +339,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "to_date",
"fieldtype": "Date",
"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": "To Date",
"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,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -402,37 +373,6 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "frequency",
"fieldtype": "Select",
"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": "Frequency",
"length": 0,
"no_copy": 0,
"options": "\nDaily\nWeekly\nMonthly\nQuarterly\nHalf-yearly\nYearly",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
@@ -844,7 +784,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-10-03 17:20:26.919630",
"modified": "2017-10-23 18:28:08.966403",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Subscription",

View File

@@ -17,6 +17,7 @@ month_map = {'Monthly': 1, 'Quarterly': 3, 'Half-yearly': 6, 'Yearly': 12}
class Subscription(Document):
def validate(self):
self.update_status()
self.validate_reference_doctype()
self.validate_dates()
self.validate_next_schedule_date()
self.validate_email_id()
@@ -25,25 +26,28 @@ class Subscription(Document):
validate_template(self.message or "")
def before_submit(self):
self.set_next_schedule_date()
if not self.next_schedule_date:
self.next_schedule_date = get_next_schedule_date(self.start_date,
self.frequency, self.repeat_on_day)
def on_submit(self):
# self.update_subscription_id()
self.update_subscription_data()
self.update_subscription_id()
def on_update_after_submit(self):
self.update_subscription_data()
self.validate_dates()
self.set_next_schedule_date()
def before_cancel(self):
self.unlink_subscription_id()
self.next_schedule_date = None
def unlink_subscription_id(self):
doc = frappe.get_doc(self.reference_doctype, self.reference_document)
if doc.meta.get_field('subscription'):
doc.subscription = None
doc.db_update()
frappe.db.sql("update `tab{0}` set subscription = null where subscription=%s"
.format(self.reference_doctype), self.name)
def validate_reference_doctype(self):
if not frappe.get_meta(self.reference_doctype).has_field('subscription'):
frappe.throw(_("Add custom field Subscription in the doctype {0}").format(self.reference_doctype))
def validate_dates(self):
if self.end_date and getdate(self.start_date) > getdate(self.end_date):
@@ -76,30 +80,11 @@ class Subscription(Document):
frappe.throw(_("'Recipients' not specified"))
def set_next_schedule_date(self):
self.next_schedule_date = get_next_schedule_date(self.start_date,
self.frequency, self.repeat_on_day)
def update_subscription_data(self):
update_doc = False
doc = frappe.get_doc(self.reference_doctype, self.reference_document)
if frappe.get_meta(self.reference_doctype).get_field("from_date"):
doc.from_date = self.from_date
doc.to_date = self.to_date
update_doc = True
if not doc.subscription:
doc.subscription = self.name
update_doc = True
if update_doc:
doc.db_update()
if self.repeat_on_day:
self.next_schedule_date = get_next_date(self.next_schedule_date, 0, self.repeat_on_day)
def update_subscription_id(self):
doc = frappe.get_doc(self.reference_doctype, self.reference_document)
if not doc.meta.get_field('subscription'):
frappe.throw(_("Add custom field Subscription Id in the doctype {0}").format(self.reference_doctype))
doc.db_set('subscription', self.name)
frappe.db.set_value(self.reference_doctype, self.reference_document, "subscription", self.name)
def update_status(self, status=None):
self.status = {
@@ -142,9 +127,6 @@ def get_subscription_entries(date):
def create_documents(data, schedule_date):
try:
doc = make_new_document(data, schedule_date)
if getattr(doc, "from_date", None):
update_subscription_period(data, doc)
if data.notify_by_email and data.recipients:
print_format = data.print_format or "Standard"
send_notification(doc, data, print_format=print_format)
@@ -159,13 +141,6 @@ def create_documents(data, schedule_date):
if data.reference_document and not frappe.flags.in_test:
notify_error_to_user(data)
def update_subscription_period(data, doc):
from_date = doc.from_date
to_date = doc.to_date
frappe.db.set_value('Subscription', data.name, 'from_date', from_date)
frappe.db.set_value('Subscription', data.name, 'to_date', to_date)
def disable_subscription(data):
subscription = frappe.get_doc('Subscription', data.name)
subscription.db_set('disabled', 1)
@@ -205,24 +180,49 @@ def update_doc(new_document, reference_doc, args, schedule_date):
if new_document.meta.get_field('subscription'):
new_document.set('subscription', args.name)
if args.from_date and args.to_date:
from_date = get_next_date(args.from_date, mcount)
for fieldname in ['naming_series', 'ignore_pricing_rule', 'posting_time'
'select_print_heading', 'remarks', 'owner']:
if new_document.meta.get_field(fieldname):
new_document.set(fieldname, reference_doc.get(fieldname))
if (cstr(get_first_day(args.from_date)) == cstr(args.from_date)) and \
(cstr(get_last_day(args.to_date)) == cstr(args.to_date)):
to_date = get_last_day(get_next_date(args.to_date, mcount))
else:
to_date = get_next_date(args.to_date, mcount)
# copy item fields
if new_document.meta.get_field('items'):
for i, item in enumerate(new_document.items):
for fieldname in ("page_break",):
item.set(fieldname, reference_doc.items[i].get(fieldname))
if new_document.meta.get_field('from_date'):
new_document.set('from_date', from_date)
new_document.set('to_date', to_date)
new_document.run_method("on_recurring", reference_doc=reference_doc, subscription_doc=args)
for data in new_document.meta.fields:
if data.fieldtype == 'Date' and data.reqd:
new_document.set(data.fieldname, schedule_date)
set_subscription_period(args, mcount, new_document)
new_document.run_method("on_recurring", reference_doc=reference_doc, subscription_doc=args)
def set_subscription_period(args, mcount, new_document):
if new_document.meta.get_field('from_date') and new_document.meta.get_field('to_date'):
last_ref_doc = frappe.db.sql("""
select name, from_date, to_date
from `tab{0}`
where subscription=%s and docstatus < 2
order by creation desc
limit 1
""".format(args.reference_doctype), args.name, as_dict=1)
if not last_ref_doc:
return
from_date = get_next_date(last_ref_doc[0].from_date, mcount)
if (cstr(get_first_day(last_ref_doc[0].from_date)) == cstr(last_ref_doc[0].from_date)) and \
(cstr(get_last_day(last_ref_doc[0].to_date)) == cstr(last_ref_doc[0].to_date)):
to_date = get_last_day(get_next_date(last_ref_doc[0].to_date, mcount))
else:
to_date = get_next_date(last_ref_doc[0].to_date, mcount)
new_document.set('from_date', from_date)
new_document.set('to_date', to_date)
def get_next_date(dt, mcount, day=None):
dt = getdate(dt)
dt += relativedelta(months=mcount, day=day)
@@ -276,8 +276,11 @@ def assign_task_to_owner(name, msg, users):
@frappe.whitelist()
def make_subscription(doctype, docname):
doc = frappe.new_doc('Subscription')
reference_doc = frappe.get_doc(doctype, docname)
doc.reference_doctype = doctype
doc.reference_document = docname
doc.start_date = reference_doc.get('posting_date') or reference_doc.get('transaction_date')
return doc
@frappe.whitelist()

View File

@@ -84,6 +84,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
this.get_data_from_server(function () {
me.make_control();
me.create_new();
me.make();
});
},
@@ -382,7 +383,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
},
setup: function () {
this.make();
this.set_primary_action();
this.party_field.$input.attr('disabled', false);
if(this.selected_row) {
@@ -1341,6 +1341,12 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
this.wrapper.find('input.discount-percentage').on("change", function () {
me.frm.doc.additional_discount_percentage = flt($(this).val(), precision("additional_discount_percentage"));
if(me.frm.doc.additional_discount_percentage && me.frm.doc.discount_amount) {
// Reset discount amount
me.frm.doc.discount_amount = 0;
}
var total = me.frm.doc.grand_total
if (me.frm.doc.apply_discount_on == 'Net Total') {
@@ -1348,15 +1354,15 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
}
me.frm.doc.discount_amount = flt(total * flt(me.frm.doc.additional_discount_percentage) / 100, precision("discount_amount"));
me.wrapper.find('input.discount-amount').val(me.frm.doc.discount_amount)
me.refresh();
me.wrapper.find('input.discount-amount').val(me.frm.doc.discount_amount)
});
this.wrapper.find('input.discount-amount').on("change", function () {
me.frm.doc.discount_amount = flt($(this).val(), precision("discount_amount"));
me.frm.doc.additional_discount_percentage = 0.0;
me.wrapper.find('input.discount-percentage').val(0);
me.refresh();
me.wrapper.find('input.discount-percentage').val(0);
});
},
@@ -1517,6 +1523,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
var me = this;
this.wrapper.find(".net-total").text(format_currency(me.frm.doc.total, me.frm.doc.currency));
this.wrapper.find(".grand-total").text(format_currency(me.frm.doc.grand_total, me.frm.doc.currency));
this.wrapper.find('input.discount-percentage').val(this.frm.doc.additional_discount_percentage);
this.wrapper.find('input.discount-amount').val(this.frm.doc.discount_amount);
},
set_primary_action: function () {

View File

@@ -76,7 +76,7 @@ def set_address_details(out, party, party_type, doctype=None, company=None):
# shipping address
if party_type in ["Customer", "Lead"]:
out.shipping_address_name = get_default_address(party_type, party.name, 'is_shipping_address')
out.shipping_address_name = get_party_shipping_address(party_type, party.name)
out.shipping_address = get_address_display(out["shipping_address_name"])
if doctype:
out.update(get_fetch_values(doctype, 'shipping_address_name', out.shipping_address_name))
@@ -418,3 +418,32 @@ def get_dashboard_info(party_type, party):
info["total_unpaid"] = -1 * info["total_unpaid"]
return info
def get_party_shipping_address(doctype, name):
"""
Returns an Address name (best guess) for the given doctype and name for which `address_type == 'Shipping'` is true.
and/or `is_shipping_address = 1`.
It returns an empty string if there is no matching record.
:param doctype: Party Doctype
:param name: Party name
:return: String
"""
out = frappe.db.sql(
'SELECT dl.parent '
'from `tabDynamic Link` dl join `tabAddress` ta on dl.parent=ta.name '
'where '
'dl.link_doctype=%s '
'and dl.link_name=%s '
'and dl.parenttype="Address" '
'and '
'(ta.address_type="Shipping" or ta.is_shipping_address=1) '
'order by ta.is_shipping_address desc, ta.address_type desc limit 1',
(doctype, name)
)
if out:
return out[0][0]
else:
return ''

View File

@@ -107,6 +107,8 @@ class GrossProfitGenerator(object):
def process(self):
self.grouped = {}
self.grouped_data = []
for row in self.si_list:
if self.skip_row(row, self.product_bundles):
continue
@@ -150,7 +152,6 @@ class GrossProfitGenerator(object):
def get_average_rate_based_on_group_by(self):
# sum buying / selling totals for group
self.grouped_data = []
for key in self.grouped.keys():
if self.filters.get("group_by") != "Invoice":
for i, row in enumerate(self.grouped[key]):

View File

View File

@@ -0,0 +1,84 @@
import unittest
from erpnext.accounts.party import get_party_shipping_address
from frappe.test_runner import make_test_objects
class TestUtils(unittest.TestCase):
@classmethod
def setUpClass(cls):
super(TestUtils, cls).setUpClass()
make_test_objects('Address', ADDRESS_RECORDS)
def test_get_party_shipping_address(self):
address = get_party_shipping_address('Customer', '_Test Customer 1')
self.assertEqual(address, '_Test Billing Address 2 Title-Billing')
def test_get_party_shipping_address2(self):
address = get_party_shipping_address('Customer', '_Test Customer 2')
self.assertEqual(address, '_Test Shipping Address 2 Title-Shipping')
ADDRESS_RECORDS = [
{
"doctype": "Address",
"address_type": "Billing",
"address_line1": "Address line 1",
"address_title": "_Test Billing Address Title",
"city": "Lagos",
"country": "Nigeria",
"links": [
{
"link_doctype": "Customer",
"link_name": "_Test Customer 2",
"doctype": "Dynamic Link"
}
]
},
{
"doctype": "Address",
"address_type": "Shipping",
"address_line1": "Address line 2",
"address_title": "_Test Shipping Address 1 Title",
"city": "Lagos",
"country": "Nigeria",
"links": [
{
"link_doctype": "Customer",
"link_name": "_Test Customer 2",
"doctype": "Dynamic Link"
}
]
},
{
"doctype": "Address",
"address_type": "Shipping",
"address_line1": "Address line 3",
"address_title": "_Test Shipping Address 2 Title",
"city": "Lagos",
"country": "Nigeria",
"is_shipping_address": "1",
"links": [
{
"link_doctype": "Customer",
"link_name": "_Test Customer 2",
"doctype": "Dynamic Link"
}
]
},
{
"doctype": "Address",
"address_type": "Billing",
"address_line1": "Address line 4",
"address_title": "_Test Billing Address 2 Title",
"city": "Lagos",
"country": "Nigeria",
"is_shipping_address": "1",
"links": [
{
"link_doctype": "Customer",
"link_name": "_Test Customer 1",
"doctype": "Dynamic Link"
}
]
}
]

View File

@@ -2917,418 +2917,13 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "subscription",
"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": "Subscription",
"length": 0,
"no_copy": 1,
"options": "Subscription",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"collapsible_depends_on": "is_recurring",
"columns": 0,
"depends_on": "eval:doc.docstatus<2 && !doc.__islocal",
"fieldname": "recurring_order",
"fieldtype": "Section Break",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Recurring Order",
"length": 0,
"no_copy": 0,
"options": "fa fa-time",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break",
"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,
"label": "Settings",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.docstatus<2",
"description": "",
"fieldname": "is_recurring",
"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": "Is Recurring",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_recurring",
"description": "",
"fieldname": "recurring_id",
"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": "Reference Document",
"length": 0,
"no_copy": 1,
"options": "Purchase Order",
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "recurring_type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Frequency",
"length": 0,
"no_copy": 1,
"options": "Monthly\nQuarterly\nHalf-yearly\nYearly",
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "repeat_on_day_of_month",
"fieldtype": "Int",
"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": "Repeat on Day of Month",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "end_date",
"fieldtype": "Date",
"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": "End Date",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"fieldname": "submit_on_creation",
"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": "Submit on creation",
"length": 0,
"no_copy": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "notify_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": "Notify by email",
"length": 0,
"no_copy": 1,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.notify_by_email && doc.recurring_id === doc.name",
"description": "",
"fieldname": "notification_email_address",
"fieldtype": "Code",
"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": "Notification Email Address",
"length": 0,
"no_copy": 1,
"options": "Email",
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.notify_by_email && doc.recurring_id === doc.name",
"fieldname": "recurring_print_format",
"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": "Recurring Print Format",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break83",
"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,
"label": "This Document",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_recurring",
"depends_on": "",
"description": "",
"fieldname": "from_date",
"fieldtype": "Date",
@@ -3359,7 +2954,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_recurring",
"depends_on": "",
"description": "",
"fieldname": "to_date",
"fieldtype": "Date",
@@ -3390,10 +2985,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_recurring",
"description": "",
"fieldname": "next_date",
"fieldtype": "Date",
"fieldname": "column_break_97",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -3401,11 +2994,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Next Date",
"length": 0,
"no_copy": 1,
"no_copy": 0,
"permlevel": 0,
"print_hide": 1,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
@@ -3414,6 +3007,37 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "subscription",
"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": "Subscription",
"length": 0,
"no_copy": 1,
"options": "Subscription",
"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,
"unique": 0
}
],
"has_web_view": 0,
@@ -3427,7 +3051,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-09-22 16:11:49.856808",
"modified": "2017-10-24 12:52:11.272306",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",

View File

@@ -816,7 +816,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-07-21 14:06:46.309322",
"modified": "2017-10-17 17:27:06.281494",
"modified_by": "Administrator",
"module": "Buying",
"name": "Request for Quotation",
@@ -903,26 +903,6 @@
"submit": 0,
"write": 0
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Supplier",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
{
"amend": 0,
"apply_user_permissions": 0,

View File

@@ -315,11 +315,16 @@ def get_data():
"name": "Payment Gateway Account",
"description": _("Setup Gateway accounts.")
},
{
"type": "doctype",
"name": "POS Settings",
"description": _("Setup mode of POS (Online / Offline)")
},
{
"type": "doctype",
"name": "POS Profile",
"label": _("Point-of-Sale Profile"),
"description": _("Rules to calculate shipping amount for a sale")
"description": _("Setup default values for POS Invoices")
},
{
"type": "doctype",

View File

@@ -201,13 +201,16 @@ def copy_attributes_to_variant(item, variant):
variant.variant_of = item.name
variant.has_variants = 0
if not variant.description:
variant.description = ''
variant.description = ""
if item.variant_based_on=='Item Attribute':
if variant.attributes:
variant.description += "\n"
attributes_description = ""
for d in variant.attributes:
variant.description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
attributes_description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
if attributes_description not in variant.description:
variant.description += attributes_description
def make_variant_item_code(template_item_code, template_item_name, variant):
"""Uses template's item code and abbreviations to make variant's item code"""

View File

@@ -78,7 +78,7 @@ def create_invoice(company, patient, physician, consultation_id):
create_invoice_items(physician, sales_invoice, company)
sales_invoice.save(ignore_permissions=True)
frappe.db.sql(_("""update tabConsultation set invoice='{0}' where name='{1}'""").format(sales_invoice.name, consultation_id))
frappe.db.sql("""update tabConsultation set invoice=%s where name=%s""", (sales_invoice.name, consultation_id))
appointment = frappe.db.get_value("Consultation", consultation_id, "appointment")
if appointment:
frappe.db.set_value("Patient Appointment", appointment, "sales_invoice", sales_invoice.name)

View File

@@ -291,5 +291,5 @@ def create_invoice(company, patient, lab_tests, prescriptions):
@frappe.whitelist()
def get_lab_test_prescribed(patient):
return frappe.db.sql(_("""select cp.name, cp.test_code, cp.parent, cp.invoice, ct.physician, ct.consultation_date from tabConsultation ct,
`tabLab Prescription` cp where ct.patient='{0}' and cp.parent=ct.name and cp.test_created=0""").format(patient))
return frappe.db.sql("""select cp.name, cp.test_code, cp.parent, cp.invoice, ct.physician, ct.consultation_date from tabConsultation ct,
`tabLab Prescription` cp where ct.patient=%s and cp.parent=ct.name and cp.test_created=0""", (patient))

View File

@@ -111,10 +111,10 @@ def make_invoice(patient, company):
@frappe.whitelist()
def get_patient_detail(patient, company=None):
patient_dict = frappe.db.sql(_("""select * from tabPatient where name='{0}'""").format(patient), as_dict=1)
patient_dict = frappe.db.sql("""select * from tabPatient where name=%s""", (patient), as_dict=1)
if not patient_dict:
frappe.throw("Patient not found")
vital_sign = frappe.db.sql(_("""select * from `tabVital Signs` where patient='{0}' order by signs_date desc limit 1""").format(patient), as_dict=1)
vital_sign = frappe.db.sql("""select * from `tabVital Signs` where patient=%s order by signs_date desc limit 1""", (patient), as_dict=1)
details = patient_dict[0]
if vital_sign:

View File

@@ -183,16 +183,20 @@ var btn_create_vital_signs = function (frm) {
var btn_update_status = function(frm, status){
var doc = frm.doc;
frappe.call({
method:
"erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_status",
args: {appointmentId: doc.name, status:status},
callback: function(data){
if(!data.exc){
cur_frm.reload_doc();
}
frappe.confirm(__('Are you sure you want to cancel this appointment?'),
function() {
frappe.call({
method:
"erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_status",
args: {appointmentId: doc.name, status:status},
callback: function(data){
if(!data.exc){
frm.reload_doc();
}
}
});
}
});
);
};
var btn_invoice_consultation = function(frm){

View File

@@ -125,7 +125,7 @@ def create_invoice(company, physician, patient, appointment_id, appointment_date
create_invoice_items(appointment_id, physician, company, sales_invoice)
sales_invoice.save(ignore_permissions=True)
frappe.db.sql(_("""update `tabPatient Appointment` set sales_invoice='{0}' where name='{1}'""").format(sales_invoice.name, appointment_id))
frappe.db.sql("""update `tabPatient Appointment` set sales_invoice=%s where name=%s""", (sales_invoice.name, appointment_id))
frappe.db.set_value("Fee Validity", fee_validity.name, "ref_invoice", sales_invoice.name)
consultation = frappe.db.exists({
"doctype": "Consultation",

View File

@@ -39,6 +39,7 @@ erpnext.hr.AttendanceControlPanel = frappe.ui.form.Controller.extend({
args: {
method: 'erpnext.hr.doctype.upload_attendance.upload_attendance.upload'
},
no_socketio: true,
sample_url: "e.g. http://example.com/somefile.csv",
callback: function(attachment, r) {
var $log_wrapper = $(cur_frm.fields_dict.import_log.wrapper).empty();

View File

@@ -322,6 +322,36 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "currency_detail",
"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": "",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@@ -359,8 +389,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "currency_detail",
"fieldtype": "Section Break",
"fieldname": "column_break_12",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -368,7 +398,6 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -414,35 +443,6 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_12",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@@ -1322,7 +1322,7 @@
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
"fieldname": "section_break0",
@@ -1671,7 +1671,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-08-23 14:09:30.492628",
"modified": "2017-10-23 14:56:21.991160",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM",

View File

@@ -128,7 +128,7 @@ class BOM(WebsiteGenerator):
'uom' : item and args['stock_uom'] or '',
'conversion_factor': 1,
'bom_no' : args['bom_no'],
'rate' : rate / self.conversion_rate,
'rate' : rate / self.conversion_rate if self.conversion_rate else rate,
'qty' : args.get("qty") or args.get("stock_qty") or 1,
'stock_qty' : args.get("qty") or args.get("stock_qty") or 1,
'base_rate' : rate
@@ -147,22 +147,28 @@ class BOM(WebsiteGenerator):
if arg.get('scrap_items'):
rate = self.get_valuation_rate(arg)
elif arg:
if self.rm_cost_as_per == 'Valuation Rate':
rate = self.get_valuation_rate(arg)
elif self.rm_cost_as_per == 'Last Purchase Rate':
rate = arg['last_purchase_rate'] \
or frappe.db.get_value("Item", arg['item_code'], "last_purchase_rate")
elif self.rm_cost_as_per == "Price List":
if not self.buying_price_list:
frappe.throw(_("Please select Price List"))
rate = frappe.db.get_value("Item Price",
{"price_list": self.buying_price_list, "item_code": arg["item_code"]}, "price_list_rate")
price_list_currency = frappe.db.get_value("Price List", self.buying_price_list, "currency")
if price_list_currency != self.company_currency():
rate = flt(rate * self.conversion_rate)
if arg['bom_no'] and (not rate or self.set_rate_of_sub_assembly_item_based_on_bom):
if arg.get('bom_no') and self.set_rate_of_sub_assembly_item_based_on_bom:
rate = self.get_bom_unitcost(arg['bom_no'])
else:
if self.rm_cost_as_per == 'Valuation Rate':
rate = self.get_valuation_rate(arg)
elif self.rm_cost_as_per == 'Last Purchase Rate':
rate = arg.get('last_purchase_rate') \
or frappe.db.get_value("Item", arg['item_code'], "last_purchase_rate")
elif self.rm_cost_as_per == "Price List":
if not self.buying_price_list:
frappe.throw(_("Please select Price List"))
rate = frappe.db.get_value("Item Price", {"price_list": self.buying_price_list,
"item_code": arg["item_code"]}, "price_list_rate")
price_list_currency = frappe.db.get_value("Price List",
self.buying_price_list, "currency")
if price_list_currency != self.company_currency():
rate = flt(rate * self.conversion_rate)
if not rate:
frappe.msgprint(_("{0} not found for Item {1}")
.format(self.rm_cost_as_per, arg["item_code"]))
return flt(rate)
@@ -374,7 +380,7 @@ class BOM(WebsiteGenerator):
if d.workstation:
if not d.hour_rate:
hour_rate = flt(frappe.db.get_value("Workstation", d.workstation, "hour_rate"))
d.hour_rate = hour_rate / flt(self.conversion_rate)
d.hour_rate = hour_rate / flt(self.conversion_rate) if self.conversion_rate else hour_rate
if d.hour_rate and d.time_in_mins:
d.base_hour_rate = flt(d.hour_rate) * flt(self.conversion_rate)

View File

@@ -448,4 +448,8 @@ erpnext.patches.v8_9.remove_employee_from_salary_structure_parent
erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts
erpnext.patches.v8_9.set_default_fields_in_variant_settings
erpnext.patches.v8_9.update_billing_gstin_for_indian_account
erpnext.patches.v9_0.fix_subscription_next_date
erpnext.patches.v9_0.fix_subscription_next_date #2017-10-23
erpnext.patches.v9_0.add_healthcare_domain
erpnext.patches.v9_0.set_variant_item_description
erpnext.patches.v9_0.set_uoms_in_variant_field
erpnext.patches.v9_0.copy_old_fees_field_data

View File

@@ -12,6 +12,7 @@ def execute():
domains = frappe.db.sql_list("select domain from tabCompany")
if "Education" not in domains:
role = frappe.get_doc("Role", "Instructor")
role.disabled = 1
role.save(ignore_permissions=True)
if frappe.db.exists("Role", "Instructor"):
role = frappe.get_doc("Role", "Instructor")
role.disabled = 1
role.save(ignore_permissions=True)

View File

@@ -18,24 +18,33 @@ def execute():
frappe.reload_doc('accounts', 'doctype', 'journal_entry')
frappe.reload_doc('accounts', 'doctype', 'payment_entry')
for doctype in ['Sales Order', 'Sales Invoice',
'Purchase Invoice', 'Purchase Invoice']:
for data in get_data(doctype):
make_subscription(doctype, data)
for doctype in ['Sales Order', 'Sales Invoice', 'Purchase Order', 'Purchase Invoice']:
date_field = "transaction_date"
if doctype in ("Sales Invoice", "Purchase Invoice"):
date_field = "posting_date"
def get_data(doctype):
return frappe.db.sql(""" select name, from_date, end_date, recurring_type,recurring_id,
for data in get_data(doctype, date_field):
make_subscription(doctype, data, date_field)
def get_data(doctype, date_field):
return frappe.db.sql(""" select name, from_date, end_date, recurring_type, recurring_id,
next_date, notify_by_email, notification_email_address, recurring_print_format,
repeat_on_day_of_month, submit_on_creation, docstatus
from `tab{0}` where is_recurring = 1 and next_date >= %s and docstatus < 2
""".format(doctype), today(), as_dict=1)
repeat_on_day_of_month, submit_on_creation, docstatus, {0}
from `tab{1}` where is_recurring = 1 and next_date >= %s and docstatus < 2
order by next_date desc
""".format(date_field, doctype), today(), as_dict=1)
def make_subscription(doctype, data, date_field):
if data.name == data.recurring_id:
start_date = data.get(date_field)
else:
start_date = frappe.db.get_value(doctype, data.recurring_id, date_field)
def make_subscription(doctype, data):
doc = frappe.get_doc({
'doctype': 'Subscription',
'reference_doctype': doctype,
'reference_document': data.name,
'start_date': data.from_date,
'reference_document': data.recurring_id,
'start_date': start_date,
'end_date': data.end_date,
'frequency': data.recurring_type,
'repeat_on_day': data.repeat_on_day_of_month,

View File

@@ -0,0 +1,14 @@
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
def execute():
domain = _('Healthcare')
if not frappe.db.exists('Domain', domain):
frappe.get_doc({
'doctype': 'Domain',
'domain': domain
}).insert(ignore_permissions=True)

View File

@@ -0,0 +1,11 @@
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
if "total_amount" not in frappe.db.get_table_columns("Fees"):
return
frappe.db.sql("""update tabFees set grand_total=total_amount where grand_total = 0.0""")

View File

@@ -3,25 +3,41 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import getdate
from erpnext.accounts.doctype.subscription.subscription import get_next_schedule_date
def execute():
frappe.reload_doctype('Subscription')
doctypes = ('Purchase Order', 'Sales Order', 'Purchase Invoice', 'Sales Invoice')
for data in frappe.get_all('Subscription', fields = ["name", "reference_doctype", "reference_document"],
filters = {'reference_doctype': ('in', doctypes)}):
doc = frappe.get_doc('Subscription', data.name)
fields = ['transaction_date']
if doc.reference_doctype in ['Sales Invoice', 'Purchase Invoice']:
fields = ['posting_date']
for data in frappe.get_all('Subscription',
fields = ["name", "reference_doctype", "reference_document",
"start_date", "frequency", "repeat_on_day"],
filters = {'reference_doctype': ('in', doctypes), 'docstatus': 1}):
fields.extend(['from_date', 'to_date'])
reference_data = frappe.db.get_value(data.reference_doctype,
data.reference_document, fields, as_dict=1)
recurring_id = frappe.db.get_value(data.reference_doctype, data.reference_document, "recurring_id")
if recurring_id:
frappe.db.sql("update `tab{0}` set subscription=%s where recurring_id=%s"
.format(data.reference_doctype), (data.name, recurring_id))
if reference_data:
doc.start_date = reference_data.get('posting_date') or reference_data.get('transaction_date')
doc.from_date = reference_data.get('from_date')
doc.to_date = reference_data.get('to_date')
doc.set_next_schedule_date()
doc.db_update()
date_field = 'transaction_date'
if data.reference_doctype in ['Sales Invoice', 'Purchase Invoice']:
date_field = 'posting_date'
start_date = frappe.db.get_value(data.reference_doctype, data.reference_document, date_field)
if start_date and getdate(start_date) != getdate(data.start_date):
last_ref_date = frappe.db.sql("""
select {0}
from `tab{1}`
where subscription=%s and docstatus < 2
order by creation desc
limit 1
""".format(date_field, data.reference_doctype), data.name)[0][0]
next_schedule_date = get_next_schedule_date(last_ref_date, data.frequency, data.repeat_on_day)
frappe.db.set_value("Subscription", data.name, {
"start_date": start_date,
"next_schedule_date": next_schedule_date
}, None)

View File

@@ -0,0 +1,14 @@
from __future__ import unicode_literals
import frappe
def execute():
doc = frappe.get_doc('Item Variant Settings')
variant_field_names = [vf.field_name for vf in doc.fields]
if 'uoms' not in variant_field_names:
doc.append(
'fields', {
'field_name': 'uoms'
}
)
doc.save()

View File

@@ -0,0 +1,45 @@
import frappe
from frappe.utils import cstr
def execute():
'''
Issue:
While copying data from template item to variant item,
the system appending description multiple times to the respective variant.
Purpose:
Check variant description,
if variant have user defined description remove all system appended descriptions
else replace multiple system generated descriptions with single description
Steps:
1. Get all variant items
2. Create system generated variant description
3. If variant have user defined description, remove all system generated descriptions
4. If variant description only contains system generated description,
replace multiple descriptions by new description.
'''
for item in frappe.db.sql(""" select name from tabItem
where ifnull(variant_of, '') != '' """,as_dict=1):
variant = frappe.get_doc("Item", item.name)
temp_variant_description = '\n'
if variant.attributes:
for d in variant.attributes:
temp_variant_description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
variant_description = variant.description.replace(temp_variant_description, '').rstrip()
if variant_description:
splitted_desc = variant.description.strip().split(temp_variant_description)
if len(splitted_desc) > 2:
if splitted_desc[0] == '':
variant_description = temp_variant_description + variant_description
elif splitted_desc[1] == '' or splitted_desc[1] == '\n':
variant_description += temp_variant_description
variant.db_set('description', variant_description, update_modified=False)
else:
variant.db_set('description', variant_description, update_modified=False)
else:
variant.db_set('description', temp_variant_description, update_modified=False)

View File

@@ -159,9 +159,14 @@ frappe.ui.form.on("Timesheet Detail", {
});
var calculate_end_time = function(frm, cdt, cdn) {
var child = locals[cdt][cdn];
let child = locals[cdt][cdn];
var d = moment(child.from_time);
if(!child.from_time) {
// if from_time value is not available then set the current datetime
frappe.model.set_value(cdt, cdn, "from_time", frappe.datetime.get_datetime_as_string());
}
let d = moment(child.from_time);
if(child.hours) {
d.add(child.hours, "hours");
frm._setting_hours = true;

View File

@@ -1,39 +1,45 @@
frappe.ui.form.on("Communication", {
refresh: function(frm) {
refresh: (frm) => {
// setup custom Make button only if Communication is Email
if(frm.doc.communication_medium == "Email" && frm.doc.sent_or_received == "Received") {
frm.events.setup_custom_buttons(frm);
}
},
setup_custom_buttons: (frm) => {
let confirm_msg = "Are you sure you want to create {0} from this email";
if(frm.doc.reference_doctype !== "Issue") {
frm.add_custom_button(__("Issue"), function() {
frappe.confirm("Are you sure you want to create Issue from this email", function(){
frm.add_custom_button(__("Issue"), () => {
frappe.confirm(__(confirm_msg, [__("Issue")]), () => {
frm.trigger('make_issue_from_communication');
})
}, "Make");
}
if(!in_list(["Lead", "Opportunity"], frm.doc.reference_doctype)) {
frm.add_custom_button(__("Lead"), function() {
frappe.confirm("Are you sure you want to create Lead from this email", function(){
frm.add_custom_button(__("Lead"), () => {
frappe.confirm(__(confirm_msg, [__("Lead")]), () => {
frm.trigger('make_lead_from_communication');
})
}, "Make");
frm.add_custom_button(__("Opportunity"), function() {
frappe.confirm("Are you sure you want to create Opportunity from this email", function(){
frm.add_custom_button(__("Opportunity"), () => {
frappe.confirm(__(confirm_msg, [__("Opportunity")]), () => {
frm.trigger('make_opportunity_from_communication');
})
}, "Make");
}
frm.page.set_inner_btn_group_as_primary(__("Make"));
},
make_lead_from_communication: function(frm) {
make_lead_from_communication: (frm) => {
return frappe.call({
method: "frappe.email.inbox.make_lead_from_communication",
args: {
communication: frm.doc.name
},
freeze: true,
callback: function(r) {
callback: (r) => {
if(r.message) {
frm.reload_doc()
}
@@ -41,14 +47,14 @@ frappe.ui.form.on("Communication", {
})
},
make_issue_from_communication: function(frm) {
make_issue_from_communication: (frm) => {
return frappe.call({
method: "frappe.email.inbox.make_issue_from_communication",
args: {
communication: frm.doc.name
},
freeze: true,
callback: function(r) {
callback: (r) => {
if(r.message) {
frm.reload_doc()
}
@@ -56,14 +62,14 @@ frappe.ui.form.on("Communication", {
})
},
make_opportunity_from_communication: function(frm) {
make_opportunity_from_communication: (frm) => {
return frappe.call({
method: "frappe.email.inbox.make_opportunity_from_communication",
args: {
communication: frm.doc.name
},
freeze: true,
callback: function(r) {
callback: (r) => {
if(r.message) {
frm.reload_doc()
}

View File

@@ -542,11 +542,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
// Make read only if Accounts Settings doesn't allow stale rates
frappe.model.get_value("Accounts Settings", null, "allow_stale",
function(d){
me.set_df_property("conversion_rate", "read_only", cint(d.allow_stale) ? 0 : 1);
}
);
this.frm.set_df_property("conversion_rate", "read_only", erpnext.stale_rate_allowed());
},
set_actual_charges_based_on_currency: function() {

View File

@@ -37,7 +37,6 @@
<div class="cell price-cell text-right tax-table">
</div>
</div>
{% if (apply_discount_on) { %}
<div class="pos-list-row discount-amount-area">
<div class="cell"></div>
<div class="cell text-right">{%= __("Discount") %}</div>
@@ -52,7 +51,6 @@
</div>
</div>
</div>
{% } %}
<div class="pos-list-row grand-total-area collapse-btn" style="border-bottom:1px solid #d1d8dd;">
<div class="cell">
<a class="">

View File

@@ -37,6 +37,10 @@ $.extend(erpnext, {
}
},
stale_rate_allowed: () => {
return cint(frappe.boot.sysdefaults.allow_stale) || 1;
},
setup_serial_no: function() {
var grid_row = cur_frm.open_grid_row();
if(!grid_row || !grid_row.grid_form.fields_dict.serial_no ||

View File

@@ -50,6 +50,7 @@ class Fees(AccountsController):
select g.email_address
from `tabGuardian` g, `tabStudent Guardian` sg
where g.name = sg.guardian and sg.parent = %s and sg.parenttype = 'Student'
and ifnull(g.email_address, '')!=''
""", self.student)
student_email_id = frappe.db.get_value("Student", self.student, "student_email_id")
@@ -111,7 +112,7 @@ def get_fee_list(doctype, txt, filters, limit_start, limit_page_length=20, order
user = frappe.session.user
student = frappe.db.sql("select name from `tabStudent` where student_email_id= %s", user)
if student:
return frappe. db.sql('''select name, program, due_date, paid_amount, outstanding_amount, total_amount from `tabFees`
return frappe. db.sql('''select name, program, due_date, paid_amount, outstanding_amount, grand_total from `tabFees`
where student= %s and docstatus=1
order by due_date asc limit {0} , {1}'''
.format(limit_start, limit_page_length), student, as_dict = True)

View File

@@ -5,14 +5,14 @@
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 2,
"idx": 3,
"is_standard": "Yes",
"modified": "2017-02-24 20:05:08.514320",
"modified": "2017-10-25 11:59:26.003899",
"modified_by": "Administrator",
"module": "Schools",
"name": "Student Fee Collection",
"owner": "Administrator",
"query": "SELECT\n student as \"Student:Link/Student:200\",\n student_name as \"Student Name::200\",\n sum(paid_amount) as \"Paid Amount:Currency:150\",\n sum(outstanding_amount) as \"Outstanding Amount:Currency:150\",\n sum(total_amount) as \"Total Amount:Currency:150\"\nFROM\n `tabFees` \nGROUP BY\n student",
"query": "SELECT\n student as \"Student:Link/Student:200\",\n student_name as \"Student Name::200\",\n sum(paid_amount) as \"Paid Amount:Currency:150\",\n sum(outstanding_amount) as \"Outstanding Amount:Currency:150\",\n sum(grand_total) as \"Grand Total:Currency:150\"\nFROM\n `tabFees` \nGROUP BY\n student",
"ref_doctype": "Fees",
"report_name": "Student Fee Collection",
"report_type": "Query Report",

View File

@@ -3272,419 +3272,13 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "subscription",
"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": "Subscription",
"length": 0,
"no_copy": 0,
"options": "Subscription",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"collapsible_depends_on": "is_recurring",
"columns": 0,
"depends_on": "eval:doc.docstatus<2 && !doc.__islocal",
"fieldname": "recurring_order",
"fieldtype": "Section Break",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Recurring Order",
"length": 0,
"no_copy": 0,
"options": "fa fa-time",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "settings",
"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,
"label": "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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.docstatus<2",
"description": "",
"fieldname": "is_recurring",
"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": "Is Recurring",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_recurring",
"description": "",
"fieldname": "recurring_id",
"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": "Reference Document",
"length": 0,
"no_copy": 1,
"options": "Sales Order",
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "recurring_type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Frequency",
"length": 0,
"no_copy": 1,
"options": "\nMonthly\nQuarterly\nHalf-yearly\nYearly",
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "repeat_on_day_of_month",
"fieldtype": "Int",
"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": "Repeat on Day of Month",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "end_date",
"fieldtype": "Date",
"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": "Recurring Upto",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"fieldname": "submit_on_creation",
"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": "Submit on creation",
"length": 0,
"no_copy": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.recurring_id === doc.name",
"description": "",
"fieldname": "notify_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": "Notify by email",
"length": 0,
"no_copy": 1,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.notify_by_email && doc.recurring_id === doc.name",
"description": "",
"fieldname": "notification_email_address",
"fieldtype": "Code",
"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": "Notification Email Address",
"length": 0,
"no_copy": 1,
"options": "Email",
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.is_recurring && doc.notify_by_email && doc.recurring_id === doc.name",
"fieldname": "recurring_print_format",
"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": "Recurring Print Format",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break83",
"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,
"label": "This Document",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_recurring",
"depends_on": "",
"description": "",
"fieldname": "from_date",
"fieldtype": "Date",
@@ -3715,7 +3309,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_recurring",
"depends_on": "",
"description": "",
"fieldname": "to_date",
"fieldtype": "Date",
@@ -3746,10 +3340,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_recurring",
"description": "",
"fieldname": "next_date",
"fieldtype": "Date",
"fieldname": "column_break_108",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -3757,11 +3349,42 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Next Date",
"length": 0,
"no_copy": 1,
"no_copy": 0,
"permlevel": 0,
"print_hide": 1,
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "subscription",
"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": "Subscription",
"length": 0,
"no_copy": 0,
"options": "Subscription",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
@@ -3783,7 +3406,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-09-19 11:21:36.332326",
"modified": "2017-10-24 12:52:28.115742",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",

View File

@@ -347,15 +347,15 @@ class SalesOrder(SellingController):
return items
def on_recurring(self, reference_doc, subscription_doc):
self.set("delivery_date", get_next_schedule_date(reference_doc.delivery_date, subscription_doc.frequency,
cint(subscription_doc.repeat_on_day)))
self.set("delivery_date", get_next_schedule_date(reference_doc.delivery_date,
subscription_doc.frequency, cint(subscription_doc.repeat_on_day)))
for d in self.get("items"):
reference_delivery_date = frappe.db.get_value("Sales Order Item",
{"parent": reference_doc.name, "item_code": d.item_code, "idx": d.idx}, "delivery_date")
d.set("delivery_date",
get_next_schedule_date(reference_delivery_date, subscription_doc.frequency, cint(subscription_doc.repeat_on_day)))
d.set("delivery_date", get_next_schedule_date(reference_delivery_date,
subscription_doc.frequency, cint(subscription_doc.repeat_on_day)))
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context

View File

@@ -48,12 +48,14 @@ erpnext.pos.PointOfSale = class PointOfSale {
this.prepare_menu();
this.set_online_status();
},
() => this.setup_company(),
() => this.setup_pos_profile(),
() => this.make_new_invoice(),
() => {
frappe.timeout(1);
this.make_items();
this.bind_events();
},
() => this.make_new_invoice(),
() => this.page.set_title(__('Point of Sale'))
]);
}
@@ -100,22 +102,20 @@ erpnext.pos.PointOfSale = class PointOfSale {
if (!this.payment) {
this.make_payment_modal();
} else {
const mop_field = this.payment.default_mop;
let amount = 0.0;
this.frm.doc.payments.map(p => {
if (p.mode_of_payment == mop_field) {
amount = p.amount;
return;
}
this.payment.dialog.set_value(p.mode_of_payment, p.amount);
});
this.payment.dialog.set_value(mop_field, flt(amount));
this.payment.set_title();
}
this.payment.open_modal();
}
},
on_select_change: () => {
this.cart.numpad.set_inactive();
},
get_item_details: (item_code) => {
return this.items.get(item_code);
}
}
});
@@ -221,6 +221,11 @@ erpnext.pos.PointOfSale = class PointOfSale {
}
update_item_in_frm(item, field, value) {
if (field == 'qty' && value < 0) {
frappe.msgprint(__("Quantity must be positive"));
value = item.qty;
}
if (field) {
frappe.model.set_value(item.doctype, item.name, field, value);
}
@@ -280,21 +285,40 @@ erpnext.pos.PointOfSale = class PointOfSale {
}
setup_pos_profile() {
return frappe.call({
method: 'erpnext.stock.get_item_details.get_pos_profile',
args: {
company: frappe.sys_defaults.company
}
}).then(r => {
this.pos_profile = r.message;
return new Promise(resolve => {
frappe.call({
method: 'erpnext.stock.get_item_details.get_pos_profile',
args: {
company: this.company
}
}).then(r => {
this.pos_profile = r.message;
if (!this.pos_profile) {
this.pos_profile = {
currency: frappe.defaults.get_default('currency'),
selling_price_list: frappe.defaults.get_default('selling_price_list')
};
if (!this.pos_profile) {
this.pos_profile = {
company: this.company,
currency: frappe.defaults.get_default('currency'),
selling_price_list: frappe.defaults.get_default('selling_price_list')
};
}
resolve();
});
})
}
setup_company() {
this.company = frappe.sys_defaults.company;
return new Promise(resolve => {
if(!this.company) {
frappe.prompt({fieldname:"company", options: "Company", fieldtype:"Link",
label: __("Select Company"), reqd: 1}, (data) => {
this.company = data.company;
resolve(this.company);
}, __("Select Company"));
} else {
resolve(this.company);
}
});
})
}
make_new_invoice() {
@@ -316,22 +340,25 @@ erpnext.pos.PointOfSale = class PointOfSale {
const doctype = 'Sales Invoice';
return new Promise(resolve => {
if (this.frm) {
this.frm = get_frm(this.frm);
this.frm = get_frm(this.pos_profile, this.frm);
resolve();
} else {
frappe.model.with_doctype(doctype, () => {
this.frm = get_frm();
this.frm = get_frm(this.pos_profile);
resolve();
});
}
});
function get_frm(_frm) {
function get_frm(pos_profile, _frm) {
const page = $('<div>');
const frm = _frm || new _f.Frm(doctype, page, false);
const name = frappe.model.make_new_doc_and_get_name(doctype, true);
frm.refresh(name);
frm.doc.items = [];
if(!frm.doc.company) {
frm.set_value('company', pos_profile.company);
}
frm.set_value('is_pos', 1);
frm.meta.default_print_format = 'POS Invoice';
return frm;
@@ -384,6 +411,7 @@ erpnext.pos.PointOfSale = class PointOfSale {
class POSCart {
constructor({frm, wrapper, pos_profile, events}) {
this.frm = frm;
this.item_data = {};
this.wrapper = wrapper;
this.events = events;
this.pos_profile = pos_profile;
@@ -517,7 +545,7 @@ class POSCart {
// Update totals
this.$taxes_and_totals.find('.net-total')
.html(format_currency(this.frm.doc.net_total, currency));
.html(format_currency(this.frm.doc.total, currency));
// Update taxes
const taxes_html = this.frm.doc.taxes.map(tax => {
@@ -643,7 +671,8 @@ class POSCart {
const $item = this.$cart_items.find(`[data-item-code="${item.item_code}"]`);
if(item.qty > 0) {
const indicator_class = item.actual_qty >= item.qty ? 'green' : 'red';
const is_stock_item = this.get_item_details(item.item_code).is_stock_item;
const indicator_class = (!is_stock_item || item.actual_qty >= item.qty) ? 'green' : 'red';
const remove_class = indicator_class == 'green' ? 'red' : 'green';
$item.find('.quantity input').val(item.qty);
@@ -657,8 +686,9 @@ class POSCart {
}
get_item_html(item) {
const is_stock_item = this.get_item_details(item.item_code).is_stock_item;
const rate = format_currency(item.rate, this.frm.doc.currency);
const indicator_class = item.actual_qty >= item.qty ? 'green' : 'red';
const indicator_class = (!is_stock_item || item.actual_qty >= item.qty) ? 'green' : 'red';
return `
<div class="list-item indicator ${indicator_class}" data-item-code="${item.item_code}" title="Item: ${item.item_name} Available Qty: ${item.actual_qty}">
<div class="item-name list-item__content list-item__content--flex-1.5 ellipsis">
@@ -693,6 +723,14 @@ class POSCart {
}
}
get_item_details(item_code) {
if (!this.item_data[item_code]) {
this.item_data[item_code] = this.events.get_item_details(item_code);
}
return this.item_data[item_code];
}
exists(item_code) {
let $item = this.$cart_items.find(`[data-item-code="${item_code}"]`);
return $item.length > 0;
@@ -941,10 +979,13 @@ class POSItems {
this.search_index = this.search_index || {};
if (this.search_index[search_term]) {
const items = this.search_index[search_term];
this.items = items;
this.render_items(items);
this.set_item_in_the_cart(items);
return;
}
} else if (item_group == "All Item Groups") {
this.items = this.all_items;
return this.render_items(this.all_items);
}
@@ -954,20 +995,34 @@ class POSItems {
this.search_index[search_term] = items;
}
this.items = items;
this.render_items(items);
if(serial_no) {
this.events.update_cart(items[0].item_code,
'serial_no', serial_no);
this.reset_search_field();
}
if(batch_no) {
this.events.update_cart(items[0].item_code,
'batch_no', batch_no);
this.reset_search_field();
}
this.set_item_in_the_cart(items, serial_no, batch_no);
});
}
set_item_in_the_cart(items, serial_no, batch_no) {
if (serial_no) {
this.events.update_cart(items[0].item_code,
'serial_no', serial_no);
this.reset_search_field();
return;
}
if (batch_no) {
this.events.update_cart(items[0].item_code,
'batch_no', batch_no);
this.reset_search_field();
return;
}
if (items.length === 1) {
this.events.update_cart(items[0].item_code,
'qty', '+1');
this.reset_search_field();
}
}
reset_search_field() {
this.search_field.set_value('');
this.search_field.$input.trigger("input");
@@ -983,7 +1038,14 @@ class POSItems {
}
get(item_code) {
return this.items[item_code];
let item = {};
this.items.map(data => {
if (data.item_code === item_code) {
item = data;
}
})
return item
}
get_all() {
@@ -1165,16 +1227,13 @@ class Payment {
make() {
this.set_flag();
let title = __('Total Amount {0}',
[format_currency(this.frm.doc.grand_total, this.frm.doc.currency)]);
this.dialog = new frappe.ui.Dialog({
title: title,
fields: this.get_fields(),
width: 800
});
this.set_title();
this.$body = this.dialog.body;
this.numpad = new NumberPad({
@@ -1193,6 +1252,13 @@ class Payment {
});
}
set_title() {
let title = __('Total Amount {0}',
[format_currency(this.frm.doc.grand_total, this.frm.doc.currency)]);
this.dialog.set_title(title);
}
bind_events() {
var me = this;
$(this.dialog.body).find('.input-with-feedback').focusin(function() {
@@ -1214,10 +1280,6 @@ class Payment {
const me = this;
let fields = this.frm.doc.payments.map(p => {
if (p.default) {
this.default_mop = p.mode_of_payment;
}
return {
fieldtype: 'Currency',
label: __(p.mode_of_payment),

View File

@@ -9,6 +9,8 @@ from frappe.utils.nestedset import get_root_of
def get_items(start, page_length, price_list, item_group, search_value=""):
serial_no = ""
batch_no = ""
barcode = ""
item_code = search_value
if not frappe.db.exists('Item Group', item_group):
item_group = get_root_of('Item Group')
@@ -24,12 +26,17 @@ def get_items(start, page_length, price_list, item_group, search_value=""):
if batch_no_data:
batch_no, item_code = batch_no_data
item_code, condition = get_conditions(item_code, serial_no, batch_no)
if not serial_no and not batch_no:
barcode_data = frappe.db.get_value('Item', {'barcode': search_value}, ['name', 'barcode'])
if barcode_data:
item_code, barcode = barcode_data
item_code, condition = get_conditions(item_code, serial_no, batch_no, barcode)
lft, rgt = frappe.db.get_value('Item Group', item_group, ['lft', 'rgt'])
# locate function is used to sort by closest match from the beginning of the value
res = frappe.db.sql("""select i.name as item_code, i.item_name, i.image as item_image,
item_det.price_list_rate, item_det.currency
i.is_stock_item, item_det.price_list_rate, item_det.currency
from `tabItem` i LEFT JOIN
(select item_code, price_list_rate, currency from
`tabItem Price` where price_list=%(price_list)s) item_det
@@ -62,12 +69,12 @@ def get_items(start, page_length, price_list, item_group, search_value=""):
return res
def get_conditions(item_code, serial_no, batch_no):
if serial_no or batch_no:
def get_conditions(item_code, serial_no, batch_no, barcode):
if serial_no or batch_no or barcode:
return frappe.db.escape(item_code), "i.item_code = %(item_code)s"
condition = """(i.item_code like %(item_code)s
or i.item_name like %(item_code)s or i.barcode like %(item_code)s)"""
or i.item_name like %(item_code)s)"""
return '%%%s%%'%(frappe.db.escape(item_code)), condition

View File

@@ -29,48 +29,53 @@ def make_custom_fields():
def create_medical_departments():
depts = ["Accident and emergency care" ,"Anaesthetics", "Biochemistry", "Cardiology", "Dermatology",
"Diagnostic imaging", "ENT", "Gastroenterology", "General Surgery", "Gynaecology",
"Haematology", "Maternity", "Microbiology", "Nephrology", "Neurology", "Oncology",
"Orthopaedics", "Pathology", "Physiotherapy", "Rheumatology", "Serology", "Urology"]
for d in depts:
departments = [
"Accident And Emergency Care" ,"Anaesthetics", "Biochemistry", "Cardiology", "Dermatology",
"Diagnostic Imaging", "ENT", "Gastroenterology", "General Surgery", "Gynaecology",
"Haematology", "Maternity", "Microbiology", "Nephrology", "Neurology", "Oncology",
"Orthopaedics", "Pathology", "Physiotherapy", "Rheumatology", "Serology", "Urology"
]
for department in departments:
mediacal_department = frappe.new_doc("Medical Department")
mediacal_department.department = d
mediacal_department.department = _(department)
try:
mediacal_department.save()
except frappe.DuplicateEntryError:
pass
def create_antibiotics():
abt = ["Amoxicillin", "Ampicillin", "Bacampicillin", "Carbenicillin", "Cloxacillin", "Dicloxacillin",
"Flucloxacillin", "Mezlocillin", "Nafcillin", "Oxacillin", "Penicillin G", "Penicillin V",
"Piperacillin", "Pivampicillin", "Pivmecillinam", "Ticarcillin", "Cefacetrile (cephacetrile)",
"Cefadroxil (cefadroxyl)", "Cefalexin (cephalexin)", "Cefaloglycin (cephaloglycin)",
"Cefalonium (cephalonium)", "Cefaloridine (cephaloradine)", "Cefalotin (cephalothin)",
"Cefapirin (cephapirin)", "Cefatrizine", "Cefazaflur", "Cefazedone", "Cefazolin (cephazolin)",
"Cefradine (cephradine)", "Cefroxadine", "Ceftezole", "Cefaclor", "Cefamandole", "Cefmetazole",
"Cefonicid", "Cefotetan", "Cefoxitin", "Cefprozil (cefproxil)", "Cefuroxime", "Cefuzonam",
"Cefcapene", "Cefdaloxime", "Cefdinir", "Cefditoren", "Cefetamet", "Cefixime", "Cefmenoxime",
"Cefodizime", "Cefotaxime", "Cefpimizole", "Cefpodoxime", "Cefteram", "Ceftibuten", "Ceftiofur",
"Ceftiolene", "Ceftizoxime", "Ceftriaxone", "Cefoperazone", "Ceftazidime", "Cefclidine", "Cefepime",
"Cefluprenam", "Cefoselis", "Cefozopran", "Cefpirome", "Cefquinome", "Ceftobiprole", "Ceftaroline",
"Cefaclomezine","Cefaloram", "Cefaparole", "Cefcanel", "Cefedrolor", "Cefempidone", "Cefetrizole",
"Cefivitril", "Cefmatilen", "Cefmepidium", "Cefovecin", "Cefoxazole", "Cefrotil", "Cefsumide",
"Cefuracetime", "Ceftioxide", "Ceftazidime/Avibactam", "Ceftolozane/Tazobactam", "Aztreonam",
"Imipenem", "Imipenem/cilastatin", "Doripenem", "Meropenem", "Ertapenem", "Azithromycin",
"Erythromycin", "Clarithromycin", "Dirithromycin", "Roxithromycin", "Telithromycin", "Clindamycin",
"Lincomycin", "Pristinamycin", "Quinupristin/dalfopristin", "Amikacin", "Gentamicin", "Kanamycin",
"Neomycin", "Netilmicin", "Paromomycin", "Streptomycin", "Tobramycin", "Flumequine", "Nalidixic acid",
"Oxolinic acid", "Piromidic acid", "Pipemidic acid", "Rosoxacin", "Ciprofloxacin", "Enoxacin",
"Lomefloxacin", "Nadifloxacin", "Norfloxacin", "Ofloxacin", "Pefloxacin", "Rufloxacin", "Balofloxacin",
"Gatifloxacin", "Grepafloxacin", "Levofloxacin", "Moxifloxacin", "Pazufloxacin", "Sparfloxacin",
"Temafloxacin", "Tosufloxacin", "Besifloxacin", "Clinafloxacin", "Gemifloxacin",
"Sitafloxacin", "Trovafloxacin", "Prulifloxacin", "Sulfamethizole", "Sulfamethoxazole",
"Sulfisoxazole", "Trimethoprim-Sulfamethoxazole", "Demeclocycline", "Doxycycline", "Minocycline",
"Oxytetracycline", "Tetracycline", "Tigecycline", "Chloramphenicol", "Metronidazole",
"Tinidazole", "Nitrofurantoin", "Vancomycin", "Teicoplanin", "Telavancin", "Linezolid",
"Cycloserine 2", "Rifampin", "Rifabutin", "Rifapentine", "Rifalazil", "Bacitracin", "Polymyxin B",
"Viomycin", "Capreomycin"]
abt = [
"Amoxicillin", "Ampicillin", "Bacampicillin", "Carbenicillin", "Cloxacillin", "Dicloxacillin",
"Flucloxacillin", "Mezlocillin", "Nafcillin", "Oxacillin", "Penicillin G", "Penicillin V",
"Piperacillin", "Pivampicillin", "Pivmecillinam", "Ticarcillin", "Cefacetrile (cephacetrile)",
"Cefadroxil (cefadroxyl)", "Cefalexin (cephalexin)", "Cefaloglycin (cephaloglycin)",
"Cefalonium (cephalonium)", "Cefaloridine (cephaloradine)", "Cefalotin (cephalothin)",
"Cefapirin (cephapirin)", "Cefatrizine", "Cefazaflur", "Cefazedone", "Cefazolin (cephazolin)",
"Cefradine (cephradine)", "Cefroxadine", "Ceftezole", "Cefaclor", "Cefamandole", "Cefmetazole",
"Cefonicid", "Cefotetan", "Cefoxitin", "Cefprozil (cefproxil)", "Cefuroxime", "Cefuzonam",
"Cefcapene", "Cefdaloxime", "Cefdinir", "Cefditoren", "Cefetamet", "Cefixime", "Cefmenoxime",
"Cefodizime", "Cefotaxime", "Cefpimizole", "Cefpodoxime", "Cefteram", "Ceftibuten", "Ceftiofur",
"Ceftiolene", "Ceftizoxime", "Ceftriaxone", "Cefoperazone", "Ceftazidime", "Cefclidine", "Cefepime",
"Cefluprenam", "Cefoselis", "Cefozopran", "Cefpirome", "Cefquinome", "Ceftobiprole", "Ceftaroline",
"Cefaclomezine","Cefaloram", "Cefaparole", "Cefcanel", "Cefedrolor", "Cefempidone", "Cefetrizole",
"Cefivitril", "Cefmatilen", "Cefmepidium", "Cefovecin", "Cefoxazole", "Cefrotil", "Cefsumide",
"Cefuracetime", "Ceftioxide", "Ceftazidime/Avibactam", "Ceftolozane/Tazobactam", "Aztreonam",
"Imipenem", "Imipenem/cilastatin", "Doripenem", "Meropenem", "Ertapenem", "Azithromycin",
"Erythromycin", "Clarithromycin", "Dirithromycin", "Roxithromycin", "Telithromycin", "Clindamycin",
"Lincomycin", "Pristinamycin", "Quinupristin/dalfopristin", "Amikacin", "Gentamicin", "Kanamycin",
"Neomycin", "Netilmicin", "Paromomycin", "Streptomycin", "Tobramycin", "Flumequine", "Nalidixic acid",
"Oxolinic acid", "Piromidic acid", "Pipemidic acid", "Rosoxacin", "Ciprofloxacin", "Enoxacin",
"Lomefloxacin", "Nadifloxacin", "Norfloxacin", "Ofloxacin", "Pefloxacin", "Rufloxacin", "Balofloxacin",
"Gatifloxacin", "Grepafloxacin", "Levofloxacin", "Moxifloxacin", "Pazufloxacin", "Sparfloxacin",
"Temafloxacin", "Tosufloxacin", "Besifloxacin", "Clinafloxacin", "Gemifloxacin",
"Sitafloxacin", "Trovafloxacin", "Prulifloxacin", "Sulfamethizole", "Sulfamethoxazole",
"Sulfisoxazole", "Trimethoprim-Sulfamethoxazole", "Demeclocycline", "Doxycycline", "Minocycline",
"Oxytetracycline", "Tetracycline", "Tigecycline", "Chloramphenicol", "Metronidazole",
"Tinidazole", "Nitrofurantoin", "Vancomycin", "Teicoplanin", "Telavancin", "Linezolid",
"Cycloserine 2", "Rifampin", "Rifabutin", "Rifapentine", "Rifalazil", "Bacitracin", "Polymyxin B",
"Viomycin", "Capreomycin"
]
for a in abt:
antibiotic = frappe.new_doc("Antibiotic")
antibiotic.antibiotic_name = a
@@ -190,21 +195,21 @@ def create_healthcare_item_groups():
def create_lab_test_items():
records = [
{"doctype": "Item", "item_code": "MCH", "item_name": "MCH", "item_group": "Laboratory",
{"doctype": "Item", "item_code": "MCH", "item_name": "MCH", "item_group": _("Laboratory"),
"stock_uom": _("Unit"), "is_stock_item": 0, "is_purchase_item": 0, "is_sales_item": 1},
{"doctype": "Item", "item_code": "LDL", "item_name": "LDL", "item_group": "Laboratory",
{"doctype": "Item", "item_code": "LDL", "item_name": "LDL", "item_group": _("Laboratory"),
"stock_uom": _("Unit"), "is_stock_item": 0, "is_purchase_item": 0, "is_sales_item": 1},
{"doctype": "Item", "item_code": "GTT", "item_name": "GTT", "item_group": "Laboratory",
{"doctype": "Item", "item_code": "GTT", "item_name": "GTT", "item_group": _("Laboratory"),
"stock_uom": _("Unit"), "is_stock_item": 0, "is_purchase_item": 0, "is_sales_item": 1},
{"doctype": "Item", "item_code": "HDL", "item_name": "HDL", "item_group": "Laboratory",
{"doctype": "Item", "item_code": "HDL", "item_name": "HDL", "item_group": _("Laboratory"),
"stock_uom": _("Unit"), "is_stock_item": 0, "is_purchase_item": 0, "is_sales_item": 1},
{"doctype": "Item", "item_code": "BILT", "item_name": "BILT", "item_group": "Laboratory",
{"doctype": "Item", "item_code": "BILT", "item_name": "BILT", "item_group": _("Laboratory"),
"stock_uom": _("Unit"), "is_stock_item": 0, "is_purchase_item": 0, "is_sales_item": 1},
{"doctype": "Item", "item_code": "BILD", "item_name": "BILD", "item_group": "Laboratory",
{"doctype": "Item", "item_code": "BILD", "item_name": "BILD", "item_group": _("Laboratory"),
"stock_uom": _("Unit"), "is_stock_item": 0, "is_purchase_item": 0, "is_sales_item": 1},
{"doctype": "Item", "item_code": "BP", "item_name": "BP", "item_group": "Laboratory",
{"doctype": "Item", "item_code": "BP", "item_name": "BP", "item_group": _("Laboratory"),
"stock_uom": _("Unit"), "is_stock_item": 0, "is_purchase_item": 0, "is_sales_item": 1},
{"doctype": "Item", "item_code": "BS", "item_name": "BS", "item_group": "Laboratory",
{"doctype": "Item", "item_code": "BS", "item_name": "BS", "item_group": _("Laboratory"),
"stock_uom": _("Unit"), "is_stock_item": 0, "is_purchase_item": 0, "is_sales_item": 1}
]
insert_record(records)
@@ -212,43 +217,43 @@ def create_lab_test_items():
def create_lab_test_template():
records = [
{"doctype": "Lab Test Template", "name": "MCH","test_name": "MCH","test_code": "MCH",
"test_group": "Laboratory","department": "Haematology","item": "MCH",
"test_group": _("Laboratory"),"department": _("Haematology"),"item": "MCH",
"test_template_type": "Single","is_billable": 1,"test_rate": 0.0,"test_uom": "Microgram",
"test_normal_range": "27 - 32 Microgram",
"sensitivity": 0,"test_description": "Mean Corpuscular Hemoglobin"},
{"doctype": "Lab Test Template", "name": "LDL","test_name": "LDL (Serum)","test_code": "LDL",
"test_group": "Laboratory","department": "Biochemistry",
"test_group": _("Laboratory"),"department": _("Biochemistry"),
"item": "LDL","test_template_type": "Single",
"is_billable": 1,"test_rate": 0.0,"test_uom": "mg / dl","test_normal_range": "70 - 160 mg/dlLow-density Lipoprotein (LDL)",
"sensitivity": 0,"test_description": "Low-density Lipoprotein (LDL)"},
{"doctype": "Lab Test Template", "name": "GTT","test_name": "GTT","test_code": "GTT",
"test_group": "Laboratory","department": "Haematology",
"test_group": _("Laboratory"),"department": _("Haematology"),
"item": "GTT","test_template_type": "Single",
"is_billable": 1,"test_rate": 0.0,"test_uom": "mg / dl","test_normal_range": "Less than 85 mg/dl",
"sensitivity": 0,"test_description": "Glucose Tolerance Test"},
{"doctype": "Lab Test Template", "name": "HDL","test_name": "HDL (Serum)","test_code": "HDL",
"test_group": "Laboratory","department": "Biochemistry",
"test_group": _("Laboratory"),"department": _("Biochemistry"),
"item": "HDL","test_template_type": "Single",
"is_billable": 1,"test_rate": 0.0,"test_uom": "mg / dl","test_normal_range": "35 - 65 mg/dl",
"sensitivity": 0,"test_description": "High-density Lipoprotein (HDL)"},
{"doctype": "Lab Test Template", "name": "BILT","test_name": "Bilirubin Total","test_code": "BILT",
"test_group": "Laboratory","department": "Biochemistry",
"test_group": _("Laboratory"),"department": _("Biochemistry"),
"item": "BILT","test_template_type": "Single",
"is_billable": 1,"test_rate": 0.0,"test_uom": "mg / dl","test_normal_range": "0.2 - 1.2 mg / dl",
"sensitivity": 0,"test_description": "Bilirubin Total"},
{"doctype": "Lab Test Template", "name": "BILD","test_name": "Bilirubin Direct","test_code": "BILD",
"test_group": "Laboratory","department": "Biochemistry",
"test_group": _("Laboratory"),"department": _("Biochemistry"),
"item": "BILD","test_template_type": "Single",
"is_billable": 1,"test_rate": 0.0,"test_uom": "mg / dl","test_normal_range": "0.4 mg / dl",
"sensitivity": 0,"test_description": "Bilirubin Direct"},
{"doctype": "Lab Test Template", "name": "BP","test_name": "Bile Pigment","test_code": "BP",
"test_group": "Laboratory","department": "Pathology",
"test_group": _("Laboratory"),"department": _("Pathology"),
"item": "BP","test_template_type": "Single",
"is_billable": 1,"test_rate": 0.0,"test_uom": "","test_normal_range": "",
"sensitivity": 0,"test_description": "Bile Pigment"},
{"doctype": "Lab Test Template", "name": "BS","test_name": "Bile Salt","test_code": "BS",
"test_group": "Laboratory","department": "Pathology",
"test_group": _("Laboratory"),"department": _("Pathology"),
"item": "BS","test_template_type": "Single",
"is_billable": 1,"test_rate": 0.0,"test_uom": "","test_normal_range": "",
"sensitivity": 0,"test_description": "Bile Salt"}
@@ -257,12 +262,12 @@ def create_lab_test_template():
def create_sensitivity():
records = [
{"doctype": "Sensitivity", "sensitivity": "Low Sensitivity"},
{"doctype": "Sensitivity", "sensitivity": "High Sensitivity"},
{"doctype": "Sensitivity", "sensitivity": "Moderate Sensitivity"},
{"doctype": "Sensitivity", "sensitivity": "Susceptible"},
{"doctype": "Sensitivity", "sensitivity": "Resistant"},
{"doctype": "Sensitivity", "sensitivity": "Intermediate"}
{"doctype": "Sensitivity", "sensitivity": _("Low Sensitivity")},
{"doctype": "Sensitivity", "sensitivity": _("High Sensitivity")},
{"doctype": "Sensitivity", "sensitivity": _("Moderate Sensitivity")},
{"doctype": "Sensitivity", "sensitivity": _("Susceptible")},
{"doctype": "Sensitivity", "sensitivity": _("Resistant")},
{"doctype": "Sensitivity", "sensitivity": _("Intermediate")}
]
insert_record(records)

View File

@@ -19,6 +19,8 @@ def boot_session(bootinfo):
'territory')
bootinfo.sysdefaults.customer_group = frappe.db.get_single_value('Selling Settings',
'customer_group')
bootinfo.sysdefaults.allow_stale = frappe.db.get_single_value('Accounts Settings',
'allow_stale') or 1
bootinfo.notification_settings = frappe.get_doc("Notification Control",
"Notification Control")

View File

@@ -103,6 +103,11 @@ frappe.ui.form.on("Item", {
frappe.set_route("Form", "Item Variant Settings");
}, __("View"));
}
if(frm.doc.__onload && frm.doc.__onload.stock_exists) {
// Hide variants section if stock exists
frm.toggle_display("variants_section", 0);
}
},
validate: function(frm){

View File

@@ -1072,7 +1072,7 @@
"in_standard_filter": 0,
"label": "UOMs",
"length": 0,
"no_copy": 1,
"no_copy": 0,
"oldfieldname": "uom_conversion_details",
"oldfieldtype": "Table",
"options": "UOM Conversion Detail",
@@ -3205,7 +3205,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 1,
"modified": "2017-09-27 14:08:02.948326",
"modified": "2017-10-25 14:08:02.948326",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",
@@ -3382,4 +3382,4 @@
"title_field": "item_name",
"track_changes": 1,
"track_seen": 0
}
}

View File

@@ -17,6 +17,7 @@ from erpnext.controllers.item_variant import (get_variant, copy_attributes_to_va
make_variant_item_code, validate_item_variant_attributes, ItemVariantExistsError)
class DuplicateReorderRows(frappe.ValidationError): pass
class StockExistsForTemplate(frappe.ValidationError): pass
class Item(WebsiteGenerator):
website = frappe._dict(
@@ -28,11 +29,15 @@ class Item(WebsiteGenerator):
def onload(self):
super(Item, self).onload()
self.set_onload('sle_exists', self.check_if_sle_exists())
if self.is_fixed_asset:
asset = frappe.db.get_all("Asset", filters={"item_code": self.name, "docstatus": 1}, limit=1)
self.set_onload("asset_exists", True if asset else False)
if frappe.db.get_value('Stock Ledger Entry', {'item_code': self.name}):
self.set_onload('stock_exists', True)
def autoname(self):
if frappe.db.get_default("item_naming_by")=="Naming Series":
if self.variant_of:
@@ -85,6 +90,7 @@ class Item(WebsiteGenerator):
self.synced_with_hub = 0
self.validate_has_variants()
self.validate_stock_exists_for_template_item()
self.validate_attributes()
self.validate_variant_attributes()
self.validate_website_image()
@@ -631,6 +637,12 @@ class Item(WebsiteGenerator):
if frappe.db.exists("Item", {"variant_of": self.name}):
frappe.throw(_("Item has variants."))
def validate_stock_exists_for_template_item(self):
if self.has_variants and \
frappe.db.get_value('Stock Ledger Entry', {'item_code': self.name}):
frappe.throw(_("As stock exists against an item {0}, you can not enable has variants property")
.format(self.name), StockExistsForTemplate)
def validate_uom(self):
if not self.get("__islocal"):
check_stock_uom_with_bin(self.name, self.stock_uom)

View File

@@ -8,6 +8,7 @@ import frappe
from frappe.test_runner import make_test_records
from erpnext.controllers.item_variant import (create_variant, ItemVariantExistsError,
InvalidItemAttributeValueError, get_variant)
from erpnext.stock.doctype.item.item import StockExistsForTemplate
from frappe.model.rename_doc import rename_doc
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
@@ -263,6 +264,15 @@ class TestItem(unittest.TestCase):
self.assertEquals(variant.manufacturer, 'MSG1')
self.assertEquals(variant.manufacturer_part_no, '007')
def test_stock_exists_against_template_item(self):
stock_item = frappe.get_all('Stock Ledger Entry', fields = ["item_code"], limit=1)
if stock_item:
item_code = stock_item[0].item_code
item_doc = frappe.get_doc('Item', item_code)
item_doc.has_variants = 1
self.assertRaises(StockExistsForTemplate, item_doc.save)
def set_item_variant_settings(fields):
doc = frappe.get_doc('Item Variant Settings')
doc.set('fields', fields)

View File

@@ -2,8 +2,8 @@
<p>{{_("An error occured while creating recurring")}} {{ type }} <b>{{ name }}</b> {{_("for")}} <b>{{ party }}</b>.</p>
<p>{{_("This could be because of some invalid Email Addresses in the")}} {{ type }}.</p>
<p>{{_("To stop sending repetitive error notifications from the system, we have checked "Disabled" field in the subscription")}} {{ subscription}} {{_("for the")}} {{ type }} {{ name }}.</p>
<p><b>{{_("Please correct the")}} {{ type }} {{_('and unchcked "Disabled" in the')}} {{ subscription }} {{_("for making recurring again.")}}</b></p>
<p>{{_("To stop sending repetitive error notifications from the system, we have checked Disabled field in the subscription")}} {{ subscription}} {{_("for the")}} {{ type }} {{ name }}.</p>
<p><b>{{_("Please correct the")}} {{ type }} {{_('and unchcked Disabled in the')}} {{ subscription }} {{_("for making recurring again.")}}</b></p>
<hr>
<p><b>{{_("It is necessary to take this action today itself for the above mentioned recurring")}} {{ type }}
{{_('to be generated. If delayed, you will have to manually change the "Repeat on Day of Month" field