Refactor multi pos profile selection in the pos invoice (#11721)
This commit is contained in:
committed by
Nabin Hait
parent
8d9edbf133
commit
c037dc775e
@@ -2,7 +2,7 @@
|
|||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
"allow_guest_to_view": 0,
|
"allow_guest_to_view": 0,
|
||||||
"allow_import": 0,
|
"allow_import": 0,
|
||||||
"allow_rename": 0,
|
"allow_rename": 1,
|
||||||
"autoname": "field:pos_profile_name",
|
"autoname": "field:pos_profile_name",
|
||||||
"beta": 0,
|
"beta": 0,
|
||||||
"creation": "2013-05-24 12:15:51",
|
"creation": "2013-05-24 12:15:51",
|
||||||
@@ -1508,7 +1508,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-10-27 06:45:32.957674",
|
"modified": "2017-11-24 14:08:09.184226",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "POS Profile",
|
"name": "POS Profile",
|
||||||
@@ -1558,6 +1558,7 @@
|
|||||||
"quick_entry": 0,
|
"quick_entry": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 0,
|
||||||
|
"search_fields": "pos_profile_name",
|
||||||
"show_name_in_global_search": 0,
|
"show_name_in_global_search": 0,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
|||||||
@@ -4,30 +4,34 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import msgprint, _
|
from frappe import msgprint, _
|
||||||
from frappe.utils import cint
|
from frappe.utils import cint, now
|
||||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import set_account_for_mode_of_payment
|
from erpnext.accounts.doctype.sales_invoice.sales_invoice import set_account_for_mode_of_payment
|
||||||
|
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class POSProfile(Document):
|
class POSProfile(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
# self.check_for_duplicate()
|
self.validate_default_profile()
|
||||||
self.validate_all_link_fields()
|
self.validate_all_link_fields()
|
||||||
self.validate_duplicate_groups()
|
self.validate_duplicate_groups()
|
||||||
self.check_default_payment()
|
self.check_default_payment()
|
||||||
self.validate_customer_territory_group()
|
self.validate_customer_territory_group()
|
||||||
|
|
||||||
def check_for_duplicate(self):
|
def validate_default_profile(self):
|
||||||
res = frappe.db.sql("""select name, user from `tabPOS Profile`
|
for row in self.applicable_for_users:
|
||||||
where ifnull(user, '') = %s and name != %s and company = %s and ifnull(disabled, 0) != 1""",
|
res = frappe.db.sql("""select pf.name
|
||||||
(self.user, self.name, self.company))
|
from
|
||||||
if res:
|
`tabPOS Profile User` pfu, `tabPOS Profile` pf
|
||||||
if res[0][1]:
|
where
|
||||||
msgprint(_("POS Profile {0} already created for user: {1} and company {2}").format(res[0][0],
|
pf.name = pfu.parent and pfu.user = %s and pf.name != %s and pf.company = %s
|
||||||
res[0][1], self.company), raise_exception=1)
|
and pfu.default=1""", (row.user, self.name, self.company))
|
||||||
else:
|
|
||||||
msgprint(_("Global POS Profile {0} already created for company {1}").format(res[0][0],
|
if row.default and res:
|
||||||
self.company), raise_exception=1)
|
msgprint(_("Already set default in pos profile {0} for user {1}, kindly disabled default")
|
||||||
|
.format(res[0][0], row.user), raise_exception=1)
|
||||||
|
elif not row.default and not res:
|
||||||
|
msgprint(_("Row {0}: set atleast one default pos profile for user {1}")
|
||||||
|
.format(row.idx, row.user), raise_exception=1)
|
||||||
|
|
||||||
def validate_all_link_fields(self):
|
def validate_all_link_fields(self):
|
||||||
accounts = {"Account": [self.income_account,
|
accounts = {"Account": [self.income_account,
|
||||||
@@ -95,44 +99,58 @@ class POSProfile(Document):
|
|||||||
def get_series():
|
def get_series():
|
||||||
return frappe.get_meta("Sales Invoice").get_field("naming_series").options or ""
|
return frappe.get_meta("Sales Invoice").get_field("naming_series").options or ""
|
||||||
|
|
||||||
@frappe.whitelist()
|
def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):
|
||||||
def get_pos_profiles_for_user(user=None):
|
user = frappe.session['user']
|
||||||
out = []
|
company = filters.get('company') or frappe.defaults.get_user_default('company')
|
||||||
if not user:
|
|
||||||
user = frappe.session.user
|
|
||||||
|
|
||||||
res = frappe.db.sql('''
|
args = {
|
||||||
select
|
'user': user,
|
||||||
parent
|
'start': start,
|
||||||
|
'company': company,
|
||||||
|
'page_len': page_len,
|
||||||
|
'txt': '%%%s%%' % txt
|
||||||
|
}
|
||||||
|
|
||||||
|
pos_profile = frappe.db.sql("""select pf.name, pf.pos_profile_name
|
||||||
from
|
from
|
||||||
`tabPOS Profile User`
|
`tabPOS Profile` pf, `tabPOS Profile User` pfu
|
||||||
where
|
where
|
||||||
user = %s
|
pfu.parent = pf.name and pfu.user = %(user)s and pf.company = %(company)s
|
||||||
''', (user), as_dict=1)
|
and (pf.name like %(txt)s or pf.pos_profile_name like %(txt)s)
|
||||||
|
and pf.disabled = 0 limit %(start)s, %(page_len)s""", args)
|
||||||
|
|
||||||
if not res:
|
if not pos_profile:
|
||||||
company = frappe.defaults.get_user_default('company')
|
del args['user']
|
||||||
res = frappe.db.sql('''
|
|
||||||
select
|
pos_profile = frappe.db.sql("""select pf.name, pf.pos_profile_name
|
||||||
pos_profile_name
|
|
||||||
from
|
from
|
||||||
`tabPOS Profile`
|
`tabPOS Profile` pf left join `tabPOS Profile User` pfu
|
||||||
|
on
|
||||||
|
pf.name = pfu.parent
|
||||||
where
|
where
|
||||||
company = %s
|
ifnull(pfu.user, '') = '' and pf.company = %(company)s and
|
||||||
''', (company), as_dict=1)
|
(pf.name like %(txt)s or pf.pos_profile_name like %(txt)s)
|
||||||
|
and pf.disabled = 0""", args)
|
||||||
|
|
||||||
out = [r.pos_profile_name for r in res]
|
return pos_profile
|
||||||
|
|
||||||
return out
|
|
||||||
|
|
||||||
for r in res:
|
|
||||||
name = frappe.db.get_value('POS Profile', r.parent, 'pos_profile_name')
|
|
||||||
out.append(name)
|
|
||||||
|
|
||||||
return out
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_pos_profile(pos_profile_name=None):
|
def set_default_profile(pos_profile, company):
|
||||||
if not pos_profile_name: return
|
modified = now()
|
||||||
name = frappe.db.get_value('POS Profile', { 'pos_profile_name': pos_profile_name })
|
user = frappe.session.user
|
||||||
return frappe.get_doc('POS Profile', name)
|
company = frappe.db.escape(company)
|
||||||
|
|
||||||
|
if pos_profile and company:
|
||||||
|
frappe.db.sql(""" update `tabPOS Profile User` pfu, `tabPOS Profile` pf
|
||||||
|
set
|
||||||
|
pfu.default = 0, pf.modified = %s, pf.modified_by = %s
|
||||||
|
where
|
||||||
|
pfu.user = %s and pf.name = pfu.parent and pf.company = %s
|
||||||
|
and pfu.default = 1""", (modified, user, user, company), auto_commit=1)
|
||||||
|
|
||||||
|
frappe.db.sql(""" update `tabPOS Profile User` pfu, `tabPOS Profile` pf
|
||||||
|
set
|
||||||
|
pfu.default = 1, pf.modified = %s, pf.modified_by = %s
|
||||||
|
where
|
||||||
|
pfu.user = %s and pf.name = pfu.parent and pf.company = %s and pf.name = %s
|
||||||
|
""", (modified, user, user, company, pos_profile), auto_commit=1)
|
||||||
|
|||||||
@@ -12,6 +12,36 @@
|
|||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"fields": [
|
"fields": [
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "default",
|
||||||
|
"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": "Default",
|
||||||
|
"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_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@@ -54,7 +84,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-10-27 16:46:12.784244",
|
"modified": "2017-11-23 17:13:16.005475",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "POS Profile User",
|
"name": "POS Profile User",
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
// rename this file from _test_[name] to test_[name] to activate
|
||||||
|
// and remove above this line
|
||||||
|
|
||||||
|
QUnit.test("test: POS Profile User", function (assert) {
|
||||||
|
let done = assert.async();
|
||||||
|
|
||||||
|
// number of asserts
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
frappe.run_serially([
|
||||||
|
// insert a new POS Profile User
|
||||||
|
() => frappe.tests.make('POS Profile User', [
|
||||||
|
// values to be set
|
||||||
|
{key: 'value'}
|
||||||
|
]),
|
||||||
|
() => {
|
||||||
|
assert.equal(cur_frm.doc.key, 'value');
|
||||||
|
},
|
||||||
|
() => done()
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class TestPOSProfileUser(unittest.TestCase):
|
||||||
|
pass
|
||||||
@@ -311,6 +311,14 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
},
|
},
|
||||||
|
|
||||||
is_pos: function(frm){
|
is_pos: function(frm){
|
||||||
|
this.set_pos_data();
|
||||||
|
},
|
||||||
|
|
||||||
|
pos_profile: function() {
|
||||||
|
this.set_pos_data();
|
||||||
|
},
|
||||||
|
|
||||||
|
set_pos_data: function() {
|
||||||
if(this.frm.doc.is_pos) {
|
if(this.frm.doc.is_pos) {
|
||||||
if(!this.frm.doc.company) {
|
if(!this.frm.doc.company) {
|
||||||
this.frm.set_value("is_pos", 0);
|
this.frm.set_value("is_pos", 0);
|
||||||
@@ -323,7 +331,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(!r.exc) {
|
if(!r.exc) {
|
||||||
if(r.message && r.message.print_format) {
|
if(r.message && r.message.print_format) {
|
||||||
frm.pos_print_format = r.message.print_format;
|
me.frm.pos_print_format = r.message.print_format;
|
||||||
}
|
}
|
||||||
me.frm.script_manager.trigger("update_stock");
|
me.frm.script_manager.trigger("update_stock");
|
||||||
frappe.model.set_default_values(me.frm.doc);
|
frappe.model.set_default_values(me.frm.doc);
|
||||||
@@ -540,6 +548,19 @@ frappe.ui.form.on('Sales Invoice', {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frm.set_query('pos_profile', function(doc) {
|
||||||
|
if(!doc.company) {
|
||||||
|
frappe.throw(_('Please set Company'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query',
|
||||||
|
filters: {
|
||||||
|
company: doc.company
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
},
|
},
|
||||||
//When multiple companies are set up. in case company name is changed set default company address
|
//When multiple companies are set up. in case company name is changed set default company address
|
||||||
company:function(frm){
|
company:function(frm){
|
||||||
|
|||||||
@@ -294,21 +294,23 @@ class SalesInvoice(SellingController):
|
|||||||
return
|
return
|
||||||
|
|
||||||
from erpnext.stock.get_item_details import get_pos_profile_item_details, get_pos_profile
|
from erpnext.stock.get_item_details import get_pos_profile_item_details, get_pos_profile
|
||||||
pos = get_pos_profile(self.company)
|
if not self.pos_profile:
|
||||||
|
pos_profile = get_pos_profile(self.company) or {}
|
||||||
|
self.pos_profile = pos_profile.get('name')
|
||||||
|
|
||||||
|
pos = {}
|
||||||
|
if self.pos_profile:
|
||||||
|
pos = frappe.get_doc('POS Profile', self.pos_profile)
|
||||||
|
|
||||||
if not self.get('payments') and not for_validate:
|
if not self.get('payments') and not for_validate:
|
||||||
pos_profile = frappe.get_doc('POS Profile', pos.name) if pos else None
|
update_multi_mode_option(self, pos)
|
||||||
update_multi_mode_option(self, pos_profile)
|
|
||||||
|
|
||||||
if not self.account_for_change_amount:
|
if not self.account_for_change_amount:
|
||||||
self.account_for_change_amount = frappe.db.get_value('Company', self.company, 'default_cash_account')
|
self.account_for_change_amount = frappe.db.get_value('Company', self.company, 'default_cash_account')
|
||||||
|
|
||||||
if pos:
|
if pos:
|
||||||
self.pos_profile = pos.name
|
|
||||||
if not for_validate and not self.customer:
|
if not for_validate and not self.customer:
|
||||||
self.customer = pos.customer
|
self.customer = pos.customer
|
||||||
self.mode_of_payment = pos.mode_of_payment
|
|
||||||
# self.set_customer_defaults()
|
|
||||||
|
|
||||||
if pos.get('account_for_change_amount'):
|
if pos.get('account_for_change_amount'):
|
||||||
self.account_for_change_amount = pos.get('account_for_change_amount')
|
self.account_for_change_amount = pos.get('account_for_change_amount')
|
||||||
|
|||||||
@@ -449,7 +449,7 @@ 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.delete_gst_doctypes_for_outside_india_accounts
|
||||||
erpnext.patches.v8_9.set_default_fields_in_variant_settings
|
erpnext.patches.v8_9.set_default_fields_in_variant_settings
|
||||||
erpnext.patches.v8_9.update_billing_gstin_for_indian_account
|
erpnext.patches.v8_9.update_billing_gstin_for_indian_account
|
||||||
erpnext.patches.v9_0.add_user_to_child_table_in_pos_profile
|
erpnext.patches.v9_0.add_user_to_child_table_in_pos_profile #2017-11-28
|
||||||
erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
|
erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
|
||||||
erpnext.patches.v9_0.student_admission_childtable_migrate
|
erpnext.patches.v9_0.student_admission_childtable_migrate
|
||||||
erpnext.patches.v9_0.fix_subscription_next_date #2017-10-23
|
erpnext.patches.v9_0.fix_subscription_next_date #2017-10-23
|
||||||
|
|||||||
@@ -5,23 +5,34 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
doctype = 'POS Profile'
|
if frappe.db.table_exists("POS Profile User"):
|
||||||
frappe.reload_doc('accounts', 'doctype', doctype)
|
frappe.reload_doc('accounts', 'doctype', 'pos_profile_user')
|
||||||
frappe.reload_doc('accounts', 'doctype', 'pos_profile_user')
|
|
||||||
frappe.reload_doc('accounts', 'doctype', 'pos_item_group')
|
|
||||||
frappe.reload_doc('accounts', 'doctype', 'pos_customer_group')
|
|
||||||
|
|
||||||
for doc in frappe.get_all(doctype):
|
frappe.db.sql(""" update `tabPOS Profile User`,
|
||||||
_doc = frappe.get_doc(doctype, doc.name)
|
(select `tabPOS Profile User`.name from `tabPOS Profile User`, `tabPOS Profile`
|
||||||
user = frappe.db.get_value(doctype, doc.name, 'user')
|
where `tabPOS Profile`.name = `tabPOS Profile User`.parent
|
||||||
|
group by `tabPOS Profile User`.user, `tabPOS Profile`.company) as pfu
|
||||||
|
set
|
||||||
|
`tabPOS Profile User`.default = 1
|
||||||
|
where `tabPOS Profile User`.name = pfu.name""")
|
||||||
|
else:
|
||||||
|
doctype = 'POS Profile'
|
||||||
|
frappe.reload_doc('accounts', 'doctype', doctype)
|
||||||
|
frappe.reload_doc('accounts', 'doctype', 'pos_profile_user')
|
||||||
|
frappe.reload_doc('accounts', 'doctype', 'pos_item_group')
|
||||||
|
frappe.reload_doc('accounts', 'doctype', 'pos_customer_group')
|
||||||
|
|
||||||
if not user: continue
|
for doc in frappe.get_all(doctype):
|
||||||
|
_doc = frappe.get_doc(doctype, doc.name)
|
||||||
|
user = frappe.db.get_value(doctype, doc.name, 'user')
|
||||||
|
|
||||||
_doc.append('applicable_for_users', {
|
if not user: continue
|
||||||
'user': user
|
|
||||||
})
|
|
||||||
_doc.pos_profile_name = user + ' - ' + _doc.company
|
|
||||||
_doc.flags.ignore_validate = True
|
|
||||||
_doc.flags.ignore_mandatory = True
|
|
||||||
_doc.save()
|
|
||||||
|
|
||||||
|
_doc.append('applicable_for_users', {
|
||||||
|
'user': user,
|
||||||
|
'default': 1
|
||||||
|
})
|
||||||
|
_doc.pos_profile_name = user + ' - ' + _doc.company
|
||||||
|
_doc.flags.ignore_validate = True
|
||||||
|
_doc.flags.ignore_mandatory = True
|
||||||
|
_doc.save()
|
||||||
@@ -322,7 +322,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
project: item.project || me.frm.doc.project,
|
project: item.project || me.frm.doc.project,
|
||||||
qty: item.qty || 1,
|
qty: item.qty || 1,
|
||||||
stock_qty: item.stock_qty,
|
stock_qty: item.stock_qty,
|
||||||
conversion_factor: item.conversion_factor
|
conversion_factor: item.conversion_factor,
|
||||||
|
pos_profile: me.frm.doc.doctype == 'Sales Invoice' ? me.frm.doc.pos_profile : ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -891,7 +892,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
"name": me.frm.doc.name,
|
"name": me.frm.doc.name,
|
||||||
"is_return": cint(me.frm.doc.is_return),
|
"is_return": cint(me.frm.doc.is_return),
|
||||||
"update_stock": in_list(['Sales Invoice', 'Purchase Invoice'], me.frm.doc.doctype) ? cint(me.frm.doc.update_stock) : 0,
|
"update_stock": in_list(['Sales Invoice', 'Purchase Invoice'], me.frm.doc.doctype) ? cint(me.frm.doc.update_stock) : 0,
|
||||||
"conversion_factor": me.frm.doc.conversion_factor
|
"conversion_factor": me.frm.doc.conversion_factor,
|
||||||
|
"pos_profile": me.frm.doc.doctype == 'Sales Invoice' ? me.frm.doc.pos_profile : ''
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ erpnext.pos.PointOfSale = class PointOfSale {
|
|||||||
this.set_online_status();
|
this.set_online_status();
|
||||||
},
|
},
|
||||||
() => this.setup_company(),
|
() => this.setup_company(),
|
||||||
() => this.setup_pos_profile(),
|
|
||||||
() => this.make_new_invoice(),
|
() => this.make_new_invoice(),
|
||||||
() => {
|
() => {
|
||||||
frappe.dom.unfreeze();
|
frappe.dom.unfreeze();
|
||||||
@@ -90,7 +90,6 @@ erpnext.pos.PointOfSale = class PointOfSale {
|
|||||||
this.cart = new POSCart({
|
this.cart = new POSCart({
|
||||||
frm: this.frm,
|
frm: this.frm,
|
||||||
wrapper: this.wrapper.find('.cart-container'),
|
wrapper: this.wrapper.find('.cart-container'),
|
||||||
pos_profile: this.pos_profile,
|
|
||||||
events: {
|
events: {
|
||||||
on_customer_change: (customer) => this.frm.set_value('customer', customer),
|
on_customer_change: (customer) => this.frm.set_value('customer', customer),
|
||||||
on_field_change: (item_code, field, value) => {
|
on_field_change: (item_code, field, value) => {
|
||||||
@@ -141,7 +140,7 @@ erpnext.pos.PointOfSale = class PointOfSale {
|
|||||||
make_items() {
|
make_items() {
|
||||||
this.items = new POSItems({
|
this.items = new POSItems({
|
||||||
wrapper: this.wrapper.find('.item-container'),
|
wrapper: this.wrapper.find('.item-container'),
|
||||||
pos_profile: this.pos_profile,
|
frm: this.frm,
|
||||||
events: {
|
events: {
|
||||||
update_cart: (item, field, value) => {
|
update_cart: (item, field, value) => {
|
||||||
if(!this.frm.doc.customer) {
|
if(!this.frm.doc.customer) {
|
||||||
@@ -292,68 +291,62 @@ erpnext.pos.PointOfSale = class PointOfSale {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_pos_profile() {
|
change_pos_profile() {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
|
const on_submit = ({ pos_profile, set_as_default }) => {
|
||||||
const load_default = () => {
|
if (pos_profile) {
|
||||||
this.pos_profile = {
|
this.frm.doc.pos_profile = pos_profile;
|
||||||
company: this.company,
|
|
||||||
currency: frappe.defaults.get_default('currency'),
|
|
||||||
selling_price_list: frappe.defaults.get_default('selling_price_list')
|
|
||||||
};
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
const on_submit = ({ pos_profile }) => {
|
|
||||||
this.get_pos_profile_doc(pos_profile)
|
|
||||||
.then(doc => {
|
|
||||||
this.pos_profile = doc;
|
|
||||||
if (!this.pos_profile) {
|
|
||||||
load_default();
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
frappe.call({
|
|
||||||
method: 'erpnext.accounts.doctype.pos_profile.pos_profile.get_pos_profiles_for_user'
|
|
||||||
}).then((r) => {
|
|
||||||
if (r && r.message) {
|
|
||||||
const pos_profiles = r.message.filter(a => a);
|
|
||||||
|
|
||||||
if (pos_profiles.length === 0) {
|
|
||||||
load_default();
|
|
||||||
} else if(pos_profiles.length === 1) {
|
|
||||||
// load profile directly
|
|
||||||
on_submit({pos_profile: pos_profiles[0]});
|
|
||||||
} else {
|
|
||||||
// ask prompt
|
|
||||||
frappe.prompt(
|
|
||||||
[{ fieldtype: 'Select', label: 'POS Profile', options: pos_profiles }],
|
|
||||||
on_submit,
|
|
||||||
__('Select POS Profile')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
frappe.dom.unfreeze();
|
|
||||||
frappe.throw(__("POS Profile is required to use Point-of-Sale"));
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
if (set_as_default) {
|
||||||
|
frappe.call({
|
||||||
|
method: "erpnext.accounts.doctype.pos_profile.pos_profile.set_default_profile",
|
||||||
|
args: {
|
||||||
|
'pos_profile': pos_profile,
|
||||||
|
'company': this.frm.doc.company
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
this.on_change_pos_profile();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.on_change_pos_profile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
frappe.prompt(this.get_promopt_fields(),
|
||||||
|
on_submit,
|
||||||
|
__('Select POS Profile')
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get_pos_profile_doc(pos_profile_name) {
|
on_change_pos_profile() {
|
||||||
return new Promise(resolve => {
|
this.set_pos_profile_data()
|
||||||
frappe.call({
|
.then(() => {
|
||||||
method: 'erpnext.accounts.doctype.pos_profile.pos_profile.get_pos_profile',
|
this.reset_cart();
|
||||||
args: {
|
if (this.items) {
|
||||||
pos_profile_name
|
this.items.reset_items();
|
||||||
},
|
|
||||||
callback: (r) => {
|
|
||||||
resolve(r.message);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
get_promopt_fields() {
|
||||||
|
return [{
|
||||||
|
fieldtype: 'Link',
|
||||||
|
label: __('POS Profile'),
|
||||||
|
options: 'POS Profile',
|
||||||
|
get_query: () => {
|
||||||
|
return {
|
||||||
|
query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query',
|
||||||
|
filters: {
|
||||||
|
company: this.frm.doc.company
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
fieldtype: 'Check',
|
||||||
|
label: __('Set as default')
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_company() {
|
setup_company() {
|
||||||
@@ -378,9 +371,7 @@ erpnext.pos.PointOfSale = class PointOfSale {
|
|||||||
.then(() => this.set_pos_profile_data())
|
.then(() => this.set_pos_profile_data())
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (this.cart) {
|
if (this.cart) {
|
||||||
this.cart.frm = this.frm;
|
this.reset_cart();
|
||||||
this.cart.reset();
|
|
||||||
this.items.reset_search_field();
|
|
||||||
} else {
|
} else {
|
||||||
this.make_items();
|
this.make_items();
|
||||||
this.make_cart();
|
this.make_cart();
|
||||||
@@ -391,29 +382,32 @@ erpnext.pos.PointOfSale = class PointOfSale {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset_cart() {
|
||||||
|
this.cart.frm = this.frm;
|
||||||
|
this.cart.reset();
|
||||||
|
this.items.reset_search_field();
|
||||||
|
}
|
||||||
|
|
||||||
make_sales_invoice_frm() {
|
make_sales_invoice_frm() {
|
||||||
const doctype = 'Sales Invoice';
|
const doctype = 'Sales Invoice';
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
if (this.frm) {
|
if (this.frm) {
|
||||||
this.frm = get_frm(this.pos_profile, this.frm);
|
this.frm = get_frm(this.frm);
|
||||||
resolve();
|
resolve();
|
||||||
} else {
|
} else {
|
||||||
frappe.model.with_doctype(doctype, () => {
|
frappe.model.with_doctype(doctype, () => {
|
||||||
this.frm = get_frm(this.pos_profile);
|
this.frm = get_frm();
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function get_frm(pos_profile, _frm) {
|
function get_frm(_frm) {
|
||||||
const page = $('<div>');
|
const page = $('<div>');
|
||||||
const frm = _frm || new _f.Frm(doctype, page, false);
|
const frm = _frm || new _f.Frm(doctype, page, false);
|
||||||
const name = frappe.model.make_new_doc_and_get_name(doctype, true);
|
const name = frappe.model.make_new_doc_and_get_name(doctype, true);
|
||||||
frm.refresh(name);
|
frm.refresh(name);
|
||||||
frm.doc.items = [];
|
frm.doc.items = [];
|
||||||
if(!frm.doc.company) {
|
|
||||||
frm.set_value('company', pos_profile.company);
|
|
||||||
}
|
|
||||||
frm.doc.is_pos = 1;
|
frm.doc.is_pos = 1;
|
||||||
return frm;
|
return frm;
|
||||||
}
|
}
|
||||||
@@ -426,6 +420,10 @@ erpnext.pos.PointOfSale = class PointOfSale {
|
|||||||
method: "set_missing_values",
|
method: "set_missing_values",
|
||||||
}).then((r) => {
|
}).then((r) => {
|
||||||
if(!r.exc) {
|
if(!r.exc) {
|
||||||
|
if (!this.frm.doc.pos_profile) {
|
||||||
|
frappe.dom.unfreeze();
|
||||||
|
frappe.throw(__("POS Profile is required to use Point-of-Sale"));
|
||||||
|
}
|
||||||
this.frm.script_manager.trigger("update_stock");
|
this.frm.script_manager.trigger("update_stock");
|
||||||
frappe.model.set_default_values(this.frm.doc);
|
frappe.model.set_default_values(this.frm.doc);
|
||||||
this.frm.cscript.calculate_taxes_and_totals();
|
this.frm.cscript.calculate_taxes_and_totals();
|
||||||
@@ -433,8 +431,8 @@ erpnext.pos.PointOfSale = class PointOfSale {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare_menu() {
|
prepare_menu() {
|
||||||
@@ -458,6 +456,10 @@ erpnext.pos.PointOfSale = class PointOfSale {
|
|||||||
this.page.add_menu_item(__('POS Settings'), function() {
|
this.page.add_menu_item(__('POS Settings'), function() {
|
||||||
frappe.set_route('Form', 'POS Settings');
|
frappe.set_route('Form', 'POS Settings');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.page.add_menu_item(__('Change POS Profile'), function() {
|
||||||
|
me.change_pos_profile();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
set_form_action() {
|
set_form_action() {
|
||||||
@@ -478,12 +480,11 @@ erpnext.pos.PointOfSale = class PointOfSale {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class POSCart {
|
class POSCart {
|
||||||
constructor({frm, wrapper, pos_profile, events}) {
|
constructor({frm, wrapper, events}) {
|
||||||
this.frm = frm;
|
this.frm = frm;
|
||||||
this.item_data = {};
|
this.item_data = {};
|
||||||
this.wrapper = wrapper;
|
this.wrapper = wrapper;
|
||||||
this.events = events;
|
this.events = events;
|
||||||
this.pos_profile = pos_profile;
|
|
||||||
this.make();
|
this.make();
|
||||||
this.bind_events();
|
this.bind_events();
|
||||||
}
|
}
|
||||||
@@ -549,7 +550,7 @@ class POSCart {
|
|||||||
this.wrapper.find('.grand-total-value').text(
|
this.wrapper.find('.grand-total-value').text(
|
||||||
format_currency(this.frm.doc.grand_total, this.frm.currency));
|
format_currency(this.frm.doc.grand_total, this.frm.currency));
|
||||||
|
|
||||||
const customer = this.frm.doc.customer || this.pos_profile.customer;
|
const customer = this.frm.doc.customer;
|
||||||
this.customer_field.set_value(customer);
|
this.customer_field.set_value(customer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,7 +638,6 @@ class POSCart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
make_customer_field() {
|
make_customer_field() {
|
||||||
let customer = this.frm.doc.customer || this.pos_profile['customer'];
|
|
||||||
this.customer_field = frappe.ui.form.make_control({
|
this.customer_field = frappe.ui.form.make_control({
|
||||||
df: {
|
df: {
|
||||||
fieldtype: 'Link',
|
fieldtype: 'Link',
|
||||||
@@ -653,9 +653,7 @@ class POSCart {
|
|||||||
render_input: true
|
render_input: true
|
||||||
});
|
});
|
||||||
|
|
||||||
if (customer) {
|
this.customer_field.set_value(this.frm.doc.customer);
|
||||||
this.customer_field.set_value(customer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
make_numpad() {
|
make_numpad() {
|
||||||
@@ -920,19 +918,22 @@ class POSCart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class POSItems {
|
class POSItems {
|
||||||
constructor({wrapper, pos_profile, events}) {
|
constructor({wrapper, frm, events}) {
|
||||||
this.wrapper = wrapper;
|
this.wrapper = wrapper;
|
||||||
this.pos_profile = pos_profile;
|
this.frm = frm;
|
||||||
this.items = {};
|
this.items = {};
|
||||||
this.events = events;
|
this.events = events;
|
||||||
this.currency = this.pos_profile.currency;
|
this.currency = this.frm.doc.currency;
|
||||||
|
|
||||||
this.make_dom();
|
this.make_dom();
|
||||||
this.make_fields();
|
this.make_fields();
|
||||||
|
|
||||||
this.init_clusterize();
|
this.init_clusterize();
|
||||||
this.bind_events();
|
this.bind_events();
|
||||||
|
this.load_items_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
load_items_data() {
|
||||||
// bootstrap with 20 items
|
// bootstrap with 20 items
|
||||||
this.get_items()
|
this.get_items()
|
||||||
.then(({ items }) => {
|
.then(({ items }) => {
|
||||||
@@ -942,6 +943,12 @@ class POSItems {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset_items() {
|
||||||
|
this.wrapper.find('.pos-items').empty();
|
||||||
|
this.init_clusterize();
|
||||||
|
this.load_items_data();
|
||||||
|
}
|
||||||
|
|
||||||
make_dom() {
|
make_dom() {
|
||||||
this.wrapper.html(`
|
this.wrapper.html(`
|
||||||
<div class="fields">
|
<div class="fields">
|
||||||
@@ -1165,7 +1172,7 @@ class POSItems {
|
|||||||
args: {
|
args: {
|
||||||
start,
|
start,
|
||||||
page_length,
|
page_length,
|
||||||
'price_list': this.pos_profile.selling_price_list,
|
'price_list': this.frm.doc.selling_price_list,
|
||||||
item_group,
|
item_group,
|
||||||
search_value
|
search_value
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -394,7 +394,7 @@ def get_pos_profile_item_details(company, args, pos_profile=None):
|
|||||||
res = frappe._dict()
|
res = frappe._dict()
|
||||||
|
|
||||||
if not pos_profile:
|
if not pos_profile:
|
||||||
pos_profile = get_pos_profile(company)
|
pos_profile = get_pos_profile(company, args.get('pos_profile'))
|
||||||
|
|
||||||
if pos_profile:
|
if pos_profile:
|
||||||
for fieldname in ("income_account", "cost_center", "warehouse", "expense_account"):
|
for fieldname in ("income_account", "cost_center", "warehouse", "expense_account"):
|
||||||
@@ -408,17 +408,32 @@ def get_pos_profile_item_details(company, args, pos_profile=None):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_pos_profile(company):
|
def get_pos_profile(company, pos_profile=None, user=None):
|
||||||
pos_profile = frappe.db.sql("""select * from `tabPOS Profile` where user = %s
|
if pos_profile:
|
||||||
and company = %s and ifnull(disabled,0) != 1""", (frappe.session['user'], company), as_dict=1)
|
return frappe.get_doc('POS Profile', pos_profile)
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
user = frappe.session['user']
|
||||||
|
|
||||||
|
pos_profile = frappe.db.sql("""select pf.*
|
||||||
|
from
|
||||||
|
`tabPOS Profile` pf, `tabPOS Profile User` pfu
|
||||||
|
where
|
||||||
|
pfu.parent = pf.name and pfu.user = %s and pf.company = %s
|
||||||
|
and pf.disabled = 0 and pfu.default=1""", (user, company), as_dict=1)
|
||||||
|
|
||||||
if not pos_profile:
|
if not pos_profile:
|
||||||
pos_profile = frappe.db.sql("""select * from `tabPOS Profile`
|
pos_profile = frappe.db.sql("""select pf.*
|
||||||
where ifnull(user,'') = '' and company = %s and ifnull(disabled,0) != 1""", company, as_dict=1)
|
from
|
||||||
|
`tabPOS Profile` pf left join `tabPOS Profile User` pfu
|
||||||
|
on
|
||||||
|
pf.name = pfu.parent
|
||||||
|
where
|
||||||
|
ifnull(pfu.user, '') = '' and pf.company = %s
|
||||||
|
and pf.disabled = 0""", (company), as_dict=1)
|
||||||
|
|
||||||
return pos_profile and pos_profile[0] or None
|
return pos_profile and pos_profile[0] or None
|
||||||
|
|
||||||
|
|
||||||
def get_serial_nos_by_fifo(args):
|
def get_serial_nos_by_fifo(args):
|
||||||
if frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo"):
|
if frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo"):
|
||||||
return "\n".join(frappe.db.sql_list("""select name from `tabSerial No`
|
return "\n".join(frappe.db.sql_list("""select name from `tabSerial No`
|
||||||
|
|||||||
Reference in New Issue
Block a user