Skip to content

Commit 063384e

Browse files
authored
Merge pull request #43 from ury-erp/security-fix
Security Fix and erpnext pos build issue fix
2 parents e44688e + 75542e1 commit 063384e

2 files changed

Lines changed: 21 additions & 205 deletions

File tree

ury/public/js/pos_extend.js

Lines changed: 0 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -1,167 +1,3 @@
1-
<<<<<<< HEAD
2-
3-
frappe.provide('erpnext.PointOfSale');
4-
frappe.pages['point-of-sale'].on_page_load = function (wrapper) {
5-
frappe.ui.make_app_page({
6-
parent: wrapper,
7-
title: __('Point of Sale'),
8-
single_column: true
9-
10-
});
11-
12-
frappe.require('point-of-sale.bundle.js', function () {
13-
14-
15-
erpnext.PointOfSale.PastOrderList = class MyPastOrder extends erpnext.PointOfSale.PastOrderList {
16-
constructor(wrapper) {
17-
super(wrapper);
18-
}
19-
20-
make_filter_section() {
21-
const me = this;
22-
this.search_field = frappe.ui.form.make_control({
23-
df: {
24-
label: ('Search'),
25-
fieldtype: 'Data',
26-
placeholder: ('Search by invoice id or customer name')
27-
},
28-
parent: this.$component.find('.search-field'),
29-
render_input: true,
30-
});
31-
32-
this.status_field = frappe.ui.form.make_control({
33-
df: {
34-
label: ('Invoice Status'),
35-
fieldtype: 'Select',
36-
options: `Draft\nTo Bill`,
37-
placeholder: ('Filter by invoice status'),
38-
onchange: function () {
39-
if (me.$component.is(':visible')) me.refresh_list();
40-
}
41-
},
42-
parent: this.$component.find('.status-field'),
43-
render_input: true,
44-
});
45-
this.search_field.toggle_label(false);
46-
this.status_field.toggle_label(false);
47-
this.status_field.set_value('Draft');
48-
}
49-
refresh_list() {
50-
frappe.dom.freeze();
51-
this.events.reset_summary();
52-
const search_term = this.search_field.get_value();
53-
const status = this.status_field.get_value();
54-
55-
this.$invoices_container.html('');
56-
57-
return frappe.call({
58-
method: "ury.ury.api.pos_extend.overrided_past_order_list",
59-
freeze: true,
60-
args: { search_term, status },
61-
callback: (response) => {
62-
frappe.dom.unfreeze();
63-
response.message.forEach(invoice => {
64-
const invoice_html = this.get_invoice_html(invoice);
65-
this.$invoices_container.append(invoice_html);
66-
});
67-
}
68-
});
69-
}
70-
71-
}
72-
73-
erpnext.PointOfSale.Controller = class MyPosController extends erpnext.PointOfSale.Controller {
74-
constructor(wrapper) {
75-
super(wrapper);
76-
}
77-
prepare_menu() {
78-
this.page.clear_menu();
79-
80-
this.page.add_menu_item(__("Toggle Recent Orders"), this.toggle_recent_order.bind(this), false, 'Ctrl+O');
81-
82-
this.page.add_menu_item(__("Cancel Order"), this.cancel_order.bind(this), false, 'Ctrl+I');
83-
84-
}
85-
cancel_order() {
86-
if (!this.$components_wrapper.is(":visible")) return;
87-
88-
if (this.frm.doc.name.startsWith("new-pos")) {
89-
frappe.show_alert({
90-
message: __("You must save document as draft to cancel."),
91-
indicator: 'red'
92-
});
93-
frappe.utils.play_sound("error");
94-
return;
95-
}
96-
if (this.frm.doc.restaurant_table) {
97-
frappe.throw({
98-
message: __("Not allowed to cancel table orders through PoS")
99-
});
100-
}
101-
else {
102-
if (this.frm.doc.invoice_printed == 1) {
103-
frappe.throw({
104-
title: __("Invoice Already Billed"),
105-
message: __("Not allowed to cancel billed orders."),
106-
indicator: 'red'
107-
});
108-
}
109-
else {
110-
let cancel_flag = false;
111-
var dialog = new frappe.ui.Dialog({
112-
title: __("Confirm Cancellation"),
113-
fields: [
114-
{
115-
fieldname: 'reason',
116-
fieldtype: 'Data',
117-
label: __('Reason'),
118-
reqd: 1
119-
}
120-
],
121-
primary_action: function () {
122-
var reason = dialog.get_value('reason');
123-
if (!cancel_flag) {
124-
cancel_flag = true;
125-
this.frm.reason = reason;
126-
this.frm.cancel_reason = reason;
127-
this.cancel(this.frm.cancel_reason);
128-
dialog.hide();
129-
}
130-
}.bind(this),
131-
primary_action_label: __('Cancel'),
132-
});
133-
dialog.show();
134-
}
135-
}
136-
137-
}
138-
cancel() {
139-
140-
frappe.call({
141-
method: 'ury.ury.doctype.ury_order.ury_order.cancel_order',
142-
args: {
143-
invoice_id: this.frm.doc.name,
144-
reason: this.frm.cancel_reason
145-
},
146-
callback: function (r) {
147-
frappe.show_alert({ message: __('Cancelled'), indicator: 'red' });
148-
setTimeout(function () {
149-
window.location.reload();
150-
}, 1000)
151-
}
152-
});
153-
}
154-
};
155-
156-
erpnext.PointOfSale.PastOrderList = class MyPastOrderList extends erpnext.PointOfSale.PastOrderList {
157-
constructor(wrapper) {
158-
super(wrapper);
159-
}
160-
get_invoice_html(invoice) {
161-
const posting_datetime = moment(invoice.posting_date + " " + invoice.posting_time).format("Do MMMM, h:mma");
162-
return (
163-
`<div class="invoice-wrapper" data-invoice-name="${escape(invoice.name)}">
164-
=======
1651
frappe.provide("erpnext.PointOfSale");
1662
frappe.pages["point-of-sale"].on_page_load = function (wrapper) {
1673
frappe.ui.make_app_page({
@@ -337,7 +173,6 @@ frappe.pages["point-of-sale"].on_page_load = function (wrapper) {
337173
return `<div class="invoice-wrapper" data-invoice-name="${escape(
338174
invoice.name
339175
)}">
340-
>>>>>>> combine
341176
<div class="invoice-name-date">
342177
<div class="invoice-name">${invoice.name}</div>
343178
<div class="invoice-date">
@@ -347,25 +182,6 @@ frappe.pages["point-of-sale"].on_page_load = function (wrapper) {
347182
${frappe.ellipsis(invoice.customer, 20)}
348183
</div>
349184
</div>
350-
<<<<<<< HEAD
351-
<div class="invoice-table" style="display:flex; text-align:center; align-items: center; font-weight: 600; font-size: 14px;">${invoice.restaurant_table ? invoice.restaurant_table : ''}</div>
352-
<div class="invoice-total-status">
353-
<div class="invoice-total">${format_currency(invoice.grand_total, invoice.currency, 0) || 0}</div>
354-
<div class="invoice-date">${posting_datetime}</div>
355-
</div>
356-
</div>
357-
<div class="seperator"></div>`
358-
);
359-
}
360-
};
361-
362-
363-
wrapper.pos = new erpnext.PointOfSale.Controller(wrapper);
364-
window.cur_pos = wrapper.pos;
365-
});
366-
};
367-
368-
=======
369185
<div class="invoice-table" style="display:flex; text-align:center; align-items: center; font-weight: 600; font-size: 14px;">${
370186
invoice.restaurant_table ? invoice.restaurant_table : ""
371187
}</div>
@@ -567,4 +383,3 @@ frappe.pages["point-of-sale"].on_page_load = function (wrapper) {
567383
window.cur_pos = wrapper.pos;
568384
});
569385
};
570-
>>>>>>> combine

ury/ury/api/pos_extend.py

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
1-
from erpnext.accounts.doctype.sales_invoice.sales_invoice import (
2-
SalesInvoice,
3-
update_multi_mode_option,
4-
)
51
import frappe
6-
from frappe.utils.nestedset import get_root_of
7-
from frappe.utils import cint
8-
from erpnext.accounts.doctype.pos_invoice.pos_invoice import (
9-
add_return_modes,
10-
get_stock_availability,
11-
)
12-
from erpnext.selling.page.point_of_sale.point_of_sale import (
13-
search_by_term,
14-
get_conditions,
15-
get_item_group_condition,
16-
)
17-
from erpnext.accounts.party import get_due_date, get_party_account
2+
from frappe import _
183

4+
def validate_search_input(search_term):
5+
"""Validate and sanitize search input"""
6+
if not search_term:
7+
return ""
8+
9+
# Length validation
10+
if len(search_term) > 100:
11+
frappe.throw(_("Search term too long (max 100 characters)"))
12+
13+
# Character whitelist (adjust based on requirements)
14+
import re
15+
if not re.match(r'^[a-zA-Z0-9\s\-_@.]+$', search_term):
16+
frappe.throw(_("Invalid characters in search term"))
17+
18+
return search_term
1919

2020
@frappe.whitelist()
2121
def overrided_past_order_list(search_term, status, limit=20):
2222
user = frappe.session.user
23-
23+
search_term = validate_search_input(search_term)
2424
if user != "Administrator":
2525
sql_query = """
2626
SELECT b.branch,a.room
@@ -53,18 +53,19 @@ def overrided_past_order_list(search_term, status, limit=20):
5353
invoices_by_customer = frappe.db.get_all(
5454
"POS Invoice",
5555
filters={
56-
"customer": ["like", "%{}%".format(search_term)],
56+
"customer": ["like", "%{}%".format(frappe.db.escape(search_term))],
5757
"status": status,
5858
},
5959
fields=fields,
6060
)
6161
invoices_by_name = frappe.db.get_all(
6262
"POS Invoice",
63-
filters={"name": ["like", "%{}%".format(search_term)], "status": status},
63+
filters={"name": ["like", "%{}%".format(frappe.db.escape(search_term))], "status": status},
6464
fields=fields,
6565
)
66+
print("invoices by customer",invoices_by_customer)
6667
invoice_list = invoices_by_customer + invoices_by_name
67-
68+
updated_list = invoice_list
6869
elif status:
6970
if user != "Administrator":
7071
if status == "To Bill":

0 commit comments

Comments
 (0)