diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 405274a144..edbd9a25be 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from erpnext.hooks import regional_overrides -__version__ = '9.0.6' +__version__ = '9.0.7' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json index 85779533ea..fe41b42d9a 100644 --- a/erpnext/accounts/doctype/subscription/subscription.json +++ b/erpnext/accounts/doctype/subscription/subscription.json @@ -135,66 +135,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 1, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "disabled", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Disabled", - "length": 0, - "no_copy": 1, - "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": "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": 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, @@ -286,12 +226,12 @@ }, { "allow_bulk_edit": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "next_schedule_date", - "fieldtype": "Date", + "fieldname": "submit_on_creation", + "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -299,14 +239,44 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Next Schedule Date", + "label": "Submit on Creation", + "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, + "fieldname": "disabled", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Disabled", "length": 0, "no_copy": 1, "permlevel": 0, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, - "read_only": 1, + "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, @@ -320,7 +290,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "frequency_detail", + "fieldname": "section_break_10", "fieldtype": "Section Break", "hidden": 0, "ignore_user_permissions": 0, @@ -329,7 +299,95 @@ "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": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "from_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": "From 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, + "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, + "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_13", + "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, @@ -375,35 +433,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": 1, @@ -435,6 +464,36 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "next_schedule_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 Schedule Date", + "length": 0, + "no_copy": 1, + "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, @@ -690,7 +749,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-09-14 12:09:38.471458", + "modified": "2017-10-03 17:20:26.919630", "modified_by": "Administrator", "module": "Accounts", "name": "Subscription", @@ -700,7 +759,7 @@ { "amend": 0, "apply_user_permissions": 0, - "cancel": 0, + "cancel": 1, "create": 1, "delete": 1, "email": 1, @@ -720,7 +779,7 @@ { "amend": 0, "apply_user_permissions": 0, - "cancel": 0, + "cancel": 1, "create": 1, "delete": 1, "email": 1, @@ -740,7 +799,7 @@ { "amend": 0, "apply_user_permissions": 0, - "cancel": 0, + "cancel": 1, "create": 1, "delete": 1, "email": 1, diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index c9df7d461e..352a0aa87c 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -9,7 +9,7 @@ from frappe import _ from frappe.desk.form import assign_to from dateutil.relativedelta import relativedelta from frappe.utils.user import get_system_managers -from frappe.utils import cstr, getdate, split_emails, add_days, today +from frappe.utils import cstr, getdate, split_emails, add_days, today, get_last_day, get_first_day from frappe.model.document import Document month_map = {'Monthly': 1, 'Quarterly': 3, 'Half-yearly': 6, 'Yearly': 12} @@ -24,12 +24,23 @@ class Subscription(Document): self.set_next_schedule_date() def on_submit(self): - self.update_subscription_id() + # self.update_subscription_id() + self.update_subscription_data() 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() + + 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() + def validate_dates(self): if self.end_date and getdate(self.start_date) > getdate(self.end_date): frappe.throw(_("End date must be greater than start date")) @@ -64,6 +75,21 @@ class Subscription(Document): 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() + def update_subscription_id(self): doc = frappe.get_doc(self.reference_doctype, self.reference_document) if not doc.meta.get_field('subscription'): @@ -112,6 +138,9 @@ def get_subscription_entries(date): def create_documents(data, schedule_date): try: doc = make_new_document(data, schedule_date) + if doc.from_date: + update_subscription_period(data, doc) + if data.notify_by_email and data.recipients: print_format = data.print_format or "Standard" send_notification(doc, print_format, data.recipients) @@ -126,6 +155,13 @@ 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 disabled_subscription(data): subscription = frappe.get_doc('Subscription', data.name) subscription.db_set('disabled', 1) @@ -160,9 +196,24 @@ def update_doc(new_document, reference_doc, args, schedule_date): if new_document.meta.get_field('set_posting_time'): new_document.set('set_posting_time', 1) + mcount = month_map.get(args.frequency) + 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) + + 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) + + 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: diff --git a/erpnext/patches.txt b/erpnext/patches.txt index e75c490a36..113c40212f 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -448,3 +448,4 @@ 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 diff --git a/erpnext/patches/v9_0/fix_subscription_next_date.py b/erpnext/patches/v9_0/fix_subscription_next_date.py new file mode 100644 index 0000000000..a36e60ccaa --- /dev/null +++ b/erpnext/patches/v9_0/fix_subscription_next_date.py @@ -0,0 +1,27 @@ +# Copyright (c) 2017, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +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'] + + fields.extend(['from_date', 'to_date']) + reference_data = frappe.db.get_value(data.reference_doctype, + data.reference_document, fields, as_dict=1) + + 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() \ No newline at end of file diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js index f9045b5454..5eb822621e 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.js +++ b/erpnext/selling/page/point_of_sale/point_of_sale.js @@ -99,6 +99,17 @@ erpnext.pos.PointOfSale = class PointOfSale { if (value == 'Pay') { 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(mop_field, flt(amount)); } this.payment.open_modal(); } @@ -437,6 +448,12 @@ class POSCart { this.$taxes_and_totals.html(this.get_taxes_and_totals()); this.numpad && this.numpad.reset_value(); this.customer_field.set_value(""); + + this.wrapper.find('.grand-total-value').text( + format_currency(this.frm.doc.grand_total, this.frm.currency)); + + const customer = this.frm.doc.customer || this.pos_profile.customer; + this.customer_field.set_value(customer); } get_grand_total() { @@ -1179,6 +1196,10 @@ 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),