[Enhancement] POS Redesign (#7639)
* item group, discount * POS Redesign * offline customer * removed offline records from modal view
This commit is contained in:
parent
929c3890a4
commit
c13dbd408f
@ -30,6 +30,7 @@ def get_pos_data():
|
||||
'doc': doc,
|
||||
'default_customer': pos_profile.get('customer'),
|
||||
'items': get_items_list(pos_profile),
|
||||
'item_groups': get_item_group(pos_profile),
|
||||
'customers': get_customers_list(pos_profile),
|
||||
'serial_no_data': get_serial_no_data(pos_profile, doc.company),
|
||||
'batch_no_data': get_batch_no_data(),
|
||||
@ -140,6 +141,15 @@ def get_items_list(pos_profile):
|
||||
disabled = 0 and has_variants = 0 and is_sales_item = 1 and {cond}
|
||||
""".format(cond=cond), tuple(item_groups), as_dict=1)
|
||||
|
||||
def get_item_group(pos_profile):
|
||||
if pos_profile.get('item_groups'):
|
||||
item_groups = []
|
||||
for d in pos_profile.get('item_groups'):
|
||||
item_groups.extend(get_child_nodes('Item Group', d.item_group))
|
||||
return item_groups
|
||||
else:
|
||||
return frappe.db.sql_list("""Select name from `tabItem Group` order by name""")
|
||||
|
||||
def get_customers_list(pos_profile):
|
||||
cond = "1=1"
|
||||
customer_groups = []
|
||||
@ -276,11 +286,32 @@ def validate_customer(doc):
|
||||
customer_doc = frappe.new_doc('Customer')
|
||||
customer_doc.customer_name = doc.get('customer')
|
||||
customer_doc.customer_type = 'Company'
|
||||
customer_doc.customer_group = doc.get('customer_group')
|
||||
customer_doc.territory = doc.get('territory')
|
||||
customer_doc.customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group')
|
||||
customer_doc.territory = frappe.db.get_single_value('Selling Settings', 'territory')
|
||||
customer_doc.flags.ignore_mandatory = True
|
||||
customer_doc.save(ignore_permissions = True)
|
||||
frappe.db.commit()
|
||||
doc['customer'] = customer_doc.name
|
||||
if doc.get('contact_details'):
|
||||
args = json.loads(doc.get("contact_details"))
|
||||
make_address(doc, args, customer_doc.name)
|
||||
|
||||
def make_address(doc, args, customer):
|
||||
if args.get("address_line1"):
|
||||
address = frappe.new_doc('Address')
|
||||
address.address_line1 = args.get('address_line1')
|
||||
address.address_line2 = args.get('address_line2')
|
||||
address.city = args.get('city')
|
||||
address.state = args.get('state')
|
||||
address.zip_code = args.get('zip_code')
|
||||
address.email_id = args.get('email_id')
|
||||
address.flags.ignore_mandatory = True
|
||||
address.country = frappe.db.get_value('Company', doc.get('company'), 'country')
|
||||
address.append('links',{
|
||||
'link_doctype': 'Customer',
|
||||
'link_name': customer
|
||||
})
|
||||
address.save(ignore_permissions = True)
|
||||
|
||||
def validate_item(doc):
|
||||
for item in doc.get('items'):
|
||||
|
@ -28,7 +28,7 @@
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "fa fa-user",
|
||||
"options": "icon-user",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -232,7 +232,7 @@
|
||||
"in_standard_filter": 0,
|
||||
"label": "Offline POS Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -1035,7 +1035,7 @@
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "fa fa-shopping-cart",
|
||||
"options": "icon-shopping-cart",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -1122,7 +1122,7 @@
|
||||
"label": "Packing List",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "fa fa-suitcase",
|
||||
"options": "icon-suitcase",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -1462,7 +1462,7 @@
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "fa fa-money",
|
||||
"options": "icon-money",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -1941,7 +1941,7 @@
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "fa fa-money",
|
||||
"options": "icon-money",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -2238,7 +2238,7 @@
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "fa fa-money",
|
||||
"options": "icon-money",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -2327,7 +2327,7 @@
|
||||
"label": "Payments",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "fa fa-money",
|
||||
"options": "icon-money",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -3252,7 +3252,7 @@
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "fa fa-file-text",
|
||||
"options": "icon-file-text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -3515,7 +3515,7 @@
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "fa fa-group",
|
||||
"options": "icon-group",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -3720,7 +3720,7 @@
|
||||
"label": "Recurring",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "fa fa-time",
|
||||
"options": "icon-time",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -4173,7 +4173,7 @@
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-file-text",
|
||||
"icon": "icon-file-text",
|
||||
"idx": 181,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
@ -4282,5 +4282,6 @@
|
||||
"sort_order": "DESC",
|
||||
"timeline_field": "customer",
|
||||
"title_field": "title",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -17,9 +17,9 @@ frappe.pages['pos'].refresh = function(wrapper) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
init: function (wrapper) {
|
||||
this.page_len = 20;
|
||||
this.page = wrapper.page;
|
||||
this.wrapper = $(wrapper).find('.page-content');
|
||||
this.set_indicator();
|
||||
@ -82,10 +82,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
me.create_new();
|
||||
})
|
||||
|
||||
this.page.add_menu_item(__("View Offline Records"), function(){
|
||||
me.show_unsync_invoice_list();
|
||||
});
|
||||
|
||||
this.page.add_menu_item(__("Sync Master Data"), function () {
|
||||
me.get_data_from_server(function () {
|
||||
me.load_data(false);
|
||||
@ -104,60 +100,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
});
|
||||
},
|
||||
|
||||
show_unsync_invoice_list: function(){
|
||||
var me = this;
|
||||
this.si_docs = this.get_doc_from_localstorage();
|
||||
this.list_dialog = new frappe.ui.Dialog({
|
||||
title: 'Invoice List'
|
||||
});
|
||||
|
||||
this.list_dialog.show();
|
||||
this.list_body = this.list_dialog.body;
|
||||
if(me.pos_profile_data["allow_delete"]) {
|
||||
this.list_dialog.set_primary_action(__("Delete"), function() {
|
||||
frappe.confirm(__("Delete permanently?"), function () {
|
||||
me.delete_records();
|
||||
})
|
||||
}).addClass("btn-danger");
|
||||
this.toggle_primary_action();
|
||||
}
|
||||
|
||||
if(this.si_docs.length > 0){
|
||||
me.render_offline_data();
|
||||
me.dialog_actions()
|
||||
}else{
|
||||
$(this.list_body).append(repl('<div class="media-heading">%(message)s</div>', {'message': __("All records are synced.")}))
|
||||
}
|
||||
},
|
||||
|
||||
render_offline_data: function() {
|
||||
var me = this;
|
||||
|
||||
this.removed_items = [];
|
||||
$(this.list_body).empty();
|
||||
|
||||
$(this.list_body).append('<div class="row list-row list-row-head pos-invoice-list">\
|
||||
<div class="col-xs-1"><input class="list-select-all" type="checkbox"></div>\
|
||||
<div class="col-xs-3">Customer</div>\
|
||||
<div class="col-xs-2 text-left">Status</div>\
|
||||
<div class="col-xs-3 text-right">Paid Amount</div>\
|
||||
<div class="col-xs-3 text-right">Grand Total</div>\
|
||||
</div>')
|
||||
|
||||
$.each(this.si_docs, function(index, data){
|
||||
for(key in data) {
|
||||
$(frappe.render_template("pos_invoice_list", {
|
||||
sr: index + 1,
|
||||
name: key,
|
||||
customer: data[key].customer,
|
||||
paid_amount: format_currency(data[key].paid_amount, me.frm.doc.currency),
|
||||
grand_total: format_currency(data[key].grand_total, me.frm.doc.currency),
|
||||
data: me.get_doctype_status(data[key])
|
||||
})).appendTo($(me.list_body));
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
dialog_actions: function () {
|
||||
var me = this;
|
||||
|
||||
@ -201,7 +143,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
this.set_missing_values();
|
||||
this.refresh(false);
|
||||
this.disable_input_field();
|
||||
this.list_dialog.hide();
|
||||
this.list_dialog && this.list_dialog.hide();
|
||||
}
|
||||
},
|
||||
|
||||
@ -209,17 +151,18 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
var me = this;
|
||||
this.remove_doc_from_localstorage()
|
||||
this.update_localstorage();
|
||||
this.render_offline_data();
|
||||
this.dialog_actions();
|
||||
this.toggle_primary_action();
|
||||
},
|
||||
|
||||
toggle_primary_action: function () {
|
||||
var me = this;
|
||||
if(this.frm.doc.allow_delete) {
|
||||
if (this.removed_items && this.removed_items.length > 0) {
|
||||
$(this.list_dialog.wrapper).find('.btn-danger').show();
|
||||
$(this.wrapper).find('.btn-danger').show();
|
||||
} else {
|
||||
$(this.list_dialog.wrapper).find('.btn-danger').hide();
|
||||
$(this.wrapper).find('.btn-danger').hide();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -287,6 +230,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
var me = this;
|
||||
this.meta = r.message.meta;
|
||||
this.item_data = r.message.items;
|
||||
this.item_groups = r.message.item_groups;
|
||||
this.customers = r.message.customers;
|
||||
this.serial_no_data = r.message.serial_no_data;
|
||||
this.batch_no_data = r.message.batch_no_data;
|
||||
@ -303,14 +247,14 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
|
||||
save_previous_entry: function () {
|
||||
if (this.frm.doc.docstatus < 1 && this.frm.doc.items.length > 0) {
|
||||
this.create_invoice()
|
||||
this.create_invoice();
|
||||
}
|
||||
},
|
||||
|
||||
create_new: function () {
|
||||
var me = this;
|
||||
this.frm = {}
|
||||
this.name = '';
|
||||
this.name = null;
|
||||
this.load_data(true);
|
||||
this.setup();
|
||||
},
|
||||
@ -330,12 +274,15 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
locals["DocType"][data.name] = data;
|
||||
})
|
||||
|
||||
this.print_template_data = frappe.render_template("print_template", {content: this.print_template,
|
||||
this.print_template_data = frappe.render_template("print_template", {
|
||||
content: this.print_template,
|
||||
title: "POS", base_url: frappe.urllib.get_base_url(), print_css: frappe.boot.print_css,
|
||||
print_settings: this.print_settings, header: this.letter_head.header, footer: this.letter_head.footer})
|
||||
print_settings: this.print_settings, header: this.letter_head.header, footer: this.letter_head.footer
|
||||
})
|
||||
},
|
||||
|
||||
setup: function () {
|
||||
this.frm.doc.allow_delete = this.pos_profile_data["allow_delete"];
|
||||
this.wrapper.html(frappe.render_template("pos", this.frm.doc));
|
||||
this.set_transaction_defaults("Customer");
|
||||
this.make();
|
||||
@ -353,6 +300,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
|
||||
make: function () {
|
||||
this.make_search();
|
||||
this.make_list_customers();
|
||||
this.make_customer();
|
||||
this.make_item_list();
|
||||
this.make_discount_field()
|
||||
@ -360,25 +308,44 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
|
||||
make_search: function () {
|
||||
var me = this;
|
||||
this.search = frappe.ui.form.make_control({
|
||||
this.serach_item = frappe.ui.form.make_control({
|
||||
df: {
|
||||
"fieldtype": "Data",
|
||||
"label": "Item",
|
||||
"fieldname": "pos_item",
|
||||
"placeholder": __("Search Item")
|
||||
},
|
||||
parent: this.wrapper.find(".search-area"),
|
||||
parent: this.wrapper.find(".search-item"),
|
||||
only_input: true,
|
||||
});
|
||||
|
||||
this.search.make_input();
|
||||
this.search.$input.on("keyup", function() {
|
||||
this.serach_item.make_input();
|
||||
this.serach_item.$input.on("keyup", function () {
|
||||
setTimeout(function () {
|
||||
me.items = me.get_items();
|
||||
me.make_item_list();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
this.search_item_group = frappe.ui.form.make_control({
|
||||
df: {
|
||||
"fieldtype": "Select",
|
||||
"options": me.item_groups,
|
||||
"label": __("Item Group"),
|
||||
"fieldname": "item_group",
|
||||
"placeholder": __("Item Group")
|
||||
},
|
||||
parent: this.wrapper.find(".search-item-group"),
|
||||
only_input: true,
|
||||
});
|
||||
|
||||
this.search_item_group.make_input();
|
||||
this.search_item_group.$input.on("change", function () {
|
||||
me.page_len = 20;
|
||||
me.items = me.get_items();
|
||||
me.make_item_list();
|
||||
});
|
||||
|
||||
this.party_field = frappe.ui.form.make_control({
|
||||
df: {
|
||||
"fieldtype": "Data",
|
||||
@ -392,12 +359,129 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
});
|
||||
|
||||
this.party_field.make_input();
|
||||
this.set_focus()
|
||||
setTimeout(this.set_focus.bind(this), 500);
|
||||
|
||||
this.wrapper.find(".btn-more").on("click", function() {
|
||||
me.page_len += 20;
|
||||
me.make_item_list();
|
||||
})
|
||||
},
|
||||
|
||||
make_list_customers: function () {
|
||||
var me = this;
|
||||
this.list_customers_btn = this.wrapper.find('.list-customers-btn');
|
||||
this.add_customer_btn = this.wrapper.find('.add-customer-btn');
|
||||
this.pos_bill = this.wrapper.find('.pos-bill').hide();
|
||||
this.list_customers = this.wrapper.find('.list-customers');
|
||||
|
||||
this.list_customers_btn.on('click', function () {
|
||||
$(this).toggleClass("view_customer");
|
||||
if($(this).hasClass("view_customer")) {
|
||||
me.render_list_customers();
|
||||
me.bind_delete_event()
|
||||
me.party_field.$input.attr('disabled', true);
|
||||
me.list_customers.show();
|
||||
me.pos_bill.hide();
|
||||
} else {
|
||||
if(me.frm.doc.docstatus == 0) {
|
||||
me.party_field.$input.attr('disabled', false);
|
||||
}
|
||||
me.pos_bill.show();
|
||||
me.list_customers.hide()
|
||||
}
|
||||
});
|
||||
this.add_customer_btn.on('click', function() {
|
||||
me.save_previous_entry();
|
||||
me.create_new();
|
||||
me.refresh();
|
||||
me.set_focus();
|
||||
});
|
||||
},
|
||||
|
||||
render_list_customers: function () {
|
||||
var me = this;
|
||||
|
||||
this.removed_items = [];
|
||||
this.list_customers.empty();
|
||||
this.si_docs = this.get_doc_from_localstorage();
|
||||
|
||||
if (!this.si_docs.length) {
|
||||
this.list_customers.append(
|
||||
'<div style="padding: 12px; margin-left:-12px;">' + __("No offline records.") + '</div>'
|
||||
)
|
||||
return;
|
||||
}
|
||||
var html = '<div class="row list-row list-row-head pos-invoice-list">\
|
||||
<div class="col-xs-1"><input class="list-select-all" type="checkbox"></div>\
|
||||
<div class="col-xs-3">Customer</div>\
|
||||
<div class="col-xs-2 text-left">Status</div>\
|
||||
<div class="col-xs-3 text-right">Paid Amount</div>\
|
||||
<div class="col-xs-3 text-right">Grand Total</div>\
|
||||
</div>';
|
||||
this.si_docs.forEach(function (data, i) {
|
||||
for (key in data) {
|
||||
html += frappe.render_template("pos_invoice_list", {
|
||||
sr: i + 1,
|
||||
name: key,
|
||||
customer: data[key].customer,
|
||||
paid_amount: format_currency(data[key].paid_amount, me.frm.doc.currency),
|
||||
grand_total: format_currency(data[key].grand_total, me.frm.doc.currency),
|
||||
data: me.get_doctype_status(data[key])
|
||||
});
|
||||
}
|
||||
});
|
||||
this.list_customers.append(html);
|
||||
|
||||
this.list_customers.find('.list-column').click(function () {
|
||||
me.list_customers.hide();
|
||||
me.list_customers_btn.toggleClass("view_customer");
|
||||
me.pos_bill.show();
|
||||
me.list_customers_btn.show();
|
||||
me.name = $(this).parents().attr('invoice-name')
|
||||
me.edit_record();
|
||||
})
|
||||
|
||||
//actions
|
||||
$(this.wrapper).find('.list-select-all').click(function () {
|
||||
me.list_customers.find('.list-delete').prop("checked", $(this).is(":checked"))
|
||||
me.removed_items = [];
|
||||
if ($(this).is(":checked")) {
|
||||
$.each(me.si_docs, function (index, data) {
|
||||
for (key in data) {
|
||||
me.removed_items.push(key)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
me.toggle_primary_action();
|
||||
});
|
||||
|
||||
$(this.wrapper).find('.list-delete').click(function () {
|
||||
me.name = $(this).parent().parent().attr('invoice-name');
|
||||
if ($(this).is(":checked")) {
|
||||
me.removed_items.push(me.name);
|
||||
} else {
|
||||
me.removed_items.pop(me.name)
|
||||
}
|
||||
|
||||
me.toggle_primary_action();
|
||||
});
|
||||
},
|
||||
|
||||
bind_delete_event: function() {
|
||||
var me = this;
|
||||
|
||||
$(this.wrapper).find('.btn-danger').click(function(){
|
||||
frappe.confirm(__("Delete permanently?"), function () {
|
||||
me.delete_records();
|
||||
me.render_list_customers();
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
set_focus: function () {
|
||||
if(this.default_customer){
|
||||
this.search.$input.focus();
|
||||
if (this.default_customer || this.frm.doc.customer) {
|
||||
this.serach_item.$input.focus();
|
||||
} else {
|
||||
this.party_field.$input.focus();
|
||||
}
|
||||
@ -433,7 +517,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
.get(0);
|
||||
}
|
||||
});
|
||||
var items = this.customers.map(function(c) {
|
||||
var customers = this.customers.map(function (c) {
|
||||
return {
|
||||
label: c.name,
|
||||
value: c.name,
|
||||
@ -441,7 +525,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
territory: c.territory
|
||||
}
|
||||
});
|
||||
items.push({
|
||||
|
||||
customers.push({
|
||||
label: "<span class='text-primary link-option'>"
|
||||
+ "<i class='fa fa-plus' style='margin-right: 5px;'></i> "
|
||||
+ __("Create a new Customer")
|
||||
@ -449,22 +534,24 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
value: 'is_action',
|
||||
action: me.new_customer
|
||||
});
|
||||
this.party_field.awesomeplete.list = items;
|
||||
this.party_field.awesomeplete.list = customers;
|
||||
|
||||
this.party_field.$input
|
||||
.on('input', function (e) {
|
||||
me.party_field.awesomeplete.list = items;
|
||||
me.party_field.awesomeplete.list = customers;
|
||||
})
|
||||
.on('awesomplete-select', function (e) {
|
||||
var item = me.party_field.awesomeplete
|
||||
var customer = me.party_field.awesomeplete
|
||||
.get_item(e.originalEvent.text.value);
|
||||
if(!item) return;
|
||||
if(item.action) {
|
||||
item.action.apply(me);
|
||||
if (!customer) return;
|
||||
// create customer link
|
||||
if (customer.action) {
|
||||
customer.action.apply(me);
|
||||
return;
|
||||
}
|
||||
me.update_customer_data(item);
|
||||
me.update_customer_data(customer);
|
||||
me.refresh();
|
||||
me.set_focus();
|
||||
})
|
||||
.on('change', function (e) {
|
||||
if (!e.originalEvent.text) {
|
||||
@ -487,11 +574,84 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
new_customer: function () {
|
||||
var me = this;
|
||||
if (!this.connection_status) return;
|
||||
frappe.ui.form.quick_entry('Customer', function (doc) {
|
||||
me.customers.push(doc);
|
||||
me.party_field.$input.val(doc.name);
|
||||
me.update_customer_data(doc);
|
||||
|
||||
this.customer_doc = new frappe.ui.Dialog({
|
||||
'title': 'Customer',
|
||||
fields: [
|
||||
{
|
||||
"label": __("Full Name"),
|
||||
"fieldname": "full_name",
|
||||
"fieldtype": "Data",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"label": __("Email Id"),
|
||||
"fieldname": "email_id",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"label": __("Contact Number"),
|
||||
"fieldname": "contact_no",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"label": __("Address Line 1"),
|
||||
"fieldname": "address_line1",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"label": __("Address Line 2"),
|
||||
"fieldname": "address_line2",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"label": __("City"),
|
||||
"fieldname": "city",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"label": __("State"),
|
||||
"fieldname": "state",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"label": __("ZIP Code"),
|
||||
"fieldname": "zip_code",
|
||||
"fieldtype": "Data"
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
this.customer_doc.show()
|
||||
|
||||
this.customer_doc.set_primary_action(__("Save"), function () {
|
||||
me.make_offline_customer();
|
||||
me.pos_bill.show();
|
||||
});
|
||||
},
|
||||
|
||||
make_offline_customer: function() {
|
||||
this.frm.doc.customer = this.customer_doc.get_values().full_name;
|
||||
this.frm.doc.contact_details = JSON.stringify(this.customer_doc.get_values());
|
||||
this.party_field.$input.val(this.frm.doc.customer);
|
||||
this.customers.push({
|
||||
name: this.frm.doc.customer,
|
||||
customer_name: this.frm.doc.customer
|
||||
});
|
||||
|
||||
this.customer_doc.hide()
|
||||
},
|
||||
|
||||
update_customer_data: function (doc) {
|
||||
@ -500,6 +660,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
this.frm.doc.customer_name = doc.customer_name;
|
||||
this.frm.doc.customer_group = doc.customer_group;
|
||||
this.frm.doc.territory = doc.territory;
|
||||
this.pos_bill.show();
|
||||
},
|
||||
|
||||
get_customers: function (key) {
|
||||
@ -536,7 +697,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
|
||||
if (this.items.length > 0) {
|
||||
$.each(this.items, function(index, obj) {
|
||||
if(index < 30){
|
||||
if(index < me.page_len){
|
||||
$(frappe.render_template("pos_item", {
|
||||
item_code: obj.name,
|
||||
item_price: format_currency(me.price_list_data[obj.name], me.frm.doc.currency),
|
||||
@ -552,13 +713,15 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
}
|
||||
|
||||
if (this.items.length == 1
|
||||
&& this.search.$input.val()) {
|
||||
this.search.$input.val("");
|
||||
&& this.serach_item.$input.val()) {
|
||||
this.serach_item.$input.val("");
|
||||
this.add_to_cart();
|
||||
}
|
||||
|
||||
// if form is local then allow this function
|
||||
$(me.wrapper).find("div.pos-item").on("click", function () {
|
||||
if(me.list_customers_btn.hasClass("view_customer")) return;
|
||||
|
||||
me.customer_validate();
|
||||
if (me.frm.doc.docstatus == 0) {
|
||||
me.items = me.get_items($(this).attr("data-item-code"))
|
||||
@ -582,25 +745,27 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
})
|
||||
}
|
||||
|
||||
key = this.search.$input.val().toLowerCase().replace(/[&\/\\#,+()\[\]$~.'":*?<>{}]/g,'\\$&');
|
||||
this.items_list = this.apply_category();
|
||||
|
||||
key = this.serach_item.$input.val().toLowerCase().replace(/[&\/\\#,+()\[\]$~.'":*?<>{}]/g, '\\$&');
|
||||
var re = new RegExp('%', 'g');
|
||||
var reg = new RegExp(key.replace(re, '[\\w*\\s*[a-zA-Z0-9]*]*'))
|
||||
search_status = true
|
||||
|
||||
if (key) {
|
||||
return $.grep(this.item_data, function(item){
|
||||
return $.grep(this.items_list, function (item) {
|
||||
if (search_status) {
|
||||
if(in_list(me.batch_no_data[item.item_code], me.search.$input.val())){
|
||||
if (in_list(me.batch_no_data[item.item_code], me.serach_item.$input.val())) {
|
||||
search_status = false;
|
||||
return me.item_batch_no[item.item_code] = me.search.$input.val()
|
||||
return me.item_batch_no[item.item_code] = me.serach_item.$input.val()
|
||||
} else if (me.serial_no_data[item.item_code]
|
||||
&& in_list(Object.keys(me.serial_no_data[item.item_code]), me.search.$input.val())) {
|
||||
&& in_list(Object.keys(me.serial_no_data[item.item_code]), me.serach_item.$input.val())) {
|
||||
search_status = false;
|
||||
me.item_serial_no[item.item_code] = [me.search.$input.val(), me.serial_no_data[item.item_code][me.search.$input.val()]]
|
||||
me.item_serial_no[item.item_code] = [me.serach_item.$input.val(), me.serial_no_data[item.item_code][me.serach_item.$input.val()]]
|
||||
return true
|
||||
} else if(item.barcode == me.search.$input.val()) {
|
||||
} else if (item.barcode == me.serach_item.$input.val()) {
|
||||
search_status = false;
|
||||
return item.barcode == me.search.$input.val();
|
||||
return item.barcode == me.serach_item.$input.val();
|
||||
} else if (reg.test(item.item_code.toLowerCase()) || reg.test(item.description.toLowerCase()) ||
|
||||
reg.test(item.item_name.toLowerCase()) || reg.test(item.item_group.toLowerCase())) {
|
||||
return true
|
||||
@ -608,7 +773,20 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return this.item_data;
|
||||
return this.items_list;
|
||||
}
|
||||
},
|
||||
|
||||
apply_category: function() {
|
||||
var me = this;
|
||||
category = this.search_item_group.$input.val();
|
||||
|
||||
if(category == 'All Item Groups') {
|
||||
return this.item_data
|
||||
} else {
|
||||
return this.item_data.filter(function(element, index, array){
|
||||
return element.item_group == category;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@ -632,13 +810,25 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) - 1;
|
||||
me.update_qty(item_code, qty)
|
||||
})
|
||||
|
||||
$(this.wrapper).find(".pos-item-discount").on("change", function () {
|
||||
var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
|
||||
var discount = $(this).val();
|
||||
me.update_discount(item_code, discount)
|
||||
})
|
||||
},
|
||||
|
||||
update_qty: function (item_code, qty) {
|
||||
var me = this;
|
||||
this.items = this.get_items(item_code);
|
||||
this.validate_serial_no()
|
||||
this.update_qty_rate_against_item_code(item_code, "qty", qty);
|
||||
this.set_item_details(item_code, "qty", qty);
|
||||
},
|
||||
|
||||
update_discount: function(item_code, discount) {
|
||||
var me = this;
|
||||
this.items = this.get_items(item_code);
|
||||
this.set_item_details(item_code, "discount_percentage", discount);
|
||||
},
|
||||
|
||||
update_rate: function () {
|
||||
@ -646,11 +836,11 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
|
||||
$(this.wrapper).find(".pos-item-rate").on("change", function () {
|
||||
var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
|
||||
me.update_qty_rate_against_item_code(item_code, "rate", $(this).val());
|
||||
me.set_item_details(item_code, "rate", $(this).val());
|
||||
})
|
||||
},
|
||||
|
||||
update_qty_rate_against_item_code: function(item_code, field, value){
|
||||
set_item_details: function (item_code, field, value) {
|
||||
var me = this;
|
||||
if (value < 0) {
|
||||
frappe.throw(__("Enter value must be positive"));
|
||||
@ -658,11 +848,11 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
|
||||
this.remove_item = []
|
||||
$.each(this.frm.doc["items"] || [], function (i, d) {
|
||||
if (d.item_code == item_code) {
|
||||
if (d.serial_no && field == 'qty') {
|
||||
me.validate_serial_no_qty(d, item_code, field, value)
|
||||
}
|
||||
|
||||
if (d.item_code == item_code) {
|
||||
d[field] = flt(value);
|
||||
d.amount = flt(d.rate) * flt(d.qty);
|
||||
if (d.qty == 0) {
|
||||
@ -826,7 +1016,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
item_code: d.item_code,
|
||||
item_name: (d.item_name === d.item_code || !d.item_name) ? "" : ("<br>" + d.item_name),
|
||||
qty: d.qty,
|
||||
actual_qty: me.actual_qty_dict[d.item_code] || 0,
|
||||
discount_percentage: d.discount_percentage || 0.0,
|
||||
actual_qty: me.actual_qty_dict[d.item_code] || 0.0,
|
||||
projected_qty: d.projected_qty,
|
||||
rate: format_number(d.rate, me.frm.doc.currency),
|
||||
enabled: me.pos_profile_data["allow_user_to_edit_rate"] ? true : false,
|
||||
@ -838,6 +1029,10 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
$(this).select();
|
||||
});
|
||||
|
||||
this.wrapper.find("input.pos-item-discount").on("focus", function () {
|
||||
$(this).select();
|
||||
});
|
||||
|
||||
this.wrapper.find("input.pos-item-rate").on("focus", function () {
|
||||
$(this).select();
|
||||
});
|
||||
@ -878,7 +1073,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
me.update_paid_amount_status(true);
|
||||
me.create_invoice();
|
||||
me.make_payment();
|
||||
}, "octicon octfa fa-credit-card");
|
||||
}, "fa fa-credit-card");
|
||||
} else if (this.frm.doc.docstatus == 1) {
|
||||
this.page.set_primary_action(__("Print"), function () {
|
||||
html = frappe.render(me.print_template_data, me.frm.doc)
|
||||
@ -888,10 +1083,10 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
this.page.clear_primary_action()
|
||||
}
|
||||
|
||||
this.page.set_secondary_action(__("New"), function() {
|
||||
me.save_previous_entry();
|
||||
me.create_new();
|
||||
}, "octicon octfa fa-plus").addClass("btn-primary");
|
||||
// this.page.set_secondary_action(__("New"), function () {
|
||||
// me.save_previous_entry();
|
||||
// me.create_new();
|
||||
// }, "fa fa-plus").addClass("btn-primary");
|
||||
},
|
||||
|
||||
print_dialog: function () {
|
||||
@ -943,13 +1138,15 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
disable_input_field: function () {
|
||||
var pointer_events = 'inherit'
|
||||
$(this.wrapper).find('input').attr("disabled", false);
|
||||
$(this.wrapper).find('select').attr("disabled", false);
|
||||
|
||||
if (this.frm.doc.docstatus == 1) {
|
||||
pointer_events = 'none';
|
||||
$(this.wrapper).find('input').attr("disabled", true);
|
||||
$(this.wrapper).find('select').attr("disabled", true);
|
||||
}
|
||||
|
||||
$(this.wrapper).find('.pos-bill-wrapper').css('pointer-events', pointer_events);
|
||||
$(this.wrapper).find('.pos-bill').css('pointer-events', pointer_events);
|
||||
$(this.wrapper).find('.pos-items-section').css('pointer-events', pointer_events);
|
||||
this.set_primary_action();
|
||||
},
|
||||
@ -970,6 +1167,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
this.update_localstorage();
|
||||
this.set_primary_action();
|
||||
}
|
||||
return invoice_data;
|
||||
},
|
||||
|
||||
update_invoice: function () {
|
||||
@ -1145,16 +1343,18 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
pricing_rule = me.get_pricing_rule(item)
|
||||
me.validate_pricing_rule(pricing_rule)
|
||||
if (pricing_rule.length) {
|
||||
item.pricing_rule = pricing_rule[0].name;
|
||||
item.margin_type = pricing_rule[0].margin_type;
|
||||
item.price_list_rate = pricing_rule[0].price || item.price_list_rate;
|
||||
item.margin_rate_or_amount = pricing_rule[0].margin_rate_or_amount;
|
||||
item.discount_percentage = pricing_rule[0].discount_percentage || 0.0;
|
||||
me.apply_pricing_rule_on_item(item)
|
||||
} else if(item.discount_percentage > 0 || item.margin_rate_or_amount > 0) {
|
||||
} else if ((item.discount_percentage > 0 || item.margin_rate_or_amount > 0) && item.pricing_rule) {
|
||||
item.margin_rate_or_amount = 0.0;
|
||||
item.discount_percentage = 0.0;
|
||||
me.apply_pricing_rule_on_item(item)
|
||||
item.pricing_rule = null;
|
||||
}
|
||||
|
||||
me.apply_pricing_rule_on_item(item)
|
||||
})
|
||||
},
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 95 KiB |
Binary file not shown.
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 63 KiB |
Binary file not shown.
Before Width: | Height: | Size: 226 KiB After Width: | Height: | Size: 99 KiB |
@ -67,7 +67,6 @@
|
||||
.pos-toolbar,
|
||||
.pos-bill-toolbar {
|
||||
padding: 10px 0px;
|
||||
border-bottom: 1px solid #d1d8dd;
|
||||
height: 51px;
|
||||
}
|
||||
.pos-item-toolbar .form-group {
|
||||
@ -79,6 +78,7 @@
|
||||
margin-right: -1px;
|
||||
}
|
||||
.pos-bill {
|
||||
border-top: 1px solid #d1d8dd;
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
}
|
||||
@ -171,6 +171,9 @@
|
||||
.payment-toolbar {
|
||||
padding-right: 30px;
|
||||
}
|
||||
.list-row-head.pos-invoice-list {
|
||||
border-top: 1px solid #d1d8dd;
|
||||
}
|
||||
body[data-route="pos"] .modal-dialog {
|
||||
width: 750px;
|
||||
}
|
||||
|
@ -1,14 +1,26 @@
|
||||
<div class="pos">
|
||||
<div class="row">
|
||||
<div class="col-sm-5 pos-bill-wrapper">
|
||||
<div class="pos-bill-toolbar row">
|
||||
<div class="party-area col-xs-12"></div>
|
||||
<div class="col-sm-6 pos-bill-wrapper">
|
||||
<div class="pos-bill-toolbar" style="display: flex;">
|
||||
<div class="party-area" style="flex: 1;"></div>
|
||||
<button class="btn btn-default list-customers-btn" style="margin: 0 5px 0 15px;">
|
||||
<i class="fa fa-list"></i>
|
||||
</button>
|
||||
<button class="btn btn-default add-customer-btn">
|
||||
<i class="fa fa-plus"></i>
|
||||
</button>
|
||||
{% if (allow_delete) { %}
|
||||
<button class="btn btn-default btn-danger" style="margin: 0 5px 0 5px;display:none">
|
||||
<i class="octicon octicon-trashcan"></i>
|
||||
</button>
|
||||
{% } %}
|
||||
</div>
|
||||
<div class="pos-bill">
|
||||
<div class="item-cart">
|
||||
<div class="row pos-bill-row pos-bill-header">
|
||||
<div class="col-xs-5"><h6>{%= __("Item") %}</h6></div>
|
||||
<div class="col-xs-4"><h6 class="text-right">{%= __("Quantity") %}</h6></div>
|
||||
<div class="col-xs-4"><h6>{%= __("Item") %}</h6></div>
|
||||
<div class="col-xs-3"><h6 class="text-right">{%= __("Quantity") %}</h6></div>
|
||||
<div class="col-xs-2"><h6 class="text-right">{%= __("Discount") %}</h6></div>
|
||||
<div class="col-xs-3"><h6 class="text-right">{%= __("Rate") %}</h6></div>
|
||||
</div>
|
||||
<div class="items"></div>
|
||||
@ -48,18 +60,27 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-customers">
|
||||
|
||||
</div>
|
||||
<div class="col-sm-7 pos-items-section">
|
||||
</div>
|
||||
<div class="col-sm-6 pos-items-section">
|
||||
<div class="row pos-item-area">
|
||||
|
||||
</div>
|
||||
<span id="customer-results" style="color:#68a;"></span>
|
||||
<div class="row pos-item-toolbar">
|
||||
<div class="search-area col-xs-12"></div>
|
||||
<div class="search-item-group col-xs-5"></div>
|
||||
<div class="search-item col-xs-7"></div>
|
||||
</div>
|
||||
<div class="item-list-area">
|
||||
<div class="item-list-area" style="auto">
|
||||
<div class="app-listing item-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="text-right list-paging-area">
|
||||
<button class="btn btn-default btn-more btn-sm" style="margin:5px 20px">{{ __("More") }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,25 +1,30 @@
|
||||
<div class="row pos-bill-row pos-bill-item" data-item-code="{%= item_code %}">
|
||||
<div class="col-xs-5"><h6>{%= item_code || "" %}{%= item_name || "" %}</h6></div>
|
||||
<div class="col-xs-4">
|
||||
<div class="col-xs-4"><h6>{%= item_code || "" %}{%= __(item_name) || "" %}</h6></div>
|
||||
<div class="col-xs-3">
|
||||
<div class="row pos-qty-row">
|
||||
<div class="col-xs-2 text-center pos-qty-btn" data-action="decrease-qty"><i class="fa fa-minus text-muted" style="font-size:12px"></i></div>
|
||||
<div class="col-xs-8">
|
||||
<div>
|
||||
<input type="text" value="{%= qty %}" class="form-control input-sm pos-item-qty text-right">
|
||||
<input type="tel" value="{%= qty %}" class="form-control pos-item-qty text-right">
|
||||
</div>
|
||||
{% if(actual_qty != null) { %}
|
||||
<div style="margin-top: 5px;" class="text-muted small text-right">
|
||||
<span title="{%= __("In Stock") %}">{%= actual_qty || 0 %}<span>
|
||||
{%= __("In Stock: ") %} <span>{%= actual_qty || 0.0 %}</span>
|
||||
</div>
|
||||
{% } %}
|
||||
</div>
|
||||
<div class="col-xs-2 text-center pos-qty-btn" data-action="increase-qty"><i class="fa fa-plus text-muted" style="font-size:12px"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-2 text-right">
|
||||
<div class="row input-sm">
|
||||
<input type="tel" value="{%= discount_percentage %}" class="form-control text-right pos-item-discount">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-3 text-right">
|
||||
<div class="text-muted" style="margin-top: 5px;">
|
||||
{% if(enabled) { %}
|
||||
<input type="text" value="{%= rate %}" class="form-control input-sm pos-item-rate text-right">
|
||||
<input type="tel" value="{%= rate %}" class="form-control input-sm pos-item-rate text-right">
|
||||
{% } else { %}
|
||||
<h6>{%= format_currency(rate) %}</h6>
|
||||
{% } %}
|
||||
|
@ -82,7 +82,7 @@
|
||||
|
||||
.pos-toolbar, .pos-bill-toolbar {
|
||||
padding: 10px 0px;
|
||||
border-bottom: 1px solid #d1d8dd;
|
||||
// border-bottom: 1px solid #d1d8dd;
|
||||
height: 51px;
|
||||
}
|
||||
|
||||
@ -97,6 +97,7 @@
|
||||
}
|
||||
|
||||
.pos-bill {
|
||||
border-top: 1px solid @border-color;
|
||||
margin-left: -15px;
|
||||
margin-right: -15px;
|
||||
}
|
||||
@ -213,6 +214,10 @@
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
.list-row-head.pos-invoice-list {
|
||||
border-top: 1px solid @border-color;
|
||||
}
|
||||
|
||||
body[data-route="pos"] .modal-dialog {
|
||||
width: 750px;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user