Merge branch 'version-13-pre-release' into version-13

This commit is contained in:
Nabin Hait 2021-05-06 19:18:17 +05:30
commit ec2ba6bc1f
22 changed files with 267 additions and 173 deletions

View File

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

View File

@ -13,7 +13,7 @@ class BalanceMismatchError(frappe.ValidationError): pass
class Account(NestedSet): class Account(NestedSet):
nsm_parent_field = 'parent_account' nsm_parent_field = 'parent_account'
def on_update(self): def on_update(self):
if frappe.local.flags.ignore_on_update: if frappe.local.flags.ignore_update_nsm:
return return
else: else:
super(Account, self).on_update() super(Account, self).on_update()

View File

@ -57,10 +57,10 @@ def create_charts(company, chart_template=None, existing_company=None, custom_ch
# Rebuild NestedSet HSM tree for Account Doctype # Rebuild NestedSet HSM tree for Account Doctype
# after all accounts are already inserted. # after all accounts are already inserted.
frappe.local.flags.ignore_on_update = True frappe.local.flags.ignore_update_nsm = True
_import_accounts(chart, None, None, root_account=True) _import_accounts(chart, None, None, root_account=True)
rebuild_tree("Account", "parent_account") rebuild_tree("Account", "parent_account")
frappe.local.flags.ignore_on_update = False frappe.local.flags.ignore_update_nsm = False
def add_suffix_if_duplicate(account_name, account_number, accounts): def add_suffix_if_duplicate(account_name, account_number, accounts):
if account_number: if account_number:

View File

@ -30,5 +30,5 @@ class AccountsSettings(Document):
def enable_payment_schedule_in_print(self): def enable_payment_schedule_in_print(self):
show_in_print = cint(self.show_payment_schedule_in_print) show_in_print = cint(self.show_payment_schedule_in_print)
for doctype in ("Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"): for doctype in ("Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"):
make_property_setter(doctype, "due_date", "print_hide", show_in_print, "Check") make_property_setter(doctype, "due_date", "print_hide", show_in_print, "Check", validate_fields_for_doctype=False)
make_property_setter(doctype, "payment_schedule", "print_hide", 0 if show_in_print else 1, "Check") make_property_setter(doctype, "payment_schedule", "print_hide", 0 if show_in_print else 1, "Check", validate_fields_for_doctype=False)

View File

@ -22,7 +22,43 @@ frappe.ui.form.on('POS Closing Entry', {
}); });
if (frm.doc.docstatus === 0 && !frm.doc.amended_from) frm.set_value("period_end_date", frappe.datetime.now_datetime()); if (frm.doc.docstatus === 0 && !frm.doc.amended_from) frm.set_value("period_end_date", frappe.datetime.now_datetime());
if (frm.doc.docstatus === 1) set_html_data(frm);
frappe.realtime.on('closing_process_complete', async function(data) {
await frm.reload_doc();
if (frm.doc.status == 'Failed' && frm.doc.error_message && data.user == frappe.session.user) {
frappe.msgprint({
title: __('POS Closing Failed'),
message: frm.doc.error_message,
indicator: 'orange',
clear: true
});
}
});
set_html_data(frm);
},
refresh: function(frm) {
if (frm.doc.docstatus == 1 && frm.doc.status == 'Failed') {
const issue = '<a id="jump_to_error" style="text-decoration: underline;">issue</a>';
frm.dashboard.set_headline(
__('POS Closing failed while running in a background process. You can resolve the {0} and retry the process again.', [issue]));
$('#jump_to_error').on('click', (e) => {
e.preventDefault();
frappe.utils.scroll_to(
cur_frm.get_field("error_message").$wrapper,
true,
30
);
});
frm.add_custom_button(__('Retry'), function () {
frm.call('retry', {}, () => {
frm.reload_doc();
});
});
}
}, },
pos_opening_entry(frm) { pos_opening_entry(frm) {
@ -61,16 +97,12 @@ frappe.ui.form.on('POS Closing Entry', {
refresh_fields(frm); refresh_fields(frm);
set_html_data(frm); set_html_data(frm);
} }
})
}
}); });
},
cur_frm.cscript.before_pos_transactions_remove = function(doc, cdt, cdn) { before_save: function(frm) {
const removed_row = locals[cdt][cdn]; for (let row of frm.doc.pos_transactions) {
frappe.db.get_doc("POS Invoice", row.pos_invoice).then(doc => {
if (!removed_row.pos_invoice) return;
frappe.db.get_doc("POS Invoice", removed_row.pos_invoice).then(doc => {
cur_frm.doc.grand_total -= flt(doc.grand_total); cur_frm.doc.grand_total -= flt(doc.grand_total);
cur_frm.doc.net_total -= flt(doc.net_total); cur_frm.doc.net_total -= flt(doc.net_total);
cur_frm.doc.total_quantity -= flt(doc.total_qty); cur_frm.doc.total_quantity -= flt(doc.total_qty);
@ -80,24 +112,8 @@ cur_frm.cscript.before_pos_transactions_remove = function(doc, cdt, cdn) {
set_html_data(cur_frm); set_html_data(cur_frm);
}); });
} }
frappe.ui.form.on('POS Invoice Reference', {
pos_invoice(frm, cdt, cdn) {
const added_row = locals[cdt][cdn];
if (!added_row.pos_invoice) return;
frappe.db.get_doc("POS Invoice", added_row.pos_invoice).then(doc => {
frm.doc.grand_total += flt(doc.grand_total);
frm.doc.net_total += flt(doc.net_total);
frm.doc.total_quantity += flt(doc.total_qty);
refresh_payments(doc, frm);
refresh_taxes(doc, frm);
refresh_fields(frm);
set_html_data(frm);
});
} }
}) });
frappe.ui.form.on('POS Closing Entry Detail', { frappe.ui.form.on('POS Closing Entry Detail', {
closing_amount: (frm, cdt, cdn) => { closing_amount: (frm, cdt, cdn) => {
@ -177,11 +193,13 @@ function refresh_fields(frm) {
} }
function set_html_data(frm) { function set_html_data(frm) {
if (frm.doc.docstatus === 1 && frm.doc.status == 'Submitted') {
frappe.call({ frappe.call({
method: "get_payment_reconciliation_details", method: "get_payment_reconciliation_details",
doc: frm.doc, doc: frm.doc,
callback: (r) => { callback: (r) => {
frm.get_field("payment_reconciliation_details").$wrapper.html(r.message); frm.get_field("payment_reconciliation_details").$wrapper.html(r.message);
} }
}) });
}
} }

View File

@ -30,6 +30,8 @@
"total_quantity", "total_quantity",
"column_break_16", "column_break_16",
"taxes", "taxes",
"failure_description_section",
"error_message",
"section_break_14", "section_break_14",
"amended_from" "amended_from"
], ],
@ -195,7 +197,7 @@
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 1, "hidden": 1,
"label": "Status", "label": "Status",
"options": "Draft\nSubmitted\nQueued\nCancelled", "options": "Draft\nSubmitted\nQueued\nFailed\nCancelled",
"print_hide": 1, "print_hide": 1,
"read_only": 1 "read_only": 1
}, },
@ -203,6 +205,21 @@
"fieldname": "period_details_section", "fieldname": "period_details_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Period Details" "label": "Period Details"
},
{
"collapsible": 1,
"collapsible_depends_on": "error_message",
"depends_on": "error_message",
"fieldname": "failure_description_section",
"fieldtype": "Section Break",
"label": "Failure Description"
},
{
"depends_on": "error_message",
"fieldname": "error_message",
"fieldtype": "Small Text",
"label": "Error",
"read_only": 1
} }
], ],
"is_submittable": 1, "is_submittable": 1,
@ -212,7 +229,7 @@
"link_fieldname": "pos_closing_entry" "link_fieldname": "pos_closing_entry"
} }
], ],
"modified": "2021-02-01 13:47:20.722104", "modified": "2021-05-05 16:59:49.723261",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "POS Closing Entry", "name": "POS Closing Entry",

View File

@ -60,6 +60,10 @@ class POSClosingEntry(StatusUpdater):
def on_cancel(self): def on_cancel(self):
unconsolidate_pos_invoices(closing_entry=self) unconsolidate_pos_invoices(closing_entry=self)
@frappe.whitelist()
def retry(self):
consolidate_pos_invoices(closing_entry=self)
def update_opening_entry(self, for_cancel=False): def update_opening_entry(self, for_cancel=False):
opening_entry = frappe.get_doc("POS Opening Entry", self.pos_opening_entry) opening_entry = frappe.get_doc("POS Opening Entry", self.pos_opening_entry)
opening_entry.pos_closing_entry = self.name if not for_cancel else None opening_entry.pos_closing_entry = self.name if not for_cancel else None

View File

@ -8,6 +8,7 @@ frappe.listview_settings['POS Closing Entry'] = {
"Draft": "red", "Draft": "red",
"Submitted": "blue", "Submitted": "blue",
"Queued": "orange", "Queued": "orange",
"Failed": "red",
"Cancelled": "red" "Cancelled": "red"
}; };

View File

@ -13,8 +13,7 @@ from frappe.model.mapper import map_doc, map_child_doc
from frappe.utils.scheduler import is_scheduler_inactive from frappe.utils.scheduler import is_scheduler_inactive
from frappe.core.page.background_jobs.background_jobs import get_info from frappe.core.page.background_jobs.background_jobs import get_info
import json import json
import six
from six import iteritems
class POSInvoiceMergeLog(Document): class POSInvoiceMergeLog(Document):
def validate(self): def validate(self):
@ -239,7 +238,7 @@ def consolidate_pos_invoices(pos_invoices=None, closing_entry=None):
invoices = pos_invoices or (closing_entry and closing_entry.get('pos_transactions')) or get_all_unconsolidated_invoices() invoices = pos_invoices or (closing_entry and closing_entry.get('pos_transactions')) or get_all_unconsolidated_invoices()
invoice_by_customer = get_invoice_customer_map(invoices) invoice_by_customer = get_invoice_customer_map(invoices)
if len(invoices) >= 1 and closing_entry: if len(invoices) >= 10 and closing_entry:
closing_entry.set_status(update=True, status='Queued') closing_entry.set_status(update=True, status='Queued')
enqueue_job(create_merge_logs, invoice_by_customer=invoice_by_customer, closing_entry=closing_entry) enqueue_job(create_merge_logs, invoice_by_customer=invoice_by_customer, closing_entry=closing_entry)
else: else:
@ -252,14 +251,15 @@ def unconsolidate_pos_invoices(closing_entry):
pluck='name' pluck='name'
) )
if len(merge_logs) >= 1: if len(merge_logs) >= 10:
closing_entry.set_status(update=True, status='Queued') closing_entry.set_status(update=True, status='Queued')
enqueue_job(cancel_merge_logs, merge_logs=merge_logs, closing_entry=closing_entry) enqueue_job(cancel_merge_logs, merge_logs=merge_logs, closing_entry=closing_entry)
else: else:
cancel_merge_logs(merge_logs, closing_entry) cancel_merge_logs(merge_logs, closing_entry)
def create_merge_logs(invoice_by_customer, closing_entry=None): def create_merge_logs(invoice_by_customer, closing_entry=None):
for customer, invoices in iteritems(invoice_by_customer): try:
for customer, invoices in six.iteritems(invoice_by_customer):
merge_log = frappe.new_doc('POS Invoice Merge Log') merge_log = frappe.new_doc('POS Invoice Merge Log')
merge_log.posting_date = getdate(closing_entry.get('posting_date')) if closing_entry else nowdate() merge_log.posting_date = getdate(closing_entry.get('posting_date')) if closing_entry else nowdate()
merge_log.customer = customer merge_log.customer = customer
@ -271,9 +271,25 @@ def create_merge_logs(invoice_by_customer, closing_entry=None):
if closing_entry: if closing_entry:
closing_entry.set_status(update=True, status='Submitted') closing_entry.set_status(update=True, status='Submitted')
closing_entry.db_set('error_message', '')
closing_entry.update_opening_entry() closing_entry.update_opening_entry()
except Exception:
frappe.db.rollback()
message_log = frappe.message_log.pop()
error_message = safe_load_json(message_log)
if closing_entry:
closing_entry.set_status(update=True, status='Failed')
closing_entry.db_set('error_message', error_message)
raise
finally:
frappe.db.commit()
frappe.publish_realtime('closing_process_complete', {'user': frappe.session.user})
def cancel_merge_logs(merge_logs, closing_entry=None): def cancel_merge_logs(merge_logs, closing_entry=None):
try:
for log in merge_logs: for log in merge_logs:
merge_log = frappe.get_doc('POS Invoice Merge Log', log) merge_log = frappe.get_doc('POS Invoice Merge Log', log)
merge_log.flags.ignore_permissions = True merge_log.flags.ignore_permissions = True
@ -281,8 +297,23 @@ def cancel_merge_logs(merge_logs, closing_entry=None):
if closing_entry: if closing_entry:
closing_entry.set_status(update=True, status='Cancelled') closing_entry.set_status(update=True, status='Cancelled')
closing_entry.db_set('error_message', '')
closing_entry.update_opening_entry(for_cancel=True) closing_entry.update_opening_entry(for_cancel=True)
except Exception:
frappe.db.rollback()
message_log = frappe.message_log.pop()
error_message = safe_load_json(message_log)
if closing_entry:
closing_entry.set_status(update=True, status='Submitted')
closing_entry.db_set('error_message', error_message)
raise
finally:
frappe.db.commit()
frappe.publish_realtime('closing_process_complete', {'user': frappe.session.user})
def enqueue_job(job, **kwargs): def enqueue_job(job, **kwargs):
check_scheduler_status() check_scheduler_status()
@ -315,3 +346,13 @@ def job_already_enqueued(job_name):
enqueued_jobs = [d.get("job_name") for d in get_info()] enqueued_jobs = [d.get("job_name") for d in get_info()]
if job_name in enqueued_jobs: if job_name in enqueued_jobs:
return True return True
def safe_load_json(message):
JSONDecodeError = ValueError if six.PY2 else json.JSONDecodeError
try:
json_message = json.loads(message).get('message')
except JSONDecodeError:
json_message = message
return json_message

View File

@ -98,6 +98,7 @@ status_map = {
["Draft", None], ["Draft", None],
["Submitted", "eval:self.docstatus == 1"], ["Submitted", "eval:self.docstatus == 1"],
["Queued", "eval:self.status == 'Queued'"], ["Queued", "eval:self.status == 'Queued'"],
["Failed", "eval:self.status == 'Failed'"],
["Cancelled", "eval:self.docstatus == 2"], ["Cancelled", "eval:self.docstatus == 2"],
] ]
} }

View File

@ -31,9 +31,9 @@ class EducationSettings(Document):
def validate(self): def validate(self):
from frappe.custom.doctype.property_setter.property_setter import make_property_setter from frappe.custom.doctype.property_setter.property_setter import make_property_setter
if self.get('instructor_created_by')=='Naming Series': if self.get('instructor_created_by')=='Naming Series':
make_property_setter('Instructor', "naming_series", "hidden", 0, "Check") make_property_setter('Instructor', "naming_series", "hidden", 0, "Check", validate_fields_for_doctype=False)
else: else:
make_property_setter('Instructor', "naming_series", "hidden", 1, "Check") make_property_setter('Instructor', "naming_series", "hidden", 1, "Check", validate_fields_for_doctype=False)
def update_website_context(context): def update_website_context(context):
context["lms_enabled"] = frappe.get_doc("Education Settings").enable_lms context["lms_enabled"] = frappe.get_doc("Education Settings").enable_lms

View File

@ -31,7 +31,8 @@ class Department(NestedSet):
return new return new
def on_update(self): def on_update(self):
NestedSet.on_update(self) if not frappe.local.flags.ignore_update_nsm:
super(Department, self).on_update()
def on_trash(self): def on_trash(self):
super(Department, self).on_trash() super(Department, self).on_trash()

View File

@ -774,3 +774,4 @@ erpnext.patches.v12_0.add_document_type_field_for_italy_einvoicing
erpnext.patches.v13_0.make_non_standard_user_type #13-04-2021 erpnext.patches.v13_0.make_non_standard_user_type #13-04-2021
erpnext.patches.v13_0.update_shipment_status erpnext.patches.v13_0.update_shipment_status
erpnext.patches.v13_0.remove_attribute_field_from_item_variant_setting erpnext.patches.v13_0.remove_attribute_field_from_item_variant_setting
erpnext.patches.v13_0.set_pos_closing_as_failed

View File

@ -0,0 +1,7 @@
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doc('accounts', 'doctype', 'pos_closing_entry')
frappe.db.sql("update `tabPOS Closing Entry` set `status` = 'Failed' where `status` = 'Queued'")

View File

@ -28,5 +28,5 @@ class PayrollSettings(Document):
def toggle_rounded_total(self): def toggle_rounded_total(self):
self.disable_rounded_total = cint(self.disable_rounded_total) self.disable_rounded_total = cint(self.disable_rounded_total)
make_property_setter("Salary Slip", "rounded_total", "hidden", self.disable_rounded_total, "Check") make_property_setter("Salary Slip", "rounded_total", "hidden", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)
make_property_setter("Salary Slip", "rounded_total", "print_hide", self.disable_rounded_total, "Check") make_property_setter("Salary Slip", "rounded_total", "print_hide", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)

View File

@ -1379,7 +1379,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
update_payment_schedule_grid_labels: function(company_currency) { update_payment_schedule_grid_labels: function(company_currency) {
const me = this; const me = this;
if (this.frm.fields_dict["payment_schedule"]) { if (this.frm.doc.payment_schedule && this.frm.doc.payment_schedule.length > 0) {
this.frm.set_currency_labels(["base_payment_amount", "base_outstanding", "base_paid_amount"], this.frm.set_currency_labels(["base_payment_amount", "base_outstanding", "base_paid_amount"],
company_currency, "payment_schedule"); company_currency, "payment_schedule");
this.frm.set_currency_labels(["payment_amount", "outstanding", "paid_amount"], this.frm.set_currency_labels(["payment_amount", "outstanding", "paid_amount"],
@ -2034,7 +2034,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
if(r.message && !r.exc) { if(r.message && !r.exc) {
me.frm.set_value("payment_schedule", r.message); me.frm.set_value("payment_schedule", r.message);
const company_currency = me.get_company_currency(); const company_currency = me.get_company_currency();
this.update_payment_schedule_grid_labels(company_currency); me.update_payment_schedule_grid_labels(company_currency);
} }
} }
}) })

View File

@ -30,8 +30,8 @@ class SellingSettings(Document):
# Make property setters to hide tax_id fields # Make property setters to hide tax_id fields
for doctype in ("Sales Order", "Sales Invoice", "Delivery Note"): for doctype in ("Sales Order", "Sales Invoice", "Delivery Note"):
make_property_setter(doctype, "tax_id", "hidden", self.hide_tax_id, "Check") make_property_setter(doctype, "tax_id", "hidden", self.hide_tax_id, "Check", validate_fields_for_doctype=False)
make_property_setter(doctype, "tax_id", "print_hide", self.hide_tax_id, "Check") make_property_setter(doctype, "tax_id", "print_hide", self.hide_tax_id, "Check", validate_fields_for_doctype=False)
def set_default_customer_group_and_territory(self): def set_default_customer_group_and_territory(self):
if not self.customer_group: if not self.customer_group:

View File

@ -60,11 +60,11 @@ class GlobalDefaults(Document):
# Make property setters to hide rounded total fields # Make property setters to hide rounded total fields
for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note", for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note",
"Supplier Quotation", "Purchase Order", "Purchase Invoice"): "Supplier Quotation", "Purchase Order", "Purchase Invoice"):
make_property_setter(doctype, "base_rounded_total", "hidden", self.disable_rounded_total, "Check") make_property_setter(doctype, "base_rounded_total", "hidden", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)
make_property_setter(doctype, "base_rounded_total", "print_hide", 1, "Check") make_property_setter(doctype, "base_rounded_total", "print_hide", 1, "Check", validate_fields_for_doctype=False)
make_property_setter(doctype, "rounded_total", "hidden", self.disable_rounded_total, "Check") make_property_setter(doctype, "rounded_total", "hidden", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)
make_property_setter(doctype, "rounded_total", "print_hide", self.disable_rounded_total, "Check") make_property_setter(doctype, "rounded_total", "print_hide", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)
def toggle_in_words(self): def toggle_in_words(self):
self.disable_in_words = cint(self.disable_in_words) self.disable_in_words = cint(self.disable_in_words)
@ -72,5 +72,5 @@ class GlobalDefaults(Document):
# Make property setters to hide in words fields # Make property setters to hide in words fields
for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note", for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note",
"Supplier Quotation", "Purchase Order", "Purchase Invoice", "Purchase Receipt"): "Supplier Quotation", "Purchase Order", "Purchase Invoice", "Purchase Receipt"):
make_property_setter(doctype, "in_words", "hidden", self.disable_in_words, "Check") make_property_setter(doctype, "in_words", "hidden", self.disable_in_words, "Check", validate_fields_for_doctype=False)
make_property_setter(doctype, "in_words", "print_hide", self.disable_in_words, "Check") make_property_setter(doctype, "in_words", "print_hide", self.disable_in_words, "Check", validate_fields_for_doctype=False)

View File

@ -183,8 +183,8 @@ class NamingSeries(Document):
def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True): def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True):
from frappe.custom.doctype.property_setter.property_setter import make_property_setter from frappe.custom.doctype.property_setter.property_setter import make_property_setter
if naming_series: if naming_series:
make_property_setter(doctype, "naming_series", "hidden", 0, "Check") make_property_setter(doctype, "naming_series", "hidden", 0, "Check", validate_fields_for_doctype=False)
make_property_setter(doctype, "naming_series", "reqd", 1, "Check") make_property_setter(doctype, "naming_series", "reqd", 1, "Check", validate_fields_for_doctype=False)
# set values for mandatory # set values for mandatory
try: try:
@ -195,15 +195,15 @@ def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True
pass pass
if hide_name_field: if hide_name_field:
make_property_setter(doctype, fieldname, "reqd", 0, "Check") make_property_setter(doctype, fieldname, "reqd", 0, "Check", validate_fields_for_doctype=False)
make_property_setter(doctype, fieldname, "hidden", 1, "Check") make_property_setter(doctype, fieldname, "hidden", 1, "Check", validate_fields_for_doctype=False)
else: else:
make_property_setter(doctype, "naming_series", "reqd", 0, "Check") make_property_setter(doctype, "naming_series", "reqd", 0, "Check", validate_fields_for_doctype=False)
make_property_setter(doctype, "naming_series", "hidden", 1, "Check") make_property_setter(doctype, "naming_series", "hidden", 1, "Check", validate_fields_for_doctype=False)
if hide_name_field: if hide_name_field:
make_property_setter(doctype, fieldname, "hidden", 0, "Check") make_property_setter(doctype, fieldname, "hidden", 0, "Check", validate_fields_for_doctype=False)
make_property_setter(doctype, fieldname, "reqd", 1, "Check") make_property_setter(doctype, fieldname, "reqd", 1, "Check", validate_fields_for_doctype=False)
# set values for mandatory # set values for mandatory
frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=`name` where frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=`name` where

View File

@ -12,6 +12,7 @@ from frappe.desk.doctype.global_search_settings.global_search_settings import up
from erpnext.accounts.doctype.account.account import RootNotEditable from erpnext.accounts.doctype.account.account import RootNotEditable
from erpnext.regional.address_template.setup import set_up_address_templates from erpnext.regional.address_template.setup import set_up_address_templates
from frappe.utils.nestedset import rebuild_tree
default_lead_sources = ["Existing Customer", "Reference", "Advertisement", default_lead_sources = ["Existing Customer", "Reference", "Advertisement",
"Cold Calling", "Exhibition", "Supplier Reference", "Mass Mailing", "Cold Calling", "Exhibition", "Supplier Reference", "Mass Mailing",
@ -280,13 +281,15 @@ def install(country=None):
set_more_defaults() set_more_defaults()
update_global_search_doctypes() update_global_search_doctypes()
# path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(country))
# if os.path.exists(path.encode("utf-8")):
# frappe.get_attr("erpnext.regional.{0}.setup.setup_company_independent_fixtures".format(frappe.scrub(country)))()
def set_more_defaults(): def set_more_defaults():
# Do more setup stuff that can be done here with no dependencies # Do more setup stuff that can be done here with no dependencies
update_selling_defaults()
update_buying_defaults()
update_hr_defaults()
add_uom_data()
update_item_variant_settings()
def update_selling_defaults():
selling_settings = frappe.get_doc("Selling Settings") selling_settings = frappe.get_doc("Selling Settings")
selling_settings.set_default_customer_group_and_territory() selling_settings.set_default_customer_group_and_territory()
selling_settings.cust_master_name = "Customer Name" selling_settings.cust_master_name = "Customer Name"
@ -296,13 +299,7 @@ def set_more_defaults():
selling_settings.sales_update_frequency = "Each Transaction" selling_settings.sales_update_frequency = "Each Transaction"
selling_settings.save() selling_settings.save()
add_uom_data() def update_buying_defaults():
# set no copy fields of an item doctype to item variant settings
doc = frappe.get_doc('Item Variant Settings')
doc.set_default_fields()
doc.save()
buying_settings = frappe.get_doc("Buying Settings") buying_settings = frappe.get_doc("Buying Settings")
buying_settings.supp_master_name = "Supplier Name" buying_settings.supp_master_name = "Supplier Name"
buying_settings.po_required = "No" buying_settings.po_required = "No"
@ -311,12 +308,19 @@ def set_more_defaults():
buying_settings.allow_multiple_items = 1 buying_settings.allow_multiple_items = 1
buying_settings.save() buying_settings.save()
def update_hr_defaults():
hr_settings = frappe.get_doc("HR Settings") hr_settings = frappe.get_doc("HR Settings")
hr_settings.emp_created_by = "Naming Series" hr_settings.emp_created_by = "Naming Series"
hr_settings.leave_approval_notification_template = _("Leave Approval Notification") hr_settings.leave_approval_notification_template = _("Leave Approval Notification")
hr_settings.leave_status_notification_template = _("Leave Status Notification") hr_settings.leave_status_notification_template = _("Leave Status Notification")
hr_settings.save() hr_settings.save()
def update_item_variant_settings():
# set no copy fields of an item doctype to item variant settings
doc = frappe.get_doc('Item Variant Settings')
doc.set_default_fields()
doc.save()
def add_uom_data(): def add_uom_data():
# add UOMs # add UOMs
uoms = json.loads(open(frappe.get_app_path("erpnext", "setup", "setup_wizard", "data", "uom_data.json")).read()) uoms = json.loads(open(frappe.get_app_path("erpnext", "setup", "setup_wizard", "data", "uom_data.json")).read())
@ -327,7 +331,7 @@ def add_uom_data():
"uom_name": _(d.get("uom_name")), "uom_name": _(d.get("uom_name")),
"name": _(d.get("uom_name")), "name": _(d.get("uom_name")),
"must_be_whole_number": d.get("must_be_whole_number") "must_be_whole_number": d.get("must_be_whole_number")
}).insert(ignore_permissions=True) }).db_insert()
# bootstrap uom conversion factors # bootstrap uom conversion factors
uom_conversions = json.loads(open(frappe.get_app_path("erpnext", "setup", "setup_wizard", "data", "uom_conversion_data.json")).read()) uom_conversions = json.loads(open(frappe.get_app_path("erpnext", "setup", "setup_wizard", "data", "uom_conversion_data.json")).read())
@ -336,7 +340,7 @@ def add_uom_data():
frappe.get_doc({ frappe.get_doc({
"doctype": "UOM Category", "doctype": "UOM Category",
"category_name": _(d.get("category")) "category_name": _(d.get("category"))
}).insert(ignore_permissions=True) }).db_insert()
if not frappe.db.exists("UOM Conversion Factor", {"from_uom": _(d.get("from_uom")), "to_uom": _(d.get("to_uom"))}): if not frappe.db.exists("UOM Conversion Factor", {"from_uom": _(d.get("from_uom")), "to_uom": _(d.get("to_uom"))}):
uom_conversion = frappe.get_doc({ uom_conversion = frappe.get_doc({
@ -369,8 +373,8 @@ def add_sale_stages():
{"doctype": "Sales Stage", "stage_name": _("Proposal/Price Quote")}, {"doctype": "Sales Stage", "stage_name": _("Proposal/Price Quote")},
{"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")} {"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")}
] ]
for sales_stage in records:
make_records(records) frappe.get_doc(sales_stage).db_insert()
def install_company(args): def install_company(args):
records = [ records = [
@ -418,7 +422,14 @@ def install_post_company_fixtures(args=None):
{'doctype': 'Department', 'department_name': _('Legal'), 'parent_department': _('All Departments'), 'company': args.company_name}, {'doctype': 'Department', 'department_name': _('Legal'), 'parent_department': _('All Departments'), 'company': args.company_name},
] ]
make_records(records) # Make root department with NSM updation
make_records(records[:1])
frappe.local.flags.ignore_update_nsm = True
make_records(records[1:])
frappe.local.flags.ignore_update_nsm = False
rebuild_tree("Department", "parent_department")
def install_defaults(args=None): def install_defaults(args=None):
@ -432,7 +443,15 @@ def install_defaults(args=None):
# enable default currency # enable default currency
frappe.db.set_value("Currency", args.get("currency"), "enabled", 1) frappe.db.set_value("Currency", args.get("currency"), "enabled", 1)
frappe.db.set_value("Stock Settings", None, "email_footer_address", args.get("company_name"))
set_global_defaults(args)
set_active_domains(args)
update_stock_settings()
update_shopping_cart_settings(args)
create_bank_account(args)
def set_global_defaults(args):
global_defaults = frappe.get_doc("Global Defaults", "Global Defaults") global_defaults = frappe.get_doc("Global Defaults", "Global Defaults")
current_fiscal_year = frappe.get_all("Fiscal Year")[0] current_fiscal_year = frappe.get_all("Fiscal Year")[0]
@ -445,13 +464,10 @@ def install_defaults(args=None):
global_defaults.save() global_defaults.save()
system_settings = frappe.get_doc("System Settings") def set_active_domains(args):
system_settings.email_footer_address = args.get("company_name") frappe.get_single('Domain Settings').set_active_domains(args.get('domains'))
system_settings.save()
domain_settings = frappe.get_single('Domain Settings')
domain_settings.set_active_domains(args.get('domains'))
def update_stock_settings():
stock_settings = frappe.get_doc("Stock Settings") stock_settings = frappe.get_doc("Stock Settings")
stock_settings.item_naming_by = "Item Code" stock_settings.item_naming_by = "Item Code"
stock_settings.valuation_method = "FIFO" stock_settings.valuation_method = "FIFO"
@ -463,7 +479,10 @@ def install_defaults(args=None):
stock_settings.set_qty_in_transactions_based_on_serial_no_input = 1 stock_settings.set_qty_in_transactions_based_on_serial_no_input = 1
stock_settings.save() stock_settings.save()
if args.bank_account: def create_bank_account(args):
if not args.bank_account:
return
company_name = args.company_name company_name = args.company_name
bank_account_group = frappe.db.get_value("Account", bank_account_group = frappe.db.get_value("Account",
{"account_type": "Bank", "is_group": 1, "root_type": "Asset", {"account_type": "Bank", "is_group": 1, "root_type": "Asset",
@ -488,23 +507,16 @@ def install_defaults(args=None):
# bank account same as a CoA entry # bank account same as a CoA entry
pass pass
# Now, with fixtures out of the way, onto concrete stuff def update_shopping_cart_settings(args):
records = [ shopping_cart = frappe.get_doc("Shopping Cart Settings")
shopping_cart.update({
# Shopping cart: needs price lists
{
"doctype": "Shopping Cart Settings",
"enabled": 1, "enabled": 1,
'company': args.company_name, 'company': args.company_name,
# uh oh
'price_list': frappe.db.get_value("Price List", {"selling": 1}), 'price_list': frappe.db.get_value("Price List", {"selling": 1}),
'default_customer_group': _("Individual"), 'default_customer_group': _("Individual"),
'quotation_series': "QTN-", 'quotation_series': "QTN-",
}, })
] shopping_cart.update_single(shopping_cart.get_valid_dict())
make_records(records)
def get_fy_details(fy_start_date, fy_end_date): def get_fy_details(fy_start_date, fy_end_date):
start_year = getdate(fy_start_date).year start_year = getdate(fy_start_date).year

View File

@ -51,11 +51,6 @@ def get_setup_stages(args=None):
'status': _('Setting defaults'), 'status': _('Setting defaults'),
'fail_msg': 'Failed to set defaults', 'fail_msg': 'Failed to set defaults',
'tasks': [ 'tasks': [
{
'fn': setup_post_company_fixtures,
'args': args,
'fail_msg': _("Failed to setup post company fixtures")
},
{ {
'fn': setup_defaults, 'fn': setup_defaults,
'args': args, 'args': args,
@ -94,9 +89,6 @@ def stage_fixtures(args):
def setup_company(args): def setup_company(args):
fixtures.install_company(args) fixtures.install_company(args)
def setup_post_company_fixtures(args):
fixtures.install_post_company_fixtures(args)
def setup_defaults(args): def setup_defaults(args):
fixtures.install_defaults(frappe._dict(args)) fixtures.install_defaults(frappe._dict(args))
@ -129,7 +121,6 @@ def login_as_first_user(args):
def setup_complete(args=None): def setup_complete(args=None):
stage_fixtures(args) stage_fixtures(args)
setup_company(args) setup_company(args)
setup_post_company_fixtures(args)
setup_defaults(args) setup_defaults(args)
stage_four(args) stage_four(args)
fin(args) fin(args)

View File

@ -30,7 +30,7 @@ class StockSettings(Document):
# show/hide barcode field # show/hide barcode field
for name in ["barcode", "barcodes", "scan_barcode"]: for name in ["barcode", "barcodes", "scan_barcode"]:
frappe.make_property_setter({'fieldname': name, 'property': 'hidden', frappe.make_property_setter({'fieldname': name, 'property': 'hidden',
'value': 0 if self.show_barcode_field else 1}) 'value': 0 if self.show_barcode_field else 1}, validate_fields_for_doctype=False)
self.validate_warehouses() self.validate_warehouses()
self.cant_change_valuation_method() self.cant_change_valuation_method()
@ -67,10 +67,10 @@ class StockSettings(Document):
self.toggle_warehouse_field_for_inter_warehouse_transfer() self.toggle_warehouse_field_for_inter_warehouse_transfer()
def toggle_warehouse_field_for_inter_warehouse_transfer(self): def toggle_warehouse_field_for_inter_warehouse_transfer(self):
make_property_setter("Sales Invoice Item", "target_warehouse", "hidden", 1 - cint(self.allow_from_dn), "Check") make_property_setter("Sales Invoice Item", "target_warehouse", "hidden", 1 - cint(self.allow_from_dn), "Check", validate_fields_for_doctype=False)
make_property_setter("Delivery Note Item", "target_warehouse", "hidden", 1 - cint(self.allow_from_dn), "Check") make_property_setter("Delivery Note Item", "target_warehouse", "hidden", 1 - cint(self.allow_from_dn), "Check", validate_fields_for_doctype=False)
make_property_setter("Purchase Invoice Item", "from_warehouse", "hidden", 1 - cint(self.allow_from_pr), "Check") make_property_setter("Purchase Invoice Item", "from_warehouse", "hidden", 1 - cint(self.allow_from_pr), "Check", validate_fields_for_doctype=False)
make_property_setter("Purchase Receipt Item", "from_warehouse", "hidden", 1 - cint(self.allow_from_pr), "Check") make_property_setter("Purchase Receipt Item", "from_warehouse", "hidden", 1 - cint(self.allow_from_pr), "Check", validate_fields_for_doctype=False)
def clean_all_descriptions(): def clean_all_descriptions():