Merge branch 'rebrand-ui' of https://github.com/frappe/erpnext into rebrand-ui
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
index d51856a..0e1d140 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
@@ -64,11 +64,11 @@
prepare_invoice_summary(doctype, invoices)
return invoices_summary, max_count
-
+
def validate_company(self):
if not self.company:
frappe.throw(_("Please select the Company"))
-
+
def set_missing_values(self, row):
row.qty = row.qty or 1.0
row.temporary_opening_account = row.temporary_opening_account or get_temporary_opening_account(self.company)
@@ -209,7 +209,7 @@
frappe.db.commit()
if errors:
frappe.msgprint(_("You had {} errors while creating opening invoices. Check {} for more details")
- .format(errors, "<a href='#List/Error Log' class='variant-click'>Error Log</a>"), indicator="red", title=_("Error Occured"))
+ .format(errors, "<a href='/app/List/Error Log' class='variant-click'>Error Log</a>"), indicator="red", title=_("Error Occured"))
return names
def publish(index, total, doctype):
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 30abc66..1793dad 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -471,7 +471,7 @@
asset_bought_with_invoice = (purchase_document == self.purchase_invoice)
fixed_asset_account = self.get_fixed_asset_account()
-
+
cwip_enabled = is_cwip_accounting_enabled(self.asset_category)
cwip_account = self.get_cwip_account(cwip_enabled=cwip_enabled)
@@ -503,10 +503,10 @@
purchase_document = self.purchase_invoice if asset_bought_with_invoice else self.purchase_receipt
return purchase_document
-
+
def get_fixed_asset_account(self):
return get_asset_category_account('fixed_asset_account', None, self.name, None, self.asset_category, self.company)
-
+
def get_cwip_account(self, cwip_enabled=False):
cwip_account = None
try:
@@ -659,7 +659,7 @@
frappe.db.commit()
- frappe.msgprint(_("Asset Movement record {0} created").format("<a href='#Form/Asset Movement/{0}'>{0}</a>").format(movement_entry.name))
+ frappe.msgprint(_("Asset Movement record {0} created").format("<a href='/app/Form/Asset Movement/{0}'>{0}</a>").format(movement_entry.name))
@frappe.whitelist()
def get_item_details(item_code, asset_category):
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
index ae5611f..6a4c02c 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
@@ -71,7 +71,7 @@
doc_sup = doc_sup[0] if doc_sup else None
if not doc_sup:
frappe.throw(_("Supplier {0} not found in {1}").format(self.supplier,
- "<a href='desk#Form/Request for Quotation/{0}'> Request for Quotation {0} </a>".format(doc.name)))
+ "<a href='desk/app/Form/Request for Quotation/{0}'> Request for Quotation {0} </a>".format(doc.name)))
quote_status = _('Received')
for item in doc.items:
diff --git a/erpnext/config/education.py b/erpnext/config/education.py
index 4efaaa6..1c8ab10 100644
--- a/erpnext/config/education.py
+++ b/erpnext/config/education.py
@@ -173,7 +173,7 @@
{
"type": "doctype",
"name": "Course Schedule",
- "route": "#List/Course Schedule/Calendar"
+ "route": "/app/List/Course Schedule/Calendar"
},
{
"type": "doctype",
diff --git a/erpnext/config/projects.py b/erpnext/config/projects.py
index 47700d1..ab4db96 100644
--- a/erpnext/config/projects.py
+++ b/erpnext/config/projects.py
@@ -16,13 +16,13 @@
{
"type": "doctype",
"name": "Task",
- "route": "#List/Task",
+ "route": "/app/List/Task",
"description": _("Project activity / task."),
"onboard": 1,
},
{
"type": "report",
- "route": "#List/Task/Gantt",
+ "route": "/app/List/Task/Gantt",
"doctype": "Task",
"name": "Gantt Chart",
"description": _("Gantt chart of all tasks."),
@@ -97,5 +97,5 @@
},
]
},
-
+
]
diff --git a/erpnext/education/doctype/assessment_result_tool/assessment_result_tool.js b/erpnext/education/doctype/assessment_result_tool/assessment_result_tool.js
index 3cd4512..e213309 100644
--- a/erpnext/education/doctype/assessment_result_tool/assessment_result_tool.js
+++ b/erpnext/education/doctype/assessment_result_tool/assessment_result_tool.js
@@ -128,7 +128,7 @@
result_table.find(`span[data-student=${assessment_result.student}].total-score-grade`).html(assessment_result.grade);
let link_span = result_table.find(`span[data-student=${assessment_result.student}].total-result-link`);
$(link_span).css("display", "block");
- $(link_span).find("a").attr("href", "#Form/Assessment Result/"+assessment_result.name);
+ $(link_span).find("a").attr("href", "/desk/Form/Assessment Result/"+assessment_result.name);
}
});
}
diff --git a/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.js b/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.js
index 20503f9..f408dae 100644
--- a/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.js
+++ b/erpnext/education/doctype/course_scheduling_tool/course_scheduling_tool.js
@@ -25,7 +25,7 @@
<thead><tr><th>${__("Course")}</th><th>${__("Date")}</th></tr></thead>
<tbody>
${course_schedules.map(
- c => `<tr><td><a href="#Form/Course Schedule/${c.name}">${c.name}</a></td>
+ c => `<tr><td><a href="/desk/Form/Course Schedule/${c.name}">${c.name}</a></td>
<td>${c.schedule_date}</td></tr>`
).join('')}
</tbody>
diff --git a/erpnext/education/doctype/program_enrollment/program_enrollment.py b/erpnext/education/doctype/program_enrollment/program_enrollment.py
index 6fbcd8a..3045db7 100644
--- a/erpnext/education/doctype/program_enrollment/program_enrollment.py
+++ b/erpnext/education/doctype/program_enrollment/program_enrollment.py
@@ -87,7 +87,7 @@
fees.submit()
fee_list.append(fees.name)
if fee_list:
- fee_list = ["""<a href="#Form/Fees/%s" target="_blank">%s</a>""" % \
+ fee_list = ["""<a href="/app/Form/Fees/%s" target="_blank">%s</a>""" % \
(fee, fee) for fee in fee_list]
msgprint(_("Fee Records Created - {0}").format(comma_and(fee_list)))
diff --git a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.js b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.js
index fd16d1e..e864111 100644
--- a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.js
+++ b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.js
@@ -23,10 +23,10 @@
frappe.msgprint({
message: __("An error has occurred during {0}. Check {1} for more details",
[
- repl("<a href='#Form/Tally Migration/%(tally_document)s' class='variant-click'>%(tally_document)s</a>", {
+ repl("<a href='/desk/Form/Tally Migration/%(tally_document)s' class='variant-click'>%(tally_document)s</a>", {
tally_document: frm.docname
}),
- "<a href='#List/Error Log' class='variant-click'>Error Log</a>"
+ "<a href='/desk/List/Error Log' class='variant-click'>Error Log</a>"
]
),
title: __("Tally Migration Error"),
diff --git a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
index eb7d4bd..19bddbb 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
+++ b/erpnext/healthcare/doctype/clinical_procedure/clinical_procedure.js
@@ -86,7 +86,7 @@
if (r.message) {
frappe.show_alert({
message: __('Stock Entry {0} created',
- ['<a class="bold" href="#Form/Stock Entry/'+ r.message + '">' + r.message + '</a>']),
+ ['<a class="bold" href="/desk/Form/Stock Entry/'+ r.message + '">' + r.message + '</a>']),
indicator: 'green'
});
}
diff --git a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py
index bc76970..c7ab447 100644
--- a/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py
+++ b/erpnext/healthcare/doctype/inpatient_record/inpatient_record.py
@@ -50,7 +50,7 @@
if ip_record:
msg = _(("Already {0} Patient {1} with Inpatient Record ").format(ip_record[0].status, self.patient) \
- + """ <b><a href="#Form/Inpatient Record/{0}">{0}</a></b>""".format(ip_record[0].name))
+ + """ <b><a href="/app/Form/Inpatient Record/{0}">{0}</a></b>""".format(ip_record[0].name))
frappe.throw(msg)
def admit(self, service_unit, check_in, expected_discharge=None):
diff --git a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
index e685b20..90d9023 100755
--- a/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/patient_appointment.py
@@ -63,7 +63,7 @@
if overlaps:
overlapping_details = _('Appointment overlaps with ')
- overlapping_details += "<b><a href='#Form/Patient Appointment/{0}'>{0}</a></b><br>".format(overlaps[0][0])
+ overlapping_details += "<b><a href='/app/Form/Patient Appointment/{0}'>{0}</a></b><br>".format(overlaps[0][0])
overlapping_details += _('{0} has appointment scheduled with {1} at {2} having {3} minute(s) duration.').format(
overlaps[0][1], overlaps[0][2], overlaps[0][3], overlaps[0][4])
frappe.throw(overlapping_details, title=_('Appointments Overlapping'))
@@ -75,7 +75,7 @@
if frappe.db.get_single_value('Healthcare Settings', 'automate_appointment_invoicing'):
if not frappe.db.get_value('Patient', self.patient, 'customer'):
msg = _("Please set a Customer linked to the Patient")
- msg += " <b><a href='#Form/Patient/{0}'>{0}</a></b>".format(self.patient)
+ msg += " <b><a href='/app/Form/Patient/{0}'>{0}</a></b>".format(self.patient)
frappe.throw(msg, title=_('Customer Not Found'))
def update_prescription_details(self):
diff --git a/erpnext/healthcare/utils.py b/erpnext/healthcare/utils.py
index 96282f5..2486923 100644
--- a/erpnext/healthcare/utils.py
+++ b/erpnext/healthcare/utils.py
@@ -32,7 +32,7 @@
def validate_customer_created(patient):
if not frappe.db.get_value('Patient', patient.name, 'customer'):
msg = _("Please set a Customer linked to the Patient")
- msg += " <b><a href='#Form/Patient/{0}'>{0}</a></b>".format(patient.name)
+ msg += " <b><a href='/app/Form/Patient/{0}'>{0}</a></b>".format(patient.name)
frappe.throw(msg, title=_('Customer Not Found'))
@@ -169,7 +169,7 @@
service_item = get_healthcare_service_item('clinical_procedure_consumable_item')
if not service_item:
msg = _('Please Configure Clinical Procedure Consumable Item in ')
- msg += '''<b><a href='#Form/Healthcare Settings'>Healthcare Settings</a></b>'''
+ msg += '''<b><a href='/app/Form/Healthcare Settings'>Healthcare Settings</a></b>'''
frappe.throw(msg, title=_('Missing Configuration'))
clinical_procedures_to_invoice.append({
@@ -324,7 +324,7 @@
service_item_label = _('Inpatient Visit Charge Item')
msg = _(('Please Configure {0} in ').format(service_item_label) \
- + '''<b><a href='#Form/Healthcare Settings'>Healthcare Settings</a></b>''')
+ + '''<b><a href='/app/Form/Healthcare Settings'>Healthcare Settings</a></b>''')
frappe.throw(msg, title=_('Missing Configuration'))
@@ -334,7 +334,7 @@
charge_name = _('Inpatient Visit Charge')
msg = _(('Please Configure {0} for Healthcare Practitioner').format(charge_name) \
- + ''' <b><a href='#Form/Healthcare Practitioner/{0}'>{0}</a></b>'''.format(practitioner))
+ + ''' <b><a href='/app/Form/Healthcare Practitioner/{0}'>{0}</a></b>'''.format(practitioner))
frappe.throw(msg, title=_('Missing Configuration'))
@@ -654,6 +654,6 @@
><div class='col-md-12 col-sm-12'>" \
+ section_html + html +'</div></div>'
if doc_html:
- doc_html = "<div class='small'><div class='col-md-12 text-right'><a class='btn btn-default btn-xs' href='#Form/%s/%s'></a></div>" %(doctype, docname) + doc_html + '</div>'
+ doc_html = "<div class='small'><div class='col-md-12 text-right'><a class='btn btn-default btn-xs' href='/app/Form/%s/%s'></a></div>" %(doctype, docname) + doc_html + '</div>'
return {'html': doc_html}
diff --git a/erpnext/hr/doctype/employee_transfer/employee_transfer.py b/erpnext/hr/doctype/employee_transfer/employee_transfer.py
index c730e02..37d616f 100644
--- a/erpnext/hr/doctype/employee_transfer/employee_transfer.py
+++ b/erpnext/hr/doctype/employee_transfer/employee_transfer.py
@@ -50,7 +50,7 @@
employee = frappe.get_doc("Employee", self.employee)
if self.create_new_employee_id:
if self.new_employee_id:
- frappe.throw(_("Please delete the Employee <a href='#Form/Employee/{0}'>{0}</a>\
+ frappe.throw(_("Please delete the Employee <a href='/app/Form/Employee/{0}'>{0}</a>\
to cancel this document").format(self.new_employee_id))
#mark the employee as active
employee.status = "Active"
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
index 03fe3fa..32c5456 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
@@ -82,7 +82,7 @@
frappe.msgprint(_("{0} already allocated for Employee {1} for period {2} to {3}")
.format(self.leave_type, self.employee, formatdate(self.from_date), formatdate(self.to_date)))
- frappe.throw(_('Reference') + ': <a href="#Form/Leave Allocation/{0}">{0}</a>'
+ frappe.throw(_('Reference') + ': <a href="/app/Form/Leave Allocation/{0}">{0}</a>'
.format(leave_allocation[0][0]), OverlapError)
def validate_back_dated_allocation(self):
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 3f25f58..35c3ea7 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -246,7 +246,7 @@
def throw_overlap_error(self, d):
msg = _("Employee {0} has already applied for {1} between {2} and {3} : ").format(self.employee,
d['leave_type'], formatdate(d['from_date']), formatdate(d['to_date'])) \
- + """ <b><a href="#Form/Leave Application/{0}">{0}</a></b>""".format(d["name"])
+ + """ <b><a href="/app/Form/Leave Application/{0}">{0}</a></b>""".format(d["name"])
frappe.throw(msg, OverlapError)
def get_total_leaves_on_half_day(self):
diff --git a/erpnext/hr/doctype/shift_request/shift_request.py b/erpnext/hr/doctype/shift_request/shift_request.py
index 1c2801b..473193d 100644
--- a/erpnext/hr/doctype/shift_request/shift_request.py
+++ b/erpnext/hr/doctype/shift_request/shift_request.py
@@ -87,5 +87,5 @@
def throw_overlap_error(self, d):
msg = _("Employee {0} has already applied for {1} between {2} and {3} : ").format(self.employee,
d['shift_type'], formatdate(d['from_date']), formatdate(d['to_date'])) \
- + """ <b><a href="#Form/Shift Request/{0}">{0}</a></b>""".format(d["name"])
+ + """ <b><a href="/app/Form/Shift Request/{0}">{0}</a></b>""".format(d["name"])
frappe.throw(msg, OverlapError)
\ No newline at end of file
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index 8d95924..3b8d73b 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -211,7 +211,7 @@
def throw_overlap_error(doc, exists_for, overlap_doc, from_date, to_date):
msg = _("A {0} exists between {1} and {2} (").format(doc.doctype,
formatdate(from_date), formatdate(to_date)) \
- + """ <b><a href="#Form/{0}/{1}">{1}</a></b>""".format(doc.doctype, overlap_doc) \
+ + """ <b><a href="/app/Form/{0}/{1}">{1}</a></b>""".format(doc.doctype, overlap_doc) \
+ _(") for {0}").format(exists_for)
frappe.throw(msg)
diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js
index 1c4b7a1..55f7a1b 100644
--- a/erpnext/manufacturing/doctype/bom/bom.js
+++ b/erpnext/manufacturing/doctype/bom/bom.js
@@ -134,7 +134,7 @@
frm.set_intro(__('This is a Template BOM and will be used to make the work order for {0} of the item {1}',
[
`<a class="variants-intro">variants</a>`,
- `<a href="#Form/Item/${frm.doc.item}">${frm.doc.item}</a>`,
+ `<a href="/desk/Form/Item/${frm.doc.item}">${frm.doc.item}</a>`,
]), true);
frm.$wrapper.find(".variants-intro").on("click", () => {
diff --git a/erpnext/manufacturing/doctype/bom/bom_item_preview.html b/erpnext/manufacturing/doctype/bom/bom_item_preview.html
index c782f7b..6cd5f8c 100644
--- a/erpnext/manufacturing/doctype/bom/bom_item_preview.html
+++ b/erpnext/manufacturing/doctype/bom/bom_item_preview.html
@@ -12,11 +12,11 @@
<hr style="margin: 15px -15px;">
<p>
{% if data.value %}
- <a style="margin-right: 7px; margin-bottom: 7px" class="btn btn-default btn-xs" href="#Form/BOM/{{ data.value }}">
+ <a style="margin-right: 7px; margin-bottom: 7px" class="btn btn-default btn-xs" href="/app/Form/BOM/{{ data.value }}">
{{ __("Open BOM {0}", [data.value.bold()]) }}</a>
{% endif %}
{% if data.item_code %}
- <a class="btn btn-default btn-xs" href="#Form/Item/{{ data.item_code }}">
+ <a class="btn btn-default btn-xs" href="/app/Form/Item/{{ data.item_code }}">
{{ __("Open Item {0}", [data.item_code.bold()]) }}</a>
{% endif %}
</p>
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index 3833e86..8f9dd05 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -319,7 +319,7 @@
frappe.flags.mute_messages = False
if wo_list:
- wo_list = ["""<a href="#Form/Work Order/%s" target="_blank">%s</a>""" % \
+ wo_list = ["""<a href="/app/Form/Work Order/%s" target="_blank">%s</a>""" % \
(p, p) for p in wo_list]
msgprint(_("{0} created").format(comma_and(wo_list)))
else :
@@ -423,7 +423,7 @@
frappe.flags.mute_messages = False
if material_request_list:
- material_request_list = ["""<a href="#Form/Material Request/{0}">{1}</a>""".format(m.name, m.name) \
+ material_request_list = ["""<a href="/app/Form/Material Request/{0}">{1}</a>""".format(m.name, m.name) \
for m in material_request_list]
msgprint(_("{0} created").format(comma_and(material_request_list)))
else :
diff --git a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js
index 2ac6fa0..2f18d17 100644
--- a/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js
+++ b/erpnext/manufacturing/report/bom_stock_report/bom_stock_report.js
@@ -27,9 +27,9 @@
value = default_formatter(value, row, column, data);
if (column.id == "Item"){
if (data["Enough Parts to Build"] > 0){
- value = `<a style='color:green' href="#Form/Item/${data['Item']}" data-doctype="Item">${data['Item']}</a>`
+ value = `<a style='color:green' href="/desk/Form/Item/${data['Item']}" data-doctype="Item">${data['Item']}</a>`
} else {
- value = `<a style='color:red' href="#Form/Item/${data['Item']}" data-doctype="Item">${data['Item']}</a>`
+ value = `<a style='color:red' href="/desk/Form/Item/${data['Item']}" data-doctype="Item">${data['Item']}</a>`
}
}
return value
diff --git a/erpnext/payroll/doctype/payroll_period/payroll_period.py b/erpnext/payroll/doctype/payroll_period/payroll_period.py
index d7893d0..1c8cc53 100644
--- a/erpnext/payroll/doctype/payroll_period/payroll_period.py
+++ b/erpnext/payroll/doctype/payroll_period/payroll_period.py
@@ -41,7 +41,7 @@
if overlap_doc:
msg = _("A {0} exists between {1} and {2} (").format(self.doctype,
formatdate(self.start_date), formatdate(self.end_date)) \
- + """ <b><a href="#Form/{0}/{1}">{1}</a></b>""".format(self.doctype, overlap_doc[0].name) \
+ + """ <b><a href="/app/Form/{0}/{1}">{1}</a></b>""".format(self.doctype, overlap_doc[0].name) \
+ _(") for {0}").format(self.company)
frappe.throw(msg)
diff --git a/erpnext/projects/doctype/task/task_list.js b/erpnext/projects/doctype/task/task_list.js
index 941fe97..7c62031 100644
--- a/erpnext/projects/doctype/task/task_list.js
+++ b/erpnext/projects/doctype/task/task_list.js
@@ -26,7 +26,7 @@
},
gantt_custom_popup_html: function(ganttobj, task) {
var html = `<h5><a style="text-decoration:underline"\
- href="#Form/Task/${ganttobj.id}""> ${ganttobj.name} </a></h5>`;
+ href="/desk/Form/Task/${ganttobj.id}""> ${ganttobj.name} </a></h5>`;
if(task.project) html += `<p>Project: ${task.project}</p>`;
html += `<p>Progress: ${ganttobj.progress}</p>`;
diff --git a/erpnext/public/build.json b/erpnext/public/build.json
index 2695502..ec15b88 100644
--- a/erpnext/public/build.json
+++ b/erpnext/public/build.json
@@ -2,7 +2,8 @@
"css/erpnext.css": [
"public/less/erpnext.less",
"public/less/hub.less",
- "public/less/call_popup.less"
+ "public/less/call_popup.less",
+ "public/scss/point-of-sale.scss"
],
"css/marketplace.css": [
"public/less/hub.less"
@@ -27,16 +28,6 @@
"public/js/payment/payments.js",
"public/js/controllers/taxes_and_totals.js",
"public/js/controllers/transaction.js",
- "public/js/pos/pos.html",
- "public/js/pos/pos_bill_item.html",
- "public/js/pos/pos_bill_item_new.html",
- "public/js/pos/pos_selected_item.html",
- "public/js/pos/pos_item.html",
- "public/js/pos/pos_tax_row.html",
- "public/js/pos/customer_toolbar.html",
- "public/js/pos/pos_invoice_list.html",
- "public/js/payment/pos_payment.html",
- "public/js/payment/payment_details.html",
"public/js/templates/item_selector.html",
"public/js/templates/employees_to_mark_attendance.html",
"public/js/utils/item_selector.js",
@@ -55,5 +46,15 @@
"stock/dashboard/item_dashboard.html",
"stock/dashboard/item_dashboard_list.html",
"stock/dashboard/item_dashboard.js"
+ ],
+ "js/point-of-sale.min.js": [
+ "selling/page/point_of_sale/pos_item_selector.js",
+ "selling/page/point_of_sale/pos_item_cart.js",
+ "selling/page/point_of_sale/pos_item_details.js",
+ "selling/page/point_of_sale/pos_number_pad.js",
+ "selling/page/point_of_sale/pos_payment.js",
+ "selling/page/point_of_sale/pos_past_order_list.js",
+ "selling/page/point_of_sale/pos_past_order_summary.js",
+ "selling/page/point_of_sale/pos_controller.js"
]
}
diff --git a/erpnext/public/css/pos.css b/erpnext/public/css/pos.css
deleted file mode 100644
index 47f5771..0000000
--- a/erpnext/public/css/pos.css
+++ /dev/null
@@ -1,217 +0,0 @@
-[data-route="point-of-sale"] .layout-main-section { border: none; font-size: 12px; }
-[data-route="point-of-sale"] .layout-main-section-wrapper { margin-bottom: 0; }
-[data-route="point-of-sale"] .pos-items-wrapper { max-height: calc(100vh - 210px); }
-:root { --border-color: #d1d8dd; --text-color: #8d99a6; --primary: #5e64ff; }
-[data-route="point-of-sale"] .flex { display: flex; }
-[data-route="point-of-sale"] .grid { display: grid; }
-[data-route="point-of-sale"] .absolute { position: absolute; }
-[data-route="point-of-sale"] .relative { position: relative; }
-[data-route="point-of-sale"] .abs-center { top: 50%; left: 50%; transform: translate(-50%, -50%); }
-[data-route="point-of-sale"] .inline { display: inline; }
-[data-route="point-of-sale"] .float-right { float: right; }
-[data-route="point-of-sale"] .grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
-[data-route="point-of-sale"] .grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
-[data-route="point-of-sale"] .grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
-[data-route="point-of-sale"] .grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
-[data-route="point-of-sale"] .grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
-[data-route="point-of-sale"] .grid-cols-10 { grid-template-columns: repeat(10, minmax(0, 1fr)); }
-[data-route="point-of-sale"] .gap-2 { grid-gap: 0.5rem; gap: 0.5rem; }
-[data-route="point-of-sale"] .gap-4 { grid-gap: 1rem; gap: 1rem; }
-[data-route="point-of-sale"] .gap-6 { grid-gap: 1.25rem; gap: 1.25rem; }
-[data-route="point-of-sale"] .gap-8 { grid-gap: 1.5rem; gap: 1.5rem; }
-[data-route="point-of-sale"] .row-gap-2 { grid-row-gap: 0.5rem; row-gap: 0.5rem; }
-[data-route="point-of-sale"] .col-gap-4 { grid-column-gap: 1rem; column-gap: 1rem; }
-[data-route="point-of-sale"] .col-span-2 { grid-column: span 2 / span 2; }
-[data-route="point-of-sale"] .col-span-3 { grid-column: span 3 / span 3; }
-[data-route="point-of-sale"] .col-span-4 { grid-column: span 4 / span 4; }
-[data-route="point-of-sale"] .col-span-6 { grid-column: span 6 / span 6; }
-[data-route="point-of-sale"] .col-span-10 { grid-column: span 10 / span 10; }
-[data-route="point-of-sale"] .row-span-2 { grid-row: span 2 / span 2; }
-[data-route="point-of-sale"] .grid-auto-row { grid-auto-rows: 5.5rem; }
-[data-route="point-of-sale"] .d-none { display: none; }
-[data-route="point-of-sale"] .flex-wrap { flex-wrap: wrap; }
-[data-route="point-of-sale"] .flex-row { flex-direction: row; }
-[data-route="point-of-sale"] .flex-col { flex-direction: column; }
-[data-route="point-of-sale"] .flex-row-rev { flex-direction: row-reverse; }
-[data-route="point-of-sale"] .flex-col-rev { flex-direction: column-reverse; }
-[data-route="point-of-sale"] .flex-1 { flex: 1 1 0%; }
-[data-route="point-of-sale"] .items-center { align-items: center; }
-[data-route="point-of-sale"] .items-end { align-items: flex-end; }
-[data-route="point-of-sale"] .f-grow-1 { flex-grow: 1; }
-[data-route="point-of-sale"] .f-grow-2 { flex-grow: 2; }
-[data-route="point-of-sale"] .f-grow-3 { flex-grow: 3; }
-[data-route="point-of-sale"] .f-grow-4 { flex-grow: 4; }
-[data-route="point-of-sale"] .f-shrink-0 { flex-shrink: 0; }
-[data-route="point-of-sale"] .f-shrink-1 { flex-shrink: 1; }
-[data-route="point-of-sale"] .f-shrink-2 { flex-shrink: 2; }
-[data-route="point-of-sale"] .f-shrink-3 { flex-shrink: 3; }
-[data-route="point-of-sale"] .shadow { box-shadow: 0 0px 3px 0 rgba(0, 0, 0, 0.2), 0 1px 2px 0 rgba(0, 0, 0, 0.06); }
-[data-route="point-of-sale"] .shadow-sm { box-shadow: 0 0.5px 3px 0 rgba(0, 0, 0, 0.125); }
-[data-route="point-of-sale"] .shadow-inner { box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.1); }
-[data-route="point-of-sale"] .rounded { border-radius: 0.3rem; }
-[data-route="point-of-sale"] .rounded-b { border-bottom-left-radius: 0.3rem; border-bottom-right-radius: 0.3rem; }
-[data-route="point-of-sale"] .p-8 { padding: 2rem; }
-[data-route="point-of-sale"] .p-16 { padding: 4rem; }
-[data-route="point-of-sale"] .p-32 { padding: 8rem; }
-[data-route="point-of-sale"] .p-6 { padding: 1.5rem; }
-[data-route="point-of-sale"] .p-4 { padding: 1rem; }
-[data-route="point-of-sale"] .p-3 { padding: 0.75rem; }
-[data-route="point-of-sale"] .p-2 { padding: 0.5rem; }
-[data-route="point-of-sale"] .m-8 { margin: 2rem; }
-[data-route="point-of-sale"] .p-1 { padding: 0.25rem; }
-[data-route="point-of-sale"] .pr-0 { padding-right: 0rem; }
-[data-route="point-of-sale"] .pl-0 { padding-left: 0rem; }
-[data-route="point-of-sale"] .pt-0 { padding-top: 0rem; }
-[data-route="point-of-sale"] .pb-0 { padding-bottom: 0rem; }
-[data-route="point-of-sale"] .mr-0 { margin-right: 0rem; }
-[data-route="point-of-sale"] .ml-0 { margin-left: 0rem; }
-[data-route="point-of-sale"] .mt-0 { margin-top: 0rem; }
-[data-route="point-of-sale"] .mb-0 { margin-bottom: 0rem; }
-[data-route="point-of-sale"] .pr-2 { padding-right: 0.5rem; }
-[data-route="point-of-sale"] .pl-2 { padding-left: 0.5rem; }
-[data-route="point-of-sale"] .pt-2 { padding-top: 0.5rem; }
-[data-route="point-of-sale"] .pb-2 { padding-bottom: 0.5rem; }
-[data-route="point-of-sale"] .pr-3 { padding-right: 0.75rem; }
-[data-route="point-of-sale"] .pl-3 { padding-left: 0.75rem; }
-[data-route="point-of-sale"] .pt-3 { padding-top: 0.75rem; }
-[data-route="point-of-sale"] .pb-3 { padding-bottom: 0.75rem; }
-[data-route="point-of-sale"] .pr-4 { padding-right: 1rem; }
-[data-route="point-of-sale"] .pl-4 { padding-left: 1rem; }
-[data-route="point-of-sale"] .pt-4 { padding-top: 1rem; }
-[data-route="point-of-sale"] .pb-4 { padding-bottom: 1rem; }
-[data-route="point-of-sale"] .mr-4 { margin-right: 1rem; }
-[data-route="point-of-sale"] .ml-4 { margin-left: 1rem; }
-[data-route="point-of-sale"] .mt-4 { margin-top: 1rem; }
-[data-route="point-of-sale"] .mb-4 { margin-bottom: 1rem; }
-[data-route="point-of-sale"] .mr-2 { margin-right: 0.5rem; }
-[data-route="point-of-sale"] .ml-2 { margin-left: 0.5rem; }
-[data-route="point-of-sale"] .mt-2 { margin-top: 0.5rem; }
-[data-route="point-of-sale"] .mb-2 { margin-bottom: 0.5rem; }
-[data-route="point-of-sale"] .mr-1 { margin-right: 0.25rem; }
-[data-route="point-of-sale"] .ml-1 { margin-left: 0.25rem; }
-[data-route="point-of-sale"] .mt-1 { margin-top: 0.25rem; }
-[data-route="point-of-sale"] .mb-1 { margin-bottom: 0.25rem; }
-[data-route="point-of-sale"] .mr-auto { margin-right: auto; }
-[data-route="point-of-sale"] .ml-auto { margin-left: auto; }
-[data-route="point-of-sale"] .mt-auto { margin-top: auto; }
-[data-route="point-of-sale"] .mb-auto { margin-bottom: auto; }
-[data-route="point-of-sale"] .pr-6 { padding-right: 1.5rem; }
-[data-route="point-of-sale"] .pl-6 { padding-left: 1.5rem; }
-[data-route="point-of-sale"] .pt-6 { padding-top: 1.5rem; }
-[data-route="point-of-sale"] .pb-6 { padding-bottom: 1.5rem; }
-[data-route="point-of-sale"] .mr-6 { margin-right: 1.5rem; }
-[data-route="point-of-sale"] .ml-6 { margin-left: 1.5rem; }
-[data-route="point-of-sale"] .mt-6 { margin-top: 1.5rem; }
-[data-route="point-of-sale"] .mb-6 { margin-bottom: 1.5rem; }
-[data-route="point-of-sale"] .mr-8 { margin-right: 2rem; }
-[data-route="point-of-sale"] .ml-8 { margin-left: 2rem; }
-[data-route="point-of-sale"] .mt-8 { margin-top: 2rem; }
-[data-route="point-of-sale"] .mb-8 { margin-bottom: 2rem; }
-[data-route="point-of-sale"] .pr-8 { padding-right: 2rem; }
-[data-route="point-of-sale"] .pl-8 { padding-left: 2rem; }
-[data-route="point-of-sale"] .pt-8 { padding-top: 2rem; }
-[data-route="point-of-sale"] .pb-8 { padding-bottom: 2rem; }
-[data-route="point-of-sale"] .pr-16 { padding-right: 4rem; }
-[data-route="point-of-sale"] .pl-16 { padding-left: 4rem; }
-[data-route="point-of-sale"] .pt-16 { padding-top: 4rem; }
-[data-route="point-of-sale"] .pb-16 { padding-bottom: 4rem; }
-[data-route="point-of-sale"] .w-full { width: 100%; }
-[data-route="point-of-sale"] .h-full { height: 100%; }
-[data-route="point-of-sale"] .w-quarter { width: 25%; }
-[data-route="point-of-sale"] .w-half { width: 50%; }
-[data-route="point-of-sale"] .w-66 { width: 66.66%; }
-[data-route="point-of-sale"] .w-33 { width: 33.33%; }
-[data-route="point-of-sale"] .w-60 { width: 60%; }
-[data-route="point-of-sale"] .w-40 { width: 40%; }
-[data-route="point-of-sale"] .w-fit { width: fit-content; }
-[data-route="point-of-sale"] .w-6 { width: 2rem; }
-[data-route="point-of-sale"] .h-6 { min-height: 2rem; height: 2rem; }
-[data-route="point-of-sale"] .w-8 { width: 2.5rem; }
-[data-route="point-of-sale"] .h-8 { min-height: 2.5rem; height: 2.5rem; }
-[data-route="point-of-sale"] .w-10 { width: 3rem; }
-[data-route="point-of-sale"] .h-10 { min-height:3rem; height: 3rem; }
-[data-route="point-of-sale"] .h-12 { min-height: 3.3rem; height: 3.3rem; }
-[data-route="point-of-sale"] .w-12 { width: 3.3rem; }
-[data-route="point-of-sale"] .h-14 { min-height: 4.2rem; height: 4.2rem; }
-[data-route="point-of-sale"] .h-16 { min-height: 4.6rem; height: 4.6rem; }
-[data-route="point-of-sale"] .h-18 { min-height: 5rem; height: 5rem; }
-[data-route="point-of-sale"] .w-18 { width: 5.4rem; }
-[data-route="point-of-sale"] .w-24 { width: 7.2rem; }
-[data-route="point-of-sale"] .w-26 { width: 8.4rem; }
-[data-route="point-of-sale"] .h-24 { min-height: 7.2rem; height: 7.2rem; }
-[data-route="point-of-sale"] .h-32 { min-height: 9.6rem; height: 9.6rem; }
-[data-route="point-of-sale"] .w-46 { width: 15rem; }
-[data-route="point-of-sale"] .h-46 { min-height:15rem; height: 15rem; }
-[data-route="point-of-sale"] .h-100 { height: 100vh; }
-[data-route="point-of-sale"] .mx-h-70 { max-height: 67rem; }
-[data-route="point-of-sale"] .border-grey-300 { border-color: #e2e8f0; }
-[data-route="point-of-sale"] .border-grey { border: 1px solid #d1d8dd; }
-[data-route="point-of-sale"] .border-white { border: 1px solid #fff; }
-[data-route="point-of-sale"] .border-b-grey { border-bottom: 1px solid #d1d8dd; }
-[data-route="point-of-sale"] .border-t-grey { border-top: 1px solid #d1d8dd; }
-[data-route="point-of-sale"] .border-r-grey { border-right: 1px solid #d1d8dd; }
-[data-route="point-of-sale"] .text-dark-grey { color: #5f5f5f; }
-[data-route="point-of-sale"] .text-grey { color: #8d99a6; }
-[data-route="point-of-sale"] .text-grey-100 { color: #d1d8dd; }
-[data-route="point-of-sale"] .text-grey-200 { color: #a0aec0; }
-[data-route="point-of-sale"] .bg-green-200 { background-color: #c6f6d5; }
-[data-route="point-of-sale"] .text-bold { font-weight: bold; }
-[data-route="point-of-sale"] .italic { font-style: italic; }
-[data-route="point-of-sale"] .font-weight-450 { font-weight: 450; }
-[data-route="point-of-sale"] .justify-around { justify-content: space-around; }
-[data-route="point-of-sale"] .justify-between { justify-content: space-between; }
-[data-route="point-of-sale"] .justify-center { justify-content: center; }
-[data-route="point-of-sale"] .justify-end { justify-content: flex-end; }
-[data-route="point-of-sale"] .bg-white { background-color: white; }
-[data-route="point-of-sale"] .bg-light-grey { background-color: #f0f4f7; }
-[data-route="point-of-sale"] .bg-grey-100 { background-color: #f7fafc; }
-[data-route="point-of-sale"] .bg-grey-200 { background-color: #edf2f7; }
-[data-route="point-of-sale"] .bg-grey { background-color: #f4f5f6; }
-[data-route="point-of-sale"] .text-center { text-align: center; }
-[data-route="point-of-sale"] .text-right { text-align: right; }
-[data-route="point-of-sale"] .text-sm { font-size: 1rem; }
-[data-route="point-of-sale"] .text-md-0 { font-size: 1.25rem; }
-[data-route="point-of-sale"] .text-md { font-size: 1.4rem; }
-[data-route="point-of-sale"] .text-lg { font-size: 1.6rem; }
-[data-route="point-of-sale"] .text-xl { font-size: 2.2rem; }
-[data-route="point-of-sale"] .text-2xl { font-size: 2.8rem; }
-[data-route="point-of-sale"] .text-2-5xl { font-size: 3rem; }
-[data-route="point-of-sale"] .text-3xl { font-size: 3.8rem; }
-[data-route="point-of-sale"] .text-6xl { font-size: 4.8rem; }
-[data-route="point-of-sale"] .line-through { text-decoration: line-through; }
-[data-route="point-of-sale"] .text-primary { color: #5e64ff; }
-[data-route="point-of-sale"] .text-white { color: #fff; }
-[data-route="point-of-sale"] .text-green-500 { color: #48bb78; }
-[data-route="point-of-sale"] .bg-primary { background-color: #5e64ff; }
-[data-route="point-of-sale"] .border-primary { border-color: #5e64ff; }
-[data-route="point-of-sale"] .text-danger { color: #e53e3e; }
-[data-route="point-of-sale"] .scroll-x { overflow-x: scroll;overflow-y: hidden; }
-[data-route="point-of-sale"] .scroll-y { overflow-y: scroll;overflow-x: hidden; }
-[data-route="point-of-sale"] .overflow-hidden { overflow: hidden; }
-[data-route="point-of-sale"] .whitespace-nowrap { white-space: nowrap; }
-[data-route="point-of-sale"] .sticky { position: sticky; top: -1px; }
-[data-route="point-of-sale"] .bg-white { background-color: #fff; }
-[data-route="point-of-sale"] .bg-selected { background-color: #fffdf4; }
-[data-route="point-of-sale"] .border-dashed { border-width:1px; border-style: dashed; }
-[data-route="point-of-sale"] .z-100 { z-index: 100; }
-
-[data-route="point-of-sale"] .frappe-control { margin: 0 !important; width: 100%; }
-[data-route="point-of-sale"] .form-control { font-size: 12px; }
-[data-route="point-of-sale"] .form-group { margin: 0 !important; }
-[data-route="point-of-sale"] .pointer { cursor: pointer; }
-[data-route="point-of-sale"] .no-select { user-select: none; }
-[data-route="point-of-sale"] .item-wrapper:hover { transform: scale(1.02, 1.02); }
-[data-route="point-of-sale"] .hover-underline:hover { text-decoration: underline; }
-[data-route="point-of-sale"] .item-wrapper { transition: scale 0.2s ease-in-out; }
-[data-route="point-of-sale"] .cart-items-section .cart-item-wrapper:not(:first-child) { border-top: none; }
-[data-route="point-of-sale"] .customer-transactions .invoice-wrapper:not(:first-child) { border-top: none; }
-
-[data-route="point-of-sale"] .payment-summary-wrapper:last-child { border-bottom: none; }
-[data-route="point-of-sale"] .item-summary-wrapper:last-child { border-bottom: none; }
-[data-route="point-of-sale"] .total-summary-wrapper:last-child { border-bottom: none; }
-[data-route="point-of-sale"] .invoices-container .invoice-wrapper:last-child { border-bottom: none; }
-[data-route="point-of-sale"] .new-btn { background-color: #5e64ff; color: white; border: none;}
-[data-route="point-of-sale"] .summary-btns:last-child { margin-right: 0px; }
-[data-route="point-of-sale"] ::-webkit-scrollbar { width: 1px }
-
-[data-route="point-of-sale"] .indicator.grey::before { background-color: #8d99a6; }
\ No newline at end of file
diff --git a/erpnext/public/js/call_popup/call_popup.js b/erpnext/public/js/call_popup/call_popup.js
index 5e4d4a5..378d6d1 100644
--- a/erpnext/public/js/call_popup/call_popup.js
+++ b/erpnext/public/js/call_popup/call_popup.js
@@ -85,7 +85,7 @@
<br>
<a
class="text-small text-muted"
- href="#Form/Call Log/${this.call_log.name}">
+ href="/desk/Form/Call Log/${this.call_log.name}">
${__('View call log')}
</a>
`,
@@ -167,7 +167,7 @@
const issue_field = this.dialog.get_field("last_issue");
issue_field.set_value(issue.subject);
issue_field.$wrapper.append(`
- <a class="text-medium" href="#List/Issue?customer=${issue.customer}">
+ <a class="text-medium" href="/desk/List/Issue?customer=${issue.customer}">
${__('View all issues from {0}', [issue.customer])}
</a>
`);
diff --git a/erpnext/public/js/communication.js b/erpnext/public/js/communication.js
index 26e5ab8..38778e2 100644
--- a/erpnext/public/js/communication.js
+++ b/erpnext/public/js/communication.js
@@ -84,7 +84,7 @@
frm.reload_doc();
frappe.show_alert({
message: __("Opportunity {0} created",
- ['<a href="#Form/Opportunity/'+r.message+'">' + r.message + '</a>']),
+ ['<a href="/desk/Form/Opportunity/'+r.message+'">' + r.message + '</a>']),
indicator: 'green'
});
}
diff --git a/erpnext/public/js/education/assessment_result_tool.html b/erpnext/public/js/education/assessment_result_tool.html
index 9fc17f7..b591010 100644
--- a/erpnext/public/js/education/assessment_result_tool.html
+++ b/erpnext/public/js/education/assessment_result_tool.html
@@ -19,7 +19,7 @@
</thead>
<tbody>
{% for s in students %}
- <tr
+ <tr
{% if(s.assessment_details && s.docstatus && s.docstatus == 1) { %} class="text-muted" {% } %}
data-student="{{s.student}}">
@@ -29,7 +29,7 @@
<td>
<span data-student="{{s.student}}" data-criteria="{{c.assessment_criteria}}" class="student-result-grade badge" >
{% if(s.assessment_details) { %}
- {{s.assessment_details[c.assessment_criteria][1]}}
+ {{s.assessment_details[c.assessment_criteria][1]}}
{% } %}
</span>
<input type="number" class="student-result-data" style="width:70%; float:right;"
@@ -61,7 +61,7 @@
{% } %}
</span>
<span data-student="{{s.student}}" class="total-result-link" style="width: 10%; display:{% if(!s.assessment_details) { %}None{% } %}; float:right;">
- <a class="btn-open no-decoration" title="Open Link" href="#Form/Assessment Result/{% if(s.assessment_details) { %}{{s.name}}{% } %}">
+ <a class="btn-open no-decoration" title="Open Link" href="/app/Form/Assessment Result/{% if(s.assessment_details) { %}{{s.name}}{% } %}">
<i class="octicon octicon-arrow-right"></i>
</a>
</span>
diff --git a/erpnext/public/js/payment/payment_details.html b/erpnext/public/js/payment/payment_details.html
deleted file mode 100644
index 3e63944..0000000
--- a/erpnext/public/js/payment/payment_details.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<div class="row pos-payment-row" type="{{type}}" idx={{idx}}>
- <div class="col-xs-6" style="padding:20px">{{mode_of_payment}}</div>
- <div class="col-xs-6">
- <div class="input-group">
- <input disabled class="form-control text-right amount" idx="{{idx}}" type="text" value="{%= format_currency(amount, currency) %}">
- <span class="input-group-btn">
- <button type="button" class="btn btn-default clr" idx="{{idx}}" style="border:1px solid #d1d8dd">C</button>
- </span>
- </div>
- </div>
-</div>
\ No newline at end of file
diff --git a/erpnext/public/js/payment/pos_payment.html b/erpnext/public/js/payment/pos_payment.html
deleted file mode 100644
index cb6971b..0000000
--- a/erpnext/public/js/payment/pos_payment.html
+++ /dev/null
@@ -1,42 +0,0 @@
-<div class="pos_payment row">
- <div class="row" style="padding: 0px 30px;">
- <h3>{{ __("Total Amount") }}: <span class="label label-default" style="font-size:20px;padding:5px">{%= format_currency(grand_total, currency) %}</span></h3>
- </div>
- <div class="row amount-row">
- <div class="col-xs-6 col-sm-3 text-center">
- <p class="amount-label"> {{ __("Paid") }} <h3 class="paid_amount">{%= format_currency(paid_amount, currency) %}</h3></p>
- </div>
- <div class="col-xs-6 col-sm-3 text-center">
- <p class="amount-label"> {{ __("Outstanding") }} <h3 class="outstanding_amount">{%= format_currency(outstanding_amount, currency) %} </h3></p>
- </div>
- <div class="col-xs-6 col-sm-3 text-center">
- <p class="amount-label"> {{ __("Change") }} <input class="form-control text-right change_amount bold" type="text" idx="change_amount" value="{{format_number(change_amount, null, 2)}}">
- </p>
- </div>
- <div class="col-xs-6 col-sm-3 text-center">
- <p class="amount-label"> {{ __("Write off") }} <input class="form-control text-right write_off_amount bold" type="text" idx="write_off_amount" value="{{format_number(write_off_amount, null, 2)}}">
- </p>
- </div>
- </div>
- <hr>
- <div class="row">
- <div class="col-sm-6 ">
- <div class ="row multimode-payments" style = "margin-right:10px">
- </div>
- </div>
- <div class="col-sm-6 payment-toolbar">
- {% for(var i=0; i<3; i++) { %}
- <div class="row">
- {% for(var j=i*3; j<(i+1)*3; j++) { %}
- <button type="button" class="btn btn-default pos-keyboard-key">{{j+1}}</button>
- {% } %}
- </div>
- {% } %}
- <div class="row">
- <button type="button" class="btn btn-default delete-btn">{{ __("Del") }}</button>
- <button type="button" class="btn btn-default pos-keyboard-key">0</button>
- <button type="button" class="btn btn-default pos-keyboard-key">.</button>
- </div>
- </div>
- </div>
-</div>
diff --git a/erpnext/public/js/pos/clusterize.js b/erpnext/public/js/pos/clusterize.js
deleted file mode 100644
index 075c9ca..0000000
--- a/erpnext/public/js/pos/clusterize.js
+++ /dev/null
@@ -1,330 +0,0 @@
-/* eslint-disable */
-/*! Clusterize.js - v0.17.6 - 2017-03-05
-* http://NeXTs.github.com/Clusterize.js/
-* Copyright (c) 2015 Denis Lukov; Licensed GPLv3 */
-
-;(function(name, definition) {
- if (typeof module != 'undefined') module.exports = definition();
- else if (typeof define == 'function' && typeof define.amd == 'object') define(definition);
- else this[name] = definition();
-}('Clusterize', function() {
- "use strict"
-
- // detect ie9 and lower
- // https://gist.github.com/padolsey/527683#comment-786682
- var ie = (function(){
- for( var v = 3,
- el = document.createElement('b'),
- all = el.all || [];
- el.innerHTML = '<!--[if gt IE ' + (++v) + ']><i><![endif]-->',
- all[0];
- ){}
- return v > 4 ? v : document.documentMode;
- }()),
- is_mac = navigator.platform.toLowerCase().indexOf('mac') + 1;
- var Clusterize = function(data) {
- if( ! (this instanceof Clusterize))
- return new Clusterize(data);
- var self = this;
-
- var defaults = {
- rows_in_block: 50,
- blocks_in_cluster: 4,
- tag: null,
- show_no_data_row: true,
- no_data_class: 'clusterize-no-data',
- no_data_text: 'No data',
- keep_parity: true,
- callbacks: {}
- }
-
- // public parameters
- self.options = {};
- var options = ['rows_in_block', 'blocks_in_cluster', 'show_no_data_row', 'no_data_class', 'no_data_text', 'keep_parity', 'tag', 'callbacks'];
- for(var i = 0, option; option = options[i]; i++) {
- self.options[option] = typeof data[option] != 'undefined' && data[option] != null
- ? data[option]
- : defaults[option];
- }
-
- var elems = ['scroll', 'content'];
- for(var i = 0, elem; elem = elems[i]; i++) {
- self[elem + '_elem'] = data[elem + 'Id']
- ? document.getElementById(data[elem + 'Id'])
- : data[elem + 'Elem'];
- if( ! self[elem + '_elem'])
- throw new Error("Error! Could not find " + elem + " element");
- }
-
- // tabindex forces the browser to keep focus on the scrolling list, fixes #11
- if( ! self.content_elem.hasAttribute('tabindex'))
- self.content_elem.setAttribute('tabindex', 0);
-
- // private parameters
- var rows = isArray(data.rows)
- ? data.rows
- : self.fetchMarkup(),
- cache = {},
- scroll_top = self.scroll_elem.scrollTop;
-
- // append initial data
- self.insertToDOM(rows, cache);
-
- // restore the scroll position
- self.scroll_elem.scrollTop = scroll_top;
-
- // adding scroll handler
- var last_cluster = false,
- scroll_debounce = 0,
- pointer_events_set = false,
- scrollEv = function() {
- // fixes scrolling issue on Mac #3
- if (is_mac) {
- if( ! pointer_events_set) self.content_elem.style.pointerEvents = 'none';
- pointer_events_set = true;
- clearTimeout(scroll_debounce);
- scroll_debounce = setTimeout(function () {
- self.content_elem.style.pointerEvents = 'auto';
- pointer_events_set = false;
- }, 50);
- }
- if (last_cluster != (last_cluster = self.getClusterNum()))
- self.insertToDOM(rows, cache);
- if (self.options.callbacks.scrollingProgress)
- self.options.callbacks.scrollingProgress(self.getScrollProgress());
- },
- resize_debounce = 0,
- resizeEv = function() {
- clearTimeout(resize_debounce);
- resize_debounce = setTimeout(self.refresh, 100);
- }
- on('scroll', self.scroll_elem, scrollEv);
- on('resize', window, resizeEv);
-
- // public methods
- self.destroy = function(clean) {
- off('scroll', self.scroll_elem, scrollEv);
- off('resize', window, resizeEv);
- self.html((clean ? self.generateEmptyRow() : rows).join(''));
- }
- self.refresh = function(force) {
- if(self.getRowsHeight(rows) || force) self.update(rows);
- }
- self.update = function(new_rows) {
- rows = isArray(new_rows)
- ? new_rows
- : [];
- var scroll_top = self.scroll_elem.scrollTop;
- // fixes #39
- if(rows.length * self.options.item_height < scroll_top) {
- self.scroll_elem.scrollTop = 0;
- last_cluster = 0;
- }
- self.insertToDOM(rows, cache);
- self.scroll_elem.scrollTop = scroll_top;
- }
- self.clear = function() {
- self.update([]);
- }
- self.getRowsAmount = function() {
- return rows.length;
- }
- self.getScrollProgress = function() {
- return this.options.scroll_top / (rows.length * this.options.item_height) * 100 || 0;
- }
-
- var add = function(where, _new_rows) {
- var new_rows = isArray(_new_rows)
- ? _new_rows
- : [];
- if( ! new_rows.length) return;
- rows = where == 'append'
- ? rows.concat(new_rows)
- : new_rows.concat(rows);
- self.insertToDOM(rows, cache);
- }
- self.append = function(rows) {
- add('append', rows);
- }
- self.prepend = function(rows) {
- add('prepend', rows);
- }
- }
-
- Clusterize.prototype = {
- constructor: Clusterize,
- // fetch existing markup
- fetchMarkup: function() {
- var rows = [], rows_nodes = this.getChildNodes(this.content_elem);
- while (rows_nodes.length) {
- rows.push(rows_nodes.shift().outerHTML);
- }
- return rows;
- },
- // get tag name, content tag name, tag height, calc cluster height
- exploreEnvironment: function(rows, cache) {
- var opts = this.options;
- opts.content_tag = this.content_elem.tagName.toLowerCase();
- if( ! rows.length) return;
- if(ie && ie <= 9 && ! opts.tag) opts.tag = rows[0].match(/<([^>\s/]*)/)[1].toLowerCase();
- if(this.content_elem.children.length <= 1) cache.data = this.html(rows[0] + rows[0] + rows[0]);
- if( ! opts.tag) opts.tag = this.content_elem.children[0].tagName.toLowerCase();
- this.getRowsHeight(rows);
- },
- getRowsHeight: function(rows) {
- var opts = this.options,
- prev_item_height = opts.item_height;
- opts.cluster_height = 0;
- if( ! rows.length) return;
- var nodes = this.content_elem.children;
- var node = nodes[Math.floor(nodes.length / 2)];
- opts.item_height = node.offsetHeight;
- // consider table's border-spacing
- if(opts.tag == 'tr' && getStyle('borderCollapse', this.content_elem) != 'collapse')
- opts.item_height += parseInt(getStyle('borderSpacing', this.content_elem), 10) || 0;
- // consider margins (and margins collapsing)
- if(opts.tag != 'tr') {
- var marginTop = parseInt(getStyle('marginTop', node), 10) || 0;
- var marginBottom = parseInt(getStyle('marginBottom', node), 10) || 0;
- opts.item_height += Math.max(marginTop, marginBottom);
- }
- opts.block_height = opts.item_height * opts.rows_in_block;
- opts.rows_in_cluster = opts.blocks_in_cluster * opts.rows_in_block;
- opts.cluster_height = opts.blocks_in_cluster * opts.block_height;
- return prev_item_height != opts.item_height;
- },
- // get current cluster number
- getClusterNum: function () {
- this.options.scroll_top = this.scroll_elem.scrollTop;
- return Math.floor(this.options.scroll_top / (this.options.cluster_height - this.options.block_height)) || 0;
- },
- // generate empty row if no data provided
- generateEmptyRow: function() {
- var opts = this.options;
- if( ! opts.tag || ! opts.show_no_data_row) return [];
- var empty_row = document.createElement(opts.tag),
- no_data_content = document.createTextNode(opts.no_data_text), td;
- empty_row.className = opts.no_data_class;
- if(opts.tag == 'tr') {
- td = document.createElement('td');
- // fixes #53
- td.colSpan = 100;
- td.appendChild(no_data_content);
- }
- empty_row.appendChild(td || no_data_content);
- return [empty_row.outerHTML];
- },
- // generate cluster for current scroll position
- generate: function (rows, cluster_num) {
- var opts = this.options,
- rows_len = rows.length;
- if (rows_len < opts.rows_in_block) {
- return {
- top_offset: 0,
- bottom_offset: 0,
- rows_above: 0,
- rows: rows_len ? rows : this.generateEmptyRow()
- }
- }
- var items_start = Math.max((opts.rows_in_cluster - opts.rows_in_block) * cluster_num, 0),
- items_end = items_start + opts.rows_in_cluster,
- top_offset = Math.max(items_start * opts.item_height, 0),
- bottom_offset = Math.max((rows_len - items_end) * opts.item_height, 0),
- this_cluster_rows = [],
- rows_above = items_start;
- if(top_offset < 1) {
- rows_above++;
- }
- for (var i = items_start; i < items_end; i++) {
- rows[i] && this_cluster_rows.push(rows[i]);
- }
- return {
- top_offset: top_offset,
- bottom_offset: bottom_offset,
- rows_above: rows_above,
- rows: this_cluster_rows
- }
- },
- renderExtraTag: function(class_name, height) {
- var tag = document.createElement(this.options.tag),
- clusterize_prefix = 'clusterize-';
- tag.className = [clusterize_prefix + 'extra-row', clusterize_prefix + class_name].join(' ');
- height && (tag.style.height = height + 'px');
- return tag.outerHTML;
- },
- // if necessary verify data changed and insert to DOM
- insertToDOM: function(rows, cache) {
- // explore row's height
- if( ! this.options.cluster_height) {
- this.exploreEnvironment(rows, cache);
- }
- var data = this.generate(rows, this.getClusterNum()),
- this_cluster_rows = data.rows.join(''),
- this_cluster_content_changed = this.checkChanges('data', this_cluster_rows, cache),
- top_offset_changed = this.checkChanges('top', data.top_offset, cache),
- only_bottom_offset_changed = this.checkChanges('bottom', data.bottom_offset, cache),
- callbacks = this.options.callbacks,
- layout = [];
-
- if(this_cluster_content_changed || top_offset_changed) {
- if(data.top_offset) {
- this.options.keep_parity && layout.push(this.renderExtraTag('keep-parity'));
- layout.push(this.renderExtraTag('top-space', data.top_offset));
- }
- layout.push(this_cluster_rows);
- data.bottom_offset && layout.push(this.renderExtraTag('bottom-space', data.bottom_offset));
- callbacks.clusterWillChange && callbacks.clusterWillChange();
- this.html(layout.join(''));
- this.options.content_tag == 'ol' && this.content_elem.setAttribute('start', data.rows_above);
- callbacks.clusterChanged && callbacks.clusterChanged();
- } else if(only_bottom_offset_changed) {
- this.content_elem.lastChild.style.height = data.bottom_offset + 'px';
- }
- },
- // unfortunately ie <= 9 does not allow to use innerHTML for table elements, so make a workaround
- html: function(data) {
- var content_elem = this.content_elem;
- if(ie && ie <= 9 && this.options.tag == 'tr') {
- var div = document.createElement('div'), last;
- div.innerHTML = '<table><tbody>' + data + '</tbody></table>';
- while((last = content_elem.lastChild)) {
- content_elem.removeChild(last);
- }
- var rows_nodes = this.getChildNodes(div.firstChild.firstChild);
- while (rows_nodes.length) {
- content_elem.appendChild(rows_nodes.shift());
- }
- } else {
- content_elem.innerHTML = data;
- }
- },
- getChildNodes: function(tag) {
- var child_nodes = tag.children, nodes = [];
- for (var i = 0, ii = child_nodes.length; i < ii; i++) {
- nodes.push(child_nodes[i]);
- }
- return nodes;
- },
- checkChanges: function(type, value, cache) {
- var changed = value != cache[type];
- cache[type] = value;
- return changed;
- }
- }
-
- // support functions
- function on(evt, element, fnc) {
- return element.addEventListener ? element.addEventListener(evt, fnc, false) : element.attachEvent("on" + evt, fnc);
- }
- function off(evt, element, fnc) {
- return element.removeEventListener ? element.removeEventListener(evt, fnc, false) : element.detachEvent("on" + evt, fnc);
- }
- function isArray(arr) {
- return Object.prototype.toString.call(arr) === '[object Array]';
- }
- function getStyle(prop, elem) {
- return window.getComputedStyle ? window.getComputedStyle(elem)[prop] : elem.currentStyle[prop];
- }
-
- return Clusterize;
-}));
\ No newline at end of file
diff --git a/erpnext/public/js/pos/customer_toolbar.html b/erpnext/public/js/pos/customer_toolbar.html
deleted file mode 100644
index 3ba5ccb..0000000
--- a/erpnext/public/js/pos/customer_toolbar.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<div class="pos-bill-toolbar col-xs-9" style="display: flex; width: 70%;">
- <div class="party-area" style="flex: 1;">
- <span class="edit-customer-btn text-muted" style="display: inline;">
- <a class="btn-open no-decoration" title="Edit Customer">
- <i class="octicon octicon-pencil"></i>
- </a>
- </span>
- </div>
- <button class="btn btn-default list-customers-btn" style="margin-left: 12px">
- <i class="octicon octicon-organization"></i>
- </button>
- </button> {% if (allow_delete) { %}
- <button class="btn btn-default btn-danger" style="margin: 0 5px 0 5px">
- <i class="octicon octicon-trashcan"></i>
- </button> {% } %}
-</div>
\ No newline at end of file
diff --git a/erpnext/public/js/pos/pos.html b/erpnext/public/js/pos/pos.html
deleted file mode 100644
index 89e2940..0000000
--- a/erpnext/public/js/pos/pos.html
+++ /dev/null
@@ -1,136 +0,0 @@
-<div class="pos">
- <div class="row">
- <div class="col-sm-5 pos-bill-wrapper">
- <div class="col-sm-12"><h6 class="form-section-heading uppercase">{{ __("Item Cart") }}</h6></div>
- <div class="pos-bill">
- <div class="item-cart">
- <div class="pos-list-row pos-bill-header text-muted h6">
- <span class="cell subject">
- <!--<input class="list-select-all" type="checkbox" title="{%= __("Select All") %}">-->
- {{ __("Item Name")}}
- </span>
- <span class="cell text-right">{{ __("Quantity") }}</span>
- <span class="cell text-right">{{ __("Discount") }}</span>
- <span class="cell text-right">{{ __("Rate") }}</span>
- </div>
- <div class="item-cart-items">
- <div class="no-items-message text-extra-muted">
- <span class="text-center">
- <i class="fa fa-2x fa-shopping-cart"></i>
- <p>{{ __("Tap items to add them here") }}</p>
- </span>
- </div>
- <div class="items">
- </div>
- </div>
- </div>
- </div>
- <div class="totals-area">
- <div class="pos-list-row net-total-area">
- <div class="cell"></div>
- <div class="cell text-right">{%= __("Net Total") %}</div>
- <div class="cell price-cell bold net-total text-right"></div>
- </div>
- <div class="pos-list-row tax-area">
- <div class="cell"></div>
- <div class="cell text-right">{%= __("Taxes") %}</div>
- <div class="cell price-cell text-right tax-table">
- </div>
- </div>
- {% if(allow_user_to_edit_discount) { %}
- <div class="pos-list-row discount-amount-area">
- <div class="cell"></div>
- <div class="cell text-right">{%= __("Discount") %}</div>
- <div class="cell price-cell discount-field-col">
- <div class="input-group input-group-sm">
- <span class="input-group-addon">%</span>
- <input type="text" class="form-control discount-percentage text-right">
- </div>
- <div class="input-group input-group-sm">
- <span class="input-group-addon">{%= get_currency_symbol(currency) %}</span>
- <input type="text" class="form-control discount-amount text-right" placeholder="{%= 0.00 %}">
- </div>
- </div>
- </div>
- {% } %}
- <div class="pos-list-row grand-total-area collapse-btn" style="border-bottom:1px solid #d1d8dd;">
- <div class="cell">
- <a class="">
- <i class="octicon octicon-chevron-down"></i>
- </a>
- </div>
- <div class="cell text-right bold">{%= __("Grand Total") %}</div>
- <div class="cell price-cell grand-total text-right lead"></div>
- </div>
- <div class="pos-list-row qty-total-area collapse-btn" style="border-bottom:1px solid #d1d8dd;">
- <div class="cell">
- <a class="">
- <i class="octicon octicon-chevron-down"></i>
- </a>
- </div>
- <div class="cell text-right bold">{%= __("Qty Total") %}</div>
- <div class="cell price-cell qty-total text-right lead"></div>
- </div>
- </div>
- <div class="row" style="margin-top: 30px">
- <div class="col-sm-6 selected-item">
-
- </div>
- <div class="col-xs-6 numeric_keypad hidden-xs" style="display:none">
- {% var chartData = ["Qty", "Disc", "Price"] %} {% for(var i=0; i
- <3; i++) { %} <div class="row text-right">
- {% for(var j=i*3; j
- <(i+1)*3; j++) { %} <button type="button" class="btn btn-default numeric-keypad" val="{{j+1}}">{{j+1}}</button>
- {% } %}
- <button type="button" {% if((!allow_user_to_edit_rate && __(chartData[i]) == __("Price")) || (!allow_user_to_edit_discount && __(chartData[i]) == __("Disc"))) { %} disabled {% } %} id="pos-item-{{ chartData[i].toLowerCase() }}" class="btn text-center btn-default numeric-keypad pos-operation">{{ __(chartData[i]) }}</button>
- </div>
- {% } %}
- <div class="row text-right">
- <button type="button" class="btn btn-default numeric-keypad numeric-del">{{ __("Del") }}</button>
- <button type="button" class="btn btn-default numeric-keypad" val="0">0</button>
- <button type="button" class="btn btn-default numeric-keypad" val=".">.</button>
- <button type="button" class="btn btn-primary numeric-keypad pos-pay">{{ __("Pay") }}</button>
- </div>
- </div>
- </div>
- </div>
- <div class="col-sm-5 list-customers">
- <div class="col-sm-12"><h6 class="form-section-heading uppercase">{{ __("Customers in Queue") }}</h6></div>
- <div class="pos-list-row pos-bill-header">
- <div class="cell subject"><input class="list-select-all" type="checkbox">{{ __("Customer") }}</div>
- <div class="cell text-left">{{ __("Status") }}</div>
- <div class="cell text-right">{{ __("Amount") }}</div>
- <div class="cell text-right">{{ __("Grand Total") }}</div>
- </div>
- <div class="list-customers-table border-left border-right border-bottom">
- <div class="no-items-message text-extra-muted">
- <span class="text-center">
- <i class="fa fa-2x fa-user"></i>
- <p>{{ __("No Customers yet!") }}</p>
- </span>
- </div>
- </div>
- </div>
- <div class="col-sm-7 pos-items-section">
- <div class="col-sm-12"><h6 class="form-section-heading uppercase">{{ __("Stock Items") }}</h6></div>
- <div class="row pos-item-area">
-
- </div>
- <span id="customer-results" style="color:#68a;"></span>
- <div class="item-list-area">
- <div class="pos-list-row pos-bill-header text-muted h6">
- <div class="cell subject search-item-group">
- <div class="dropdown">
- <a class="text-muted dropdown-toggle" data-toggle="dropdown"><span class="dropdown-text">{{ __("All Item Groups") }}</span><i class="caret"></i></a>
- <ul class="dropdown-menu">
- </ul>
- </div>
- </div>
- <div class="cell search-item"></div>
- </div>
- <div class="app-listing item-list image-view-container">
-
- </div>
- </div>
- </div>
-</div>
diff --git a/erpnext/public/js/pos/pos_bill_item.html b/erpnext/public/js/pos/pos_bill_item.html
deleted file mode 100644
index 21868a6..0000000
--- a/erpnext/public/js/pos/pos_bill_item.html
+++ /dev/null
@@ -1,34 +0,0 @@
-<div class="row pos-bill-row pos-bill-item" data-item-code="{%= item_code %}">
- <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="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">
- {%= __("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-disc">
- </div>
- </div>
- <div class="col-xs-3 text-right">
- <div class="text-muted" style="margin-top: 5px;">
- {% if(enabled) { %}
- <input type="tel" value="{%= rate %}" class="form-control input-sm pos-item-price text-right">
- {% } else { %}
- <h6>{%= format_currency(rate) %}</h6>
- {% } %}
- </div>
- <p><h6>{%= amount %}</h6></p>
- </div>
-</div>
diff --git a/erpnext/public/js/pos/pos_bill_item_new.html b/erpnext/public/js/pos/pos_bill_item_new.html
deleted file mode 100644
index cb626ce..0000000
--- a/erpnext/public/js/pos/pos_bill_item_new.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<div class="pos-list-row pos-bill-item {{ selected_class }}" data-item-code="{{ item_code }}">
- <div class="cell subject">
- <!--<input class="list-row-checkbox" type="checkbox" data-name="{{item_code}}">-->
- <a class="grey list-id" title="{{ item_name }}">{{ strip_html(__(item_name)) || item_code }}</a>
- </div>
- <div class="cell text-right">{%= qty %}</div>
- <div class="cell text-right">{%= discount_percentage %}</div>
- <div class="cell text-right">{%= format_currency(rate) %}</div>
-</div>
diff --git a/erpnext/public/js/pos/pos_invoice_list.html b/erpnext/public/js/pos/pos_invoice_list.html
deleted file mode 100644
index 13aa520..0000000
--- a/erpnext/public/js/pos/pos_invoice_list.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<div class="pos-list-row" invoice-name = "{{name}}">
- <div class="list-column cell subject" invoice-name = "{{name}}">
- <input class="list-delete text-left" type="checkbox" style = "margin-right:5px">
- <a class="grey list-id text-left customer-row" title="{{ customer }}">{%= customer %}</a>
- </div>
- <div class="list-column cell text-left customer-row"><span class="indicator {{data.indicator}}">{{ data.status }}</span></div>
- <div class="list-column cell text-right customer-row">{%= paid_amount %}</div>
- <div class="list-column cell text-right customer-row">{%= grand_total %}</div>
-</div>
diff --git a/erpnext/public/js/pos/pos_item.html b/erpnext/public/js/pos/pos_item.html
deleted file mode 100755
index 52f3cf6..0000000
--- a/erpnext/public/js/pos/pos_item.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<div class="pos-item-wrapper image-view-item" data-item-code="{{item_code}}">
- <div class="image-view-header doclist-row">
- <div class="list-value">
- <a class="grey list-id" data-name="{{item_code}}" title="{{ item_name || item_code}}">{{item_name || item_code}}<br>({{ __(item_stock) }})</a>
- </div>
- </div>
- <div class="image-view-body">
- <a data-item-code="{{ item_code }}"
- title="{{ item_name || item_code }}"
- >
- <div class="image-field"
- style="
- {% if (!item_image) { %}
- background-color: #fafbfc;
- {% } %}
- border: 0px;"
- >
- {% if (!item_image) { %}
- <span class="placeholder-text">
- {%= frappe.get_abbr(item_name || item_code) %}
- </span>
- {% } %}
- {% if (item_image) { %}
- <img src="{{ item_image }}" alt="{{item_name || item_code}}">
- {% } %}
- </div>
- <span class="price-info">
- {{item_price}} / {{item_uom}}
- </span>
- </a>
- </div>
-</div>
\ No newline at end of file
diff --git a/erpnext/public/js/pos/pos_selected_item.html b/erpnext/public/js/pos/pos_selected_item.html
deleted file mode 100644
index 03c7341..0000000
--- a/erpnext/public/js/pos/pos_selected_item.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<div class="pos-selected-item-action" data-item-code="{%= item_code %}" data-idx="{%= idx %}">
- <div class="pos-list-row">
- <div class="cell">{{ __("Quantity") }}:</div>
- <input type="tel" class="form-control cell pos-item-qty" value="{%= qty %}"/>
- </div>
- <div class="pos-list-row">
- <div class="cell">{{ __("Price List Rate") }}:</div>
- <input type="tel" class="form-control cell" disabled value="{%= price_list_rate %}"/>
- </div>
- <div class="pos-list-row">
- <div class="cell">{{ __("Discount") }}: %</div>
- <input type="tel" class="form-control cell pos-item-disc" {% if !allow_user_to_edit_discount %} disabled {% endif %} value="{%= discount_percentage %}">
- </div>
- <div class="pos-list-row">
- <div class="cell">{{ __("Price") }}:</div>
- <input type="tel" class="form-control cell pos-item-price" {% if !allow_user_to_edit_rate %} disabled {% endif %} value="{%= rate %}"/>
- </div>
- <div class="pos-list-row">
- <div class="cell">{{ __("Amount") }}:</div>
- <input type="tel" class="form-control cell pos-amount" disabled value="{%= amount %}"/>
- </div>
-</div>
\ No newline at end of file
diff --git a/erpnext/public/js/pos/pos_tax_row.html b/erpnext/public/js/pos/pos_tax_row.html
deleted file mode 100644
index 3752a89..0000000
--- a/erpnext/public/js/pos/pos_tax_row.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<div class="pos-list-row" style="padding-right: 0;">
- <div class="cell">{%= description %}</div>
- <div class="cell text-right bold">{%= tax_amount %}</div>
-</div>
diff --git a/erpnext/public/scss/point-of-sale.scss b/erpnext/public/scss/point-of-sale.scss
new file mode 100644
index 0000000..f388093
--- /dev/null
+++ b/erpnext/public/scss/point-of-sale.scss
@@ -0,0 +1,1112 @@
+.point-of-sale-app {
+ display: grid;
+ grid-template-columns: repeat(10, minmax(0, 1fr));
+ gap: var(--margin-md);
+
+ section {
+ min-height: 45rem;
+ height: calc(100vh - 200px);
+ max-height: calc(100vh - 200px);
+ }
+
+ .frappe-control {
+ margin: 0 !important;
+ width: 100%;
+ }
+
+ .form-group {
+ margin-bottom: 0px !important;
+ }
+
+ .pointer-no-select {
+ cursor: pointer;
+ user-select: none;
+ }
+
+ .nowrap {
+ overflow: hidden;
+ white-space: nowrap;
+ }
+
+ .image {
+ height: 100% !important;
+ object-fit: cover;
+ }
+
+ .abbr {
+ background-color: var(--gray-50);
+ font-size: var(--text-3xl);
+ }
+
+ .label {
+ display: flex;
+ align-items: center;
+ font-weight: 700;
+ font-size: var(--text-lg);
+ }
+
+ .pos-card {
+ background-color: var(--fg-color);
+ box-shadow: var(--shadow-base);
+ border-radius: var(--border-radius-md);
+ }
+
+ .seperator {
+ margin-left: var(--margin-sm);
+ margin-right: var(--margin-sm);
+ border-bottom: 1px solid var(--gray-300);
+ }
+
+ .primary-action {
+ @extend .pointer-no-select;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: var(--padding-sm);
+ margin-top: var(--margin-sm);
+ border-radius: var(--border-radius-md);
+ font-size: var(--text-lg);
+ font-weight: 700;
+ }
+
+ .highlighted-numpad-btn {
+ box-shadow: inset 0 0px 4px 0px rgba(0, 0, 0, 0.15) !important;
+ font-weight: 700;
+ background-color: var(--gray-50);
+ }
+
+ .sticky-element {
+ position: sticky;
+ top: -1px;
+ z-index: 1;
+ }
+
+ > .items-selector {
+ @extend .pos-card;
+ grid-column: span 6 / span 6;
+ display: flex;
+ flex-direction: column;
+ overflow-y: scroll;
+ overflow-x: hidden;
+
+ > .filter-section {
+ @extend .sticky-element;
+ display: grid;
+ grid-template-columns: repeat(12, minmax(0, 1fr));
+ background-color: var(--fg-color);
+ padding: var(--padding-lg);
+ padding-bottom: var(--padding-sm);
+ align-items: center;
+
+ > .label {
+ @extend .label;
+ grid-column: span 4 / span 4;
+ padding-bottom: var(--padding-xs);
+ }
+
+ > .search-field {
+ grid-column: span 5 / span 5;
+ display: flex;
+ align-items: center;
+ margin: 0px var(--margin-sm);
+ }
+
+ > .item-group-field {
+ grid-column: span 3 / span 3;
+ display: flex;
+ align-items: center;
+ }
+ }
+
+ > .items-container {
+ display: grid;
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ gap: var(--margin-lg);
+ padding: var(--padding-lg);
+ padding-top: var(--padding-xs);
+
+ > .item-wrapper {
+ @extend .pointer-no-select;
+ border-radius: var(--border-radius-md);
+ box-shadow: var(--shadow-base);
+
+ &:hover {
+ transform: scale(1.02, 1.02);
+ }
+
+ .item-display {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: var(--border-radius-md);
+ margin: var(--margin-sm);
+ margin-bottom: 0px;
+ min-height: 8rem;
+ height: 8rem;
+ color: var(--gray-500);
+
+ > img {
+ @extend .image;
+ }
+ }
+
+ > .item-detail {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ min-height: 3.5rem;
+ height: 3.5rem;
+ padding-left: var(--padding-sm);
+ padding-right: var(--padding-sm);
+
+ > .item-name {
+ @extend .nowrap;
+ display: flex;
+ align-items: center;
+ font-size: var(--text-md);
+ }
+
+ > .item-rate {
+ font-weight: 700;
+ }
+ }
+
+ }
+ }
+ }
+
+ > .customer-cart-container {
+ grid-column: span 4 / span 4;
+ display: flex;
+ flex-direction: column;
+
+ > .customer-section {
+ @extend .pos-card;
+ display: flex;
+ flex-direction: column;
+ padding: var(--padding-md) var(--padding-lg);
+
+ > .customer-field {
+ display: flex;
+ align-items: center;
+ padding-top: var(--padding-xs);
+ }
+
+ > .customer-details {
+ @extend .sticky-element;
+ display: flex;
+ flex-direction: column;
+ background-color: var(--fg-color);
+
+ > .header {
+ display: flex;
+ margin-bottom: var(--margin-md);
+ justify-content: space-between;
+ padding-top: var(--padding-md);
+
+ > .label {
+ @extend .label;
+ }
+
+ > .close-details-btn {
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+ }
+ }
+
+ > .customer-display {
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+
+ > .customer-image {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 3rem;
+ height: 3rem;
+ border-radius: 50%;
+ color: var(--gray-500);
+ margin-right: var(--margin-md);
+
+ > img {
+ @extend .image;
+ border-radius: 50%;
+ }
+ }
+
+ > .customer-abbr {
+ @extend .abbr;
+ font-size: var(--text-2xl);
+ }
+
+ > .customer-name-desc {
+ @extend .nowrap;
+ display: flex;
+ flex-direction: column;
+ margin-right: auto;
+
+ >.customer-name {
+ font-weight: 700;
+ font-size: var(--text-lg);
+ }
+
+ >.customer-desc {
+ color: var(--gray-600);
+ font-weight: 500;
+ font-size: var(--text-sm);
+ }
+ }
+
+ > .reset-customer-btn {
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+ }
+
+ }
+
+ > .customer-fields-container {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ margin-top: var(--margin-md);
+ column-gap: var(--padding-sm);
+ row-gap: var(--padding-xs);
+ }
+
+ > .transactions-label {
+ @extend .label;
+ margin-top: var(--margin-md);
+ margin-bottom: var(--margin-sm);
+ }
+ }
+
+ > .customer-transactions {
+ height: 100%;
+
+ > .no-transactions-placeholder {
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: var(--gray-50);
+ border-radius: var(--border-radius-md);
+ }
+ }
+ }
+
+ > .cart-container {
+ @extend .pos-card;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin-top: var(--margin-md);
+ position: relative;
+ height: 100%;
+
+ > .abs-cart-container {
+ position: absolute;
+ display: flex;
+ flex-direction: column;
+ padding: var(--padding-lg);
+ width: 100%;
+ height: 100%;
+
+ > .cart-label {
+ @extend .label;
+ padding-bottom: var(--padding-md);
+ }
+
+ > .cart-header {
+ display: flex;
+ width: 100%;
+ font-size: var(--text-md);
+ padding-bottom: var(--padding-md);
+
+ > .name-header {
+ flex: 1 1 0%;
+ }
+
+ > .qty-header {
+ margin-right: var(--margin-lg);
+ text-align: center;
+ }
+
+ > .rate-amount-header {
+ text-align: right;
+ margin-right: var(--margin-sm);
+ }
+ }
+
+ .no-item-wrapper {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: var(--gray-50);
+ border-radius: var(--border-radius-md);
+ font-size: var(--text-md);
+ font-weight: 500;
+ width: 100%;
+ height: 100%;
+ }
+
+ > .cart-items-section {
+ display: flex;
+ flex-direction: column;
+ flex: 1 1 0%;
+ overflow-y: scroll;
+
+ > .cart-item-wrapper {
+ @extend .pointer-no-select;
+ display: flex;
+ align-items: center;
+ padding: var(--padding-sm);
+ border-radius: var(--border-radius-md);
+
+ &:hover {
+ background-color: var(--gray-50);
+ }
+
+ > .item-image {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 2rem;
+ height: 2rem;
+ border-radius: var(--border-radius-md);
+ color: var(--gray-500);
+ margin-right: var(--margin-md);
+
+ > img {
+ @extend .image;
+ }
+ }
+
+ > .item-abbr {
+ @extend .abbr;
+ font-size: var(--text-lg);
+ }
+
+
+ > .item-name-desc {
+ @extend .nowrap;
+ display: flex;
+ flex-direction: column;
+ flex: 1 1 0%;
+ flex-shrink: 1;
+
+ > .item-name {
+ font-weight: 700;
+ }
+
+ > .item-desc {
+ font-size: var(--text-sm);
+ color: var(--gray-600);
+ font-weight: 500;
+ }
+ }
+
+ > .item-qty-rate {
+ display: flex;
+ flex-shrink: 0;
+ text-align: right;
+ margin-left: var(--margin-md);
+
+ > .item-qty {
+ display: flex;
+ align-items: center;
+ margin-right: var(--margin-lg);
+ font-weight: 700;
+ }
+
+ > .item-rate-amount {
+ display: flex;
+ flex-direction: column;
+ flex-shrink: 0;
+ text-align: right;
+
+ > .item-rate {
+ font-weight: 700;
+ }
+
+ > .item-amount {
+ font-size: var(--text-md);
+ font-weight: 600;
+ }
+ }
+ }
+
+ }
+ }
+
+ > .cart-totals-section {
+ display: flex;
+ flex-direction: column;
+ flex-shrink: 0;
+ width: 100%;
+ margin-top: var(--margin-md);
+
+ > .add-discount-wrapper {
+ @extend .pointer-no-select;
+ display: none;
+ align-items: center;
+ border-radius: var(--border-radius-md);
+ border: 1px dashed var(--gray-500);
+ padding: var(--padding-sm) var(--padding-md);
+ margin-bottom: var(--margin-sm);
+
+ > .add-discount-field {
+ width: 100%;
+ }
+
+ .discount-icon {
+ margin-right: var(--margin-sm);
+ }
+
+ .edit-discount-btn {
+ display: flex;
+ align-items: center;
+ font-weight: 500;
+ color: var(--dark-green-500);
+ }
+ }
+
+ > .net-total-container {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: var(--padding-sm) 0px;
+ font-weight: 500;
+ font-size: var(--text-md);
+ }
+
+ > .taxes-container {
+ display: none;
+ flex-direction: column;
+ font-weight: 500;
+ font-size: var(--text-md);
+
+ > .tax-row {
+ display: flex;
+ justify-content: space-between;
+ line-height: var(--text-3xl);
+ }
+ }
+
+ > .grand-total-container {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: var(--padding-sm) 0px;
+ font-weight: 700;
+ font-size: var(--text-lg);
+ }
+
+ > .checkout-btn {
+ @extend .primary-action;
+ background-color: var(--blue-200);
+ color: white;
+ }
+
+ > .edit-cart-btn {
+ @extend .primary-action;
+ display: none;
+ background-color: var(--gray-300);
+ font-weight: 500;
+ transition: all 0.15s ease-in-out;
+
+ &:hover {
+ background-color: var(--gray-600);
+ color: white;
+ font-weight: 700;
+ }
+ }
+ }
+
+ > .numpad-section {
+ display: none;
+ flex-direction: column;
+ flex-shrink: 0;
+ margin-top: var(--margin-sm);
+ padding: var(--padding-sm);
+ padding-bottom: 0px;
+ width: 100%;
+
+ > .numpad-totals {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: var(--margin-md);
+ font-size: var(--text-md);
+ font-weight: 700;
+ }
+
+ > .numpad-container {
+ display: grid;
+ grid-template-columns: repeat(5, minmax(0, 1fr));
+ gap: var(--margin-md);
+ margin-bottom: var(--margin-md);
+
+ > .numpad-btn {
+ @extend .pointer-no-select;
+ border-radius: var(--border-radius-md);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: var(--padding-md);
+ box-shadow: var(--shadow-sm);
+ }
+
+ > .col-span-2 {
+ grid-column: span 2 / span 2;
+ }
+
+ > .remove-btn {
+ font-weight: 700;
+ color: var(--red-500);
+ }
+ }
+
+ > .checkout-btn {
+ @extend .primary-action;
+ margin: 0px;
+ margin-bottom: var(--margin-sm);
+ background-color: var(--blue-200);
+ color: white;
+ }
+ }
+ }
+ }
+ }
+
+ .invoice-wrapper {
+ @extend .pointer-no-select;
+ display: flex;
+ justify-content: space-between;
+ border-radius: var(--border-radius-md);
+ padding: var(--padding-sm);
+
+ &:hover {
+ background-color: var(--gray-50);
+ }
+
+ > .invoice-name-date {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-around;
+
+ > .invoice-name {
+ @extend .nowrap;
+ font-size: var(--text-md);
+ font-weight: 700;
+ }
+
+ > .invoice-date {
+ @extend .nowrap;
+ font-size: var(--text-sm);
+ display: flex;
+ align-items: center;
+ }
+ }
+
+ > .invoice-total-status {
+ display: flex;
+ flex-direction: column;
+ font-weight: 500;
+ font-size: var(--text-sm);
+ margin-left: var(--margin-md);
+
+ > .invoice-total {
+ margin-bottom: var(--margin-xs);
+ font-size: var(--text-base);
+ font-weight: 700;
+ text-align: right;
+ }
+
+ > .invoice-status {
+ display: flex;
+ align-items: center;
+ justify-content: right;
+ }
+ }
+ }
+
+ > .item-details-container {
+ @extend .pos-card;
+ grid-column: span 4 / span 4;
+ display: none;
+ flex-direction: column;
+ padding: var(--padding-lg);
+ padding-top: var(--padding-md);
+
+ > .item-details-header {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: var(--margin-md);
+
+ > .close-btn {
+ @extend .pointer-no-select;
+ }
+ }
+
+ > .item-display {
+ display: flex;
+
+ > .item-name-desc-price {
+ flex: 1 1 0%;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-end;
+ margin-right: var(--margin-md);
+
+ > .item-name {
+ font-size: var(--text-3xl);
+ font-weight: 600;
+ }
+
+ > .item-desc {
+ font-size: var(--text-md);
+ font-weight: 500;
+ }
+
+ > .item-price {
+ font-size: var(--text-3xl);
+ font-weight: 700;
+ }
+ }
+
+ > .item-image {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 11rem;
+ height: 11rem;
+ border-radius: var(--border-radius-md);
+ margin-left: var(--margin-md);
+ color: var(--gray-500);
+
+ > img {
+ @extend .image;
+ }
+
+ > .item-abbr {
+ @extend .abbr;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: var(--border-radius-md);
+ font-size: var(--text-3xl);
+ width: 100%;
+ height: 100%;
+ }
+ }
+ }
+
+ > .discount-section {
+ display: flex;
+ align-items: center;
+ margin-bottom: var(--margin-sm);
+
+ > .item-rate {
+ font-weight: 500;
+ margin-right: var(--margin-sm);
+ text-decoration: line-through;
+ }
+
+ > .item-discount {
+ padding: 3px var(--padding-sm);
+ border-radius: var(--border-radius-sm);
+ background-color: var(--green-100);
+ color: var(--dark-green-500);
+ font-size: var(--text-sm);
+ font-weight: 700;
+ }
+ }
+
+ > .form-container {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ column-gap: var(--padding-md);
+
+ > .auto-fetch-btn {
+ @extend .pointer-no-select;
+ margin: var(--margin-xs);
+ }
+ }
+ }
+
+ > .payment-container {
+ @extend .pos-card;
+ grid-column: span 6 / span 6;
+ display: none;
+ flex-direction: column;
+ padding: var(--padding-lg);
+
+ .border-primary {
+ border: 1px solid var(--blue-500);
+ }
+
+ .submit-order-btn {
+ @extend .primary-action;
+ background-color: var(--blue-500);
+ color: white;
+ }
+
+ .section-label {
+ @extend .label;
+ @extend .pointer-no-select;
+ margin-bottom: var(--margin-md);
+ }
+
+ > .payment-modes {
+ display: flex;
+ padding-bottom: var(--padding-sm);
+ margin-bottom: var(--margin-xs);
+ overflow-x: scroll;
+ overflow-y: hidden;
+
+ > .payment-mode-wrapper {
+ min-width: 40%;
+ padding: var(--padding-xs);
+
+ > .mode-of-payment {
+ @extend .pos-card;
+ @extend .pointer-no-select;
+ padding: var(--padding-md) var(--padding-lg);
+
+ > .pay-amount {
+ display: inline;
+ float: right;
+ font-weight: 700;
+ }
+
+ > .mode-of-payment-control {
+ display: none;
+ align-items: center;
+ margin-top: var(--margin-sm);
+ margin-bottom: var(--margin-xs);
+ }
+
+ > .loyalty-amount-name {
+ display: none;
+ float: right;
+ font-weight: 700;
+ }
+
+ > .cash-shortcuts {
+ display: none;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ gap: var(--margin-sm);
+ font-size: var(--text-sm);
+ text-align: center;
+
+ > .shortcut {
+ @extend .pointer-no-select;
+ border-radius: var(--border-radius-sm);
+ background-color: var(--gray-100);
+ font-weight: 500;
+ padding: var(--padding-xs) var(--padding-sm);
+ transition: all 0.15s ease-in-out;
+
+ &:hover {
+ background-color: var(--gray-300);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ > .fields-numpad-container {
+ display: flex;
+ flex: 1;
+
+ > .fields-section {
+ flex: 1;
+ }
+
+ > .number-pad {
+ flex: 1;
+ display: flex;
+ justify-content: flex-end;
+ align-items: flex-end;
+
+ .numpad-container {
+ display: grid;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ gap: var(--margin-md);
+ margin-bottom: var(--margin-md);
+
+ > .numpad-btn {
+ @extend .pointer-no-select;
+ border-radius: var(--border-radius-md);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: var(--padding-md);
+ box-shadow: var(--shadow-sm);
+ }
+ }
+ }
+ }
+
+ > .totals-section {
+ display: flex;
+ margin-top: auto;
+ margin-bottom: var(--margin-sm);
+ justify-content: center;
+ flex-direction: column;
+
+ > .totals {
+ display: flex;
+ padding-top: var(--padding-md);
+ background-color: var(--gray-100);
+ justify-content: center;
+ padding: var(--padding-md);
+ border-radius: var(--border-radius-md);
+
+ > .col {
+ flex-grow: 1;
+ text-align: center;
+
+ > .total-label {
+ font-size: var(--text-md);
+ font-weight: 500;
+ color: var(--gray-600);
+ }
+
+ > .value {
+ font-size: var(--text-2xl);
+ font-weight: 700;
+ }
+ }
+
+ > .seperator-y {
+ margin-left: var(--margin-sm);
+ margin-right: var(--margin-sm);
+ border-right: 1px solid var(--gray-300);
+ }
+ }
+
+ > .number-pad {
+ display: none;
+ }
+ }
+ }
+
+ > .past-order-list {
+ @extend .pos-card;
+ grid-column: span 4 / span 4;
+ display: none;
+ flex-direction: column;
+ overflow-y: scroll;
+ overflow-x: hidden;
+
+ > .filter-section {
+ @extend .sticky-element;
+ display: flex;
+ flex-direction: column;
+ background-color: var(--fg-color);
+ padding: var(--padding-lg);
+
+ > .search-field {
+ width: 100%;
+ display: flex;
+ align-items: center;
+ margin-top: var(--margin-md);
+ margin-bottom: var(--margin-xs);
+ }
+
+ > .status-field {
+ width: 100%;
+ display: flex;
+ align-items: center;
+ }
+ }
+
+ > .invoices-container {
+ padding: var(--padding-lg);
+ padding-top: 0px;
+ }
+ }
+
+ > .past-order-summary {
+ // @extend .pos-card;
+ display: none;
+ grid-column: span 6 / span 6;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ // padding: var(--padding-lg);
+
+ > .no-summary-placeholder {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ background-color: var(--gray-50);
+ font-weight: 500;
+ border-radius: var(--border-radius-md);
+ }
+
+ > .invoice-summary-wrapper {
+ @extend .pos-card;
+ display: none;
+ position: relative;
+ width: 31rem;
+ height: 100%;
+
+ > .abs-container {
+ position: absolute;
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ height: 100%;
+ padding: var(--padding-lg);
+
+ > .upper-section {
+ display: flex;
+ justify-content: space-between;
+ width: 100%;
+ margin-bottom: var(--margin-md);
+
+ > .left-section {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: flex-end;
+ padding-right: var(--padding-sm);
+
+ > .customer-name {
+ font-size: var(--text-2xl);
+ font-weight: 700;
+ }
+
+ > .customer-email {
+ font-size: var(--text-md);
+ font-weight: 500;
+ color: var(--gray-600);
+ }
+
+ > .cashier {
+ font-size: var(--text-md);
+ font-weight: 500;
+ color: var(--gray-600);
+ margin-top: auto;
+ }
+ }
+
+ > .right-section {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ justify-content: space-between;
+
+ > .paid-amount {
+ font-size: var(--text-2xl);
+ font-weight: 700;
+ }
+
+ > .invoice-name {
+ font-size: var(--text-md);
+ font-weight: 500;
+ color: var(--gray-600);
+ margin-bottom: var(--margin-sm);
+ }
+ }
+ }
+
+ > .summary-container {
+ display: flex;
+ flex-direction: column;
+ border-radius: var(--border-radius-md);
+ background-color: var(--gray-50);
+ margin: var(--margin-md) 0px;
+
+ > .summary-row-wrapper {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: var(--padding-sm) var(--padding-md);
+ // border-bottom: 1px solid var(--gray-300);
+ }
+
+ > .taxes-wrapper {
+ display: flex;
+ flex-direction: column;
+ padding: 0px var(--padding-md);
+ // border-bottom: 1px solid var(--gray-300);
+
+ > .tax-row {
+ display: flex;
+ justify-content: space-between;
+ font-size: var(--text-md);
+ line-height: var(--text-3xl);
+ }
+ }
+
+ > .item-row-wrapper {
+ display: flex;
+ align-items: center;
+ padding: var(--padding-sm) var(--padding-md);
+ // border-bottom: 1px solid var(--gray-300);
+
+ > .item-name {
+ @extend .nowrap;
+ font-weight: 500;
+ margin-right: var(--margin-md);
+ }
+
+ > .item-qty {
+ font-weight: 500;
+ margin-left: auto;
+ }
+
+ > .item-rate-disc {
+ display: flex;
+ text-align: right;
+ margin-left: var(--margin-md);
+
+ > .item-disc {
+ color: var(--dark-green-500);
+ }
+
+ > .item-rate {
+ font-weight: 500;
+ margin-left: var(--margin-md);
+ }
+ }
+ }
+
+ > .grand-total {
+ // font-size: var(--text-lg);
+ font-weight: 700;
+ // padding: var(--padding-md);
+ }
+
+ > .payments {
+ font-weight: 700;
+ }
+ }
+
+
+ > .summary-btns {
+ display: flex;
+ justify-content: space-between;
+
+ > .summary-btn {
+ flex: 1;
+ margin: 0px var(--margin-xs);
+ }
+
+ > .new-btn {
+ background-color: var(--blue-500);
+ color:white;
+ font-weight: 500;
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 73cc0b8..96d265c 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -328,7 +328,7 @@
frappe.msgprint({
message: __('Work Orders Created: {0}',
[r.message.map(function(d) {
- return repl('<a href="#Form/Work Order/%(name)s">%(name)s</a>', {name:d})
+ return repl('<a href="/desk/Form/Work Order/%(name)s">%(name)s</a>', {name:d})
}).join(', ')]),
indicator: 'green'
})
@@ -437,7 +437,7 @@
callback: function(r) {
if(r.message) {
frappe.msgprint(__('Material Request {0} submitted.',
- ['<a href="#Form/Material Request/'+r.message.name+'">' + r.message.name+ '</a>']));
+ ['<a href="/desk/Form/Material Request/'+r.message.name+'">' + r.message.name+ '</a>']));
}
d.hide();
me.frm.reload_doc();
diff --git a/erpnext/selling/page/point_of_sale/onscan.js b/erpnext/selling/page/point_of_sale/onscan.js
deleted file mode 100644
index 428dc75..0000000
--- a/erpnext/selling/page/point_of_sale/onscan.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t()):e.onScan=t()}(this,function(){var d={attachTo:function(e,t){if(void 0!==e.scannerDetectionData)throw new Error("onScan.js is already initialized for DOM element "+e);var n={onScan:function(e,t){},onScanError:function(e){},onKeyProcess:function(e,t){},onKeyDetect:function(e,t){},onPaste:function(e,t){},keyCodeMapper:function(e){return d.decodeKeyEvent(e)},onScanButtonLongPress:function(){},scanButtonKeyCode:!1,scanButtonLongPressTime:500,timeBeforeScanTest:100,avgTimeByChar:30,minLength:6,suffixKeyCodes:[9,13],prefixKeyCodes:[],ignoreIfFocusOn:!1,stopPropagation:!1,preventDefault:!1,captureEvents:!1,reactToKeydown:!0,reactToPaste:!1,singleScanQty:1};return t=this._mergeOptions(n,t),e.scannerDetectionData={options:t,vars:{firstCharTime:0,lastCharTime:0,accumulatedString:"",testTimer:!1,longPressTimeStart:0,longPressed:!1}},!0===t.reactToPaste&&e.addEventListener("paste",this._handlePaste,t.captureEvents),!1!==t.scanButtonKeyCode&&e.addEventListener("keyup",this._handleKeyUp,t.captureEvents),!0!==t.reactToKeydown&&!1===t.scanButtonKeyCode||e.addEventListener("keydown",this._handleKeyDown,t.captureEvents),this},detachFrom:function(e){e.scannerDetectionData.options.reactToPaste&&e.removeEventListener("paste",this._handlePaste),!1!==e.scannerDetectionData.options.scanButtonKeyCode&&e.removeEventListener("keyup",this._handleKeyUp),e.removeEventListener("keydown",this._handleKeyDown),e.scannerDetectionData=void 0},getOptions:function(e){return e.scannerDetectionData.options},setOptions:function(e,t){switch(e.scannerDetectionData.options.reactToPaste){case!0:!1===t.reactToPaste&&e.removeEventListener("paste",this._handlePaste);break;case!1:!0===t.reactToPaste&&e.addEventListener("paste",this._handlePaste)}switch(e.scannerDetectionData.options.scanButtonKeyCode){case!1:!1!==t.scanButtonKeyCode&&e.addEventListener("keyup",this._handleKeyUp);break;default:!1===t.scanButtonKeyCode&&e.removeEventListener("keyup",this._handleKeyUp)}return e.scannerDetectionData.options=this._mergeOptions(e.scannerDetectionData.options,t),this._reinitialize(e),this},decodeKeyEvent:function(e){var t=this._getNormalizedKeyNum(e);switch(!0){case 48<=t&&t<=90:case 106<=t&&t<=111:if(void 0!==e.key&&""!==e.key)return e.key;var n=String.fromCharCode(t);switch(e.shiftKey){case!1:n=n.toLowerCase();break;case!0:n=n.toUpperCase()}return n;case 96<=t&&t<=105:return t-96}return""},simulate:function(e,t){return this._reinitialize(e),Array.isArray(t)?t.forEach(function(e){var t={};"object"!=typeof e&&"function"!=typeof e||null===e?t.keyCode=parseInt(e):t=e;var n=new KeyboardEvent("keydown",t);document.dispatchEvent(n)}):this._validateScanCode(e,t),this},_reinitialize:function(e){var t=e.scannerDetectionData.vars;t.firstCharTime=0,t.lastCharTime=0,t.accumulatedString=""},_isFocusOnIgnoredElement:function(e){var t=e.scannerDetectionData.options.ignoreIfFocusOn;if(!t)return!1;var n=document.activeElement;if(Array.isArray(t)){for(var a=0;a<t.length;a++)if(!0===n.matches(t[a]))return!0}else if(n.matches(t))return!0;return!1},_validateScanCode:function(e,t){var n,a=e.scannerDetectionData,i=a.options,o=a.options.singleScanQty,r=a.vars.firstCharTime,s=a.vars.lastCharTime,c={};switch(!0){case t.length<i.minLength:c={message:"Receieved code is shorter then minimal length"};break;case s-r>t.length*i.avgTimeByChar:c={message:"Receieved code was not entered in time"};break;default:return i.onScan.call(e,t,o),n=new CustomEvent("scan",{detail:{scanCode:t,qty:o}}),e.dispatchEvent(n),d._reinitialize(e),!0}return c.scanCode=t,c.scanDuration=s-r,c.avgTimeByChar=i.avgTimeByChar,c.minLength=i.minLength,i.onScanError.call(e,c),n=new CustomEvent("scanError",{detail:c}),e.dispatchEvent(n),d._reinitialize(e),!1},_mergeOptions:function(e,t){var n,a={};for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&(a[n]=e[n]);for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(a[n]=t[n]);return a},_getNormalizedKeyNum:function(e){return e.which||e.keyCode},_handleKeyDown:function(e){var t=d._getNormalizedKeyNum(e),n=this.scannerDetectionData.options,a=this.scannerDetectionData.vars,i=!1;if(!1!==n.onKeyDetect.call(this,t,e)&&!d._isFocusOnIgnoredElement(this))if(!1===n.scanButtonKeyCode||t!=n.scanButtonKeyCode){switch(!0){case a.firstCharTime&&-1!==n.suffixKeyCodes.indexOf(t):e.preventDefault(),e.stopImmediatePropagation(),i=!0;break;case!a.firstCharTime&&-1!==n.prefixKeyCodes.indexOf(t):e.preventDefault(),e.stopImmediatePropagation(),i=!1;break;default:var o=n.keyCodeMapper.call(this,e);if(null===o)return;a.accumulatedString+=o,n.preventDefault&&e.preventDefault(),n.stopPropagation&&e.stopImmediatePropagation(),i=!1}a.firstCharTime||(a.firstCharTime=Date.now()),a.lastCharTime=Date.now(),a.testTimer&&clearTimeout(a.testTimer),i?(d._validateScanCode(this,a.accumulatedString),a.testTimer=!1):a.testTimer=setTimeout(d._validateScanCode,n.timeBeforeScanTest,this,a.accumulatedString),n.onKeyProcess.call(this,o,e)}else a.longPressed||(a.longPressTimer=setTimeout(n.onScanButtonLongPress,n.scanButtonLongPressTime,this),a.longPressed=!0)},_handlePaste:function(e){if(!d._isFocusOnIgnoredElement(this)){e.preventDefault(),oOptions.stopPropagation&&e.stopImmediatePropagation();var t=(event.clipboardData||window.clipboardData).getData("text");this.scannerDetectionData.options.onPaste.call(this,t,event);var n=this.scannerDetectionData.vars;n.firstCharTime=0,n.lastCharTime=0,d._validateScanCode(this,t)}},_handleKeyUp:function(e){d._isFocusOnIgnoredElement(this)||d._getNormalizedKeyNum(e)==this.scannerDetectionData.options.scanButtonKeyCode&&(clearTimeout(this.scannerDetectionData.vars.longPressTimer),this.scannerDetectionData.vars.longPressed=!1)},isScanInProgressFor:function(e){return 0<e.scannerDetectionData.vars.firstCharTime}};return d});
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js
index 9d44a9f..6d8ad7e 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.js
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.js
@@ -1,7 +1,4 @@
-/* global Clusterize */
frappe.provide('erpnext.PointOfSale');
-{% include "erpnext/selling/page/point_of_sale/pos_controller.js" %}
-frappe.provide('erpnext.queries');
frappe.pages['point-of-sale'].on_page_load = function(wrapper) {
frappe.ui.make_app_page({
@@ -10,8 +7,10 @@
single_column: true
});
- wrapper.pos = new erpnext.PointOfSale.Controller(wrapper);
- window.cur_pos = wrapper.pos;
+ frappe.require('assets/js/point-of-sale.min.js', function() {
+ wrapper.pos = new erpnext.PointOfSale.Controller(wrapper);
+ window.cur_pos = wrapper.pos;
+ })
};
frappe.pages['point-of-sale'].refresh = function(wrapper) {
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
index 970d840..155d35d 100644
--- a/erpnext/selling/page/point_of_sale/pos_controller.js
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -1,23 +1,9 @@
-{% include "erpnext/selling/page/point_of_sale/onscan.js" %}
-{% include "erpnext/selling/page/point_of_sale/pos_item_selector.js" %}
-{% include "erpnext/selling/page/point_of_sale/pos_item_cart.js" %}
-{% include "erpnext/selling/page/point_of_sale/pos_item_details.js" %}
-{% include "erpnext/selling/page/point_of_sale/pos_payment.js" %}
-{% include "erpnext/selling/page/point_of_sale/pos_number_pad.js" %}
-{% include "erpnext/selling/page/point_of_sale/pos_past_order_list.js" %}
-{% include "erpnext/selling/page/point_of_sale/pos_past_order_summary.js" %}
-
erpnext.PointOfSale.Controller = class {
constructor(wrapper) {
this.wrapper = $(wrapper).find('.layout-main-section');
this.page = wrapper.page;
- this.load_assets();
- }
-
- load_assets() {
- // after loading assets first check if opening entry has been made
- frappe.require(['assets/erpnext/css/pos.css'], this.check_opening_entry.bind(this));
+ this.check_opening_entry();
}
fetch_opening_entry() {
@@ -36,6 +22,7 @@
}
create_opening_voucher() {
+ const me = this;
const table_fields = [
{
fieldname: "mode_of_payment", fieldtype: "Link",
@@ -45,7 +32,7 @@
{
fieldname: "opening_amount", fieldtype: "Currency",
in_list_view: 1, label: "Opening Amount",
- options: "company:company_currency",
+ options: "company:company_currency",
change: function () {
dialog.fields_dict.balance_details.df.data.some(d => {
if (d.idx == this.doc.idx) {
@@ -93,7 +80,7 @@
fields: table_fields
}
],
- primary_action: async ({ company, pos_profile, balance_details }) => {
+ primary_action: async function({ company, pos_profile, balance_details }) {
if (!balance_details.length) {
frappe.show_alert({
message: __("Please add Mode of payments and opening balance details."),
@@ -103,7 +90,7 @@
}
const method = "erpnext.selling.page.point_of_sale.point_of_sale.create_opening_voucher";
const res = await frappe.call({ method, args: { pos_profile, company, balance_details }, freeze:true });
- !res.exc && this.prepare_app_defaults(res.message);
+ !res.exc && me.prepare_app_defaults(res.message);
dialog.hide();
},
primary_action_label: __('Submit')
@@ -134,7 +121,7 @@
set_opening_entry_status() {
this.page.set_title_sub(
`<span class="indicator orange">
- <a class="text-muted" href="#Form/POS%20Opening%20Entry/${this.pos_opening}">
+ <a class="text-muted" href="/desk/Form/POS%20Opening%20Entry/${this.pos_opening}">
Opened at ${moment(this.pos_opening_time).format("Do MMMM, h:mma")}
</a>
</span>`);
@@ -157,10 +144,10 @@
prepare_dom() {
this.wrapper.append(
- `<div class="app grid grid-cols-10 pt-8 gap-6"></div>`
+ `<div class="point-of-sale-app"></div>`
);
- this.$components_wrapper = this.wrapper.find('.app');
+ this.$components_wrapper = this.wrapper.find('.point-of-sale-app');
}
prepare_components() {
@@ -190,7 +177,7 @@
}
toggle_recent_order() {
- const show = this.recent_order_list.$component.hasClass('d-none');
+ const show = this.recent_order_list.$component.is(':hidden');
this.toggle_recent_order_list(show);
}
@@ -199,7 +186,7 @@
if (this.frm.doc.items.length == 0) {
frappe.show_alert({
- message:__("You must add atleast one item to save it as draft."),
+ message:__("You must add atleast one item to save it as draft."),
indicator:'red'
});
frappe.utils.play_sound("error");
@@ -208,7 +195,7 @@
this.frm.save(undefined, undefined, undefined, () => {
frappe.show_alert({
- message:__("There was an error saving the document."),
+ message:__("There was an error saving the document."),
indicator:'red'
});
frappe.utils.play_sound("error");
@@ -256,7 +243,7 @@
cart_item_clicked: (item_code, batch_no, uom) => {
const item_row = this.frm.doc.items.find(
- i => i.item_code === item_code
+ i => i.item_code === item_code
&& i.uom === uom
&& (!batch_no || (batch_no && i.batch_no === batch_no))
);
@@ -356,10 +343,10 @@
toggle_other_sections: (show) => {
if (show) {
- this.item_details.$component.hasClass('d-none') ? '' : this.item_details.$component.addClass('d-none');
- this.item_selector.$component.addClass('d-none');
+ this.item_details.$component.is(':visible') ? this.item_details.$component.css('display', 'none') : '';
+ this.item_selector.$component.css('display', 'none');
} else {
- this.item_selector.$component.removeClass('d-none');
+ this.item_selector.$component.css('display', 'flex');
}
},
@@ -388,7 +375,7 @@
this.order_summary.load_summary_of(doc);
});
},
- reset_summary: () => this.order_summary.show_summary_placeholder()
+ reset_summary: () => this.order_summary.toggle_summary_placeholder(true)
}
})
}
@@ -429,7 +416,7 @@
})
}
-
+
toggle_recent_order_list(show) {
this.toggle_components(!show);
@@ -539,7 +526,7 @@
const qty_needed = field === 'qty' ? value * item_row.conversion_factor : item_row.qty * value;
await this.check_stock_availability(item_row, qty_needed, this.frm.doc.set_warehouse);
}
-
+
if (this.is_current_item_being_edited(item_row) || item_selected_from_selector) {
await frappe.model.set_value(item_row.doctype, item_row.name, field, value);
this.update_cart_html(item_row);
@@ -577,7 +564,7 @@
this.check_serial_batch_selection_needed(item_row) && this.edit_item_details_of(item_row);
this.update_cart_html(item_row);
- }
+ }
} catch (error) {
console.log(error);
} finally {
@@ -588,7 +575,7 @@
get_item_from_frm(item_code, batch_no, uom) {
const has_batch_no = batch_no;
return this.frm.doc.items.find(
- i => i.item_code === item_code
+ i => i.item_code === item_code
&& (!has_batch_no || (has_batch_no && i.batch_no === batch_no))
&& (i.uom === uom)
);
@@ -617,7 +604,7 @@
const no_serial_selected = !item_row.serial_no;
const no_batch_selected = !item_row.batch_no;
- if ((serialized && no_serial_selected) || (batched && no_batch_selected) ||
+ if ((serialized && no_serial_selected) || (batched && no_batch_selected) ||
(serialized && batched && (no_batch_selected || no_serial_selected))) {
return true;
}
diff --git a/erpnext/selling/page/point_of_sale/pos_item_cart.js b/erpnext/selling/page/point_of_sale/pos_item_cart.js
index 7799dac..efe716d 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_cart.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_cart.js
@@ -16,10 +16,10 @@
prepare_dom() {
this.wrapper.append(
- `<section class="col-span-4 flex flex-col shadow rounded item-cart bg-white mx-h-70 h-100"></section>`
+ `<section class="customer-cart-container"></section>`
)
- this.$component = this.wrapper.find('.item-cart');
+ this.$component = this.wrapper.find('.customer-cart-container');
}
init_child_components() {
@@ -29,7 +29,7 @@
init_customer_selector() {
this.$component.append(
- `<div class="customer-section rounded flex flex-col m-8 mb-0"></div>`
+ `<div class="customer-section"></div>`
)
this.$customer_section = this.$component.find('.customer-section');
}
@@ -37,23 +37,23 @@
reset_customer_selector() {
const frm = this.events.get_frm();
frm.set_value('customer', '');
- this.$customer_section.removeClass('border pr-4 pl-4');
this.make_customer_selector();
this.customer_field.set_focus();
}
init_cart_components() {
this.$component.append(
- `<div class="cart-container flex flex-col items-center rounded flex-1 relative">
- <div class="absolute flex flex-col p-8 pt-0 w-full h-full">
- <div class="flex text-grey cart-header pt-2 pb-2 p-4 mt-2 mb-2 w-full f-shrink-0">
- <div class="flex-1">Item</div>
- <div class="mr-4">Qty</div>
- <div class="rate-list-header mr-1 text-right">Amount</div>
+ `<div class="cart-container">
+ <div class="abs-cart-container">
+ <div class="cart-label">Item Cart</div>
+ <div class="cart-header">
+ <div class="name-header">Item</div>
+ <div class="qty-header">Qty</div>
+ <div class="rate-amount-header">Amount</div>
</div>
- <div class="cart-items-section flex flex-col flex-1 scroll-y rounded w-full"></div>
- <div class="cart-totals-section flex flex-col w-full mt-4 f-shrink-0"></div>
- <div class="numpad-section flex flex-col mt-4 d-none w-full p-8 pt-0 pb-0 f-shrink-0"></div>
+ <div class="cart-items-section"></div>
+ <div class="cart-totals-section"></div>
+ <div class="numpad-section"></div>
</div>
</div>`
);
@@ -72,50 +72,44 @@
}
make_no_items_placeholder() {
- this.$cart_header.addClass('d-none');
+ this.$cart_header.css('display', 'none');
this.$cart_items_wrapper.html(
- `<div class="no-item-wrapper flex items-center h-18">
- <div class="flex-1 text-center text-grey">No items in cart</div>
- </div>`
- )
- this.$cart_items_wrapper.addClass('mt-4 border-grey border-dashed');
+ `<div class="no-item-wrapper">No items in cart</div>`
+ );
+ }
+
+ get_discount_icon() {
+ return (
+ `<svg class="discount-icon" width="24" height="24" viewBox="0 0 24 24" stroke="currentColor" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <path d="M19 15.6213C19 15.2235 19.158 14.842 19.4393 14.5607L20.9393 13.0607C21.5251 12.4749 21.5251 11.5251 20.9393 10.9393L19.4393 9.43934C19.158 9.15804 19 8.7765 19 8.37868V6.5C19 5.67157 18.3284 5 17.5 5H15.6213C15.2235 5 14.842 4.84196 14.5607 4.56066L13.0607 3.06066C12.4749 2.47487 11.5251 2.47487 10.9393 3.06066L9.43934 4.56066C9.15804 4.84196 8.7765 5 8.37868 5H6.5C5.67157 5 5 5.67157 5 6.5V8.37868C5 8.7765 4.84196 9.15804 4.56066 9.43934L3.06066 10.9393C2.47487 11.5251 2.47487 12.4749 3.06066 13.0607L4.56066 14.5607C4.84196 14.842 5 15.2235 5 15.6213V17.5C5 18.3284 5.67157 19 6.5 19H8.37868C8.7765 19 9.15804 19.158 9.43934 19.4393L10.9393 20.9393C11.5251 21.5251 12.4749 21.5251 13.0607 20.9393L14.5607 19.4393C14.842 19.158 15.2235 19 15.6213 19H17.5C18.3284 19 19 18.3284 19 17.5V15.6213Z" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
+ <path d="M15 9L9 15" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
+ <path d="M10.5 9.5C10.5 10.0523 10.0523 10.5 9.5 10.5C8.94772 10.5 8.5 10.0523 8.5 9.5C8.5 8.94772 8.94772 8.5 9.5 8.5C10.0523 8.5 10.5 8.94772 10.5 9.5Z" fill="white" stroke-linecap="round" stroke-linejoin="round"/>
+ <path d="M15.5 14.5C15.5 15.0523 15.0523 15.5 14.5 15.5C13.9477 15.5 13.5 15.0523 13.5 14.5C13.5 13.9477 13.9477 13.5 14.5 13.5C15.0523 13.5 15.5 13.9477 15.5 14.5Z" fill="white" stroke-linecap="round" stroke-linejoin="round"/>
+ </svg>`
+ );
}
make_cart_totals_section() {
this.$totals_section = this.$component.find('.cart-totals-section');
this.$totals_section.append(
- `<div class="add-discount flex items-center pt-4 pb-4 pr-4 pl-4 text-grey pointer no-select d-none">
- + Add Discount
+ `<div class="add-discount-wrapper">
+ ${this.get_discount_icon()} Add Discount
</div>
- <div class="border border-grey rounded">
- <div class="net-total flex justify-between items-center h-16 pr-8 pl-8 border-b-grey">
- <div class="flex flex-col">
- <div class="text-md text-dark-grey text-bold">Net Total</div>
- </div>
- <div class="flex flex-col text-right">
- <div class="text-md text-dark-grey text-bold">0.00</div>
- </div>
- </div>
- <div class="taxes"></div>
- <div class="grand-total flex justify-between items-center h-16 pr-8 pl-8 border-b-grey">
- <div class="flex flex-col">
- <div class="text-md text-dark-grey text-bold">Grand Total</div>
- </div>
- <div class="flex flex-col text-right">
- <div class="text-md text-dark-grey text-bold">0.00</div>
- </div>
- </div>
- <div class="checkout-btn flex items-center justify-center h-16 pr-8 pl-8 text-center text-grey no-select pointer rounded-b text-md text-bold">
- Checkout
- </div>
- <div class="edit-cart-btn flex items-center justify-center h-16 pr-8 pl-8 text-center text-grey no-select pointer d-none text-md text-bold">
- Edit Cart
- </div>
- </div>`
+ <div class="net-total-container">
+ <div class="net-total-label">Net Total</div>
+ <div class="net-total-value">0.00</div>
+ </div>
+ <div class="taxes-container"></div>
+ <div class="grand-total-container">
+ <div>Grand Total</div>
+ <div>0.00</div>
+ </div>
+ <div class="checkout-btn">Checkout</div>
+ <div class="edit-cart-btn">Edit Cart</div>`
)
- this.$add_discount_elem = this.$component.find(".add-discount");
+ this.$add_discount_elem = this.$component.find(".add-discount-wrapper");
}
make_cart_numpad() {
@@ -137,39 +131,37 @@
[ '', '', '', 'col-span-2' ],
[ '', '', '', 'col-span-2' ],
[ '', '', '', 'col-span-2' ],
- [ '', '', '', 'col-span-2 text-bold text-danger' ]
+ [ '', '', '', 'col-span-2 remove-btn' ]
],
fieldnames_map: { 'Quantity': 'qty', 'Discount': 'discount_percentage' }
})
this.$numpad_section.prepend(
- `<div class="flex mb-2 justify-between">
+ `<div class="numpad-totals">
<span class="numpad-net-total"></span>
<span class="numpad-grand-total"></span>
</div>`
)
this.$numpad_section.append(
- `<div class="numpad-btn checkout-btn flex items-center justify-center h-16 pr-8 pl-8 bg-primary
- text-center text-white no-select pointer rounded text-md text-bold mt-4" data-button-value="checkout">
- Checkout
- </div>`
+ `<div class="numpad-btn checkout-btn" data-button-value="checkout">Checkout</div>`
)
}
bind_events() {
const me = this;
- this.$customer_section.on('click', '.add-remove-customer', function (e) {
- const customer_info_is_visible = me.$cart_container.hasClass('d-none');
- customer_info_is_visible ?
- me.toggle_customer_info(false) : me.reset_customer_selector();
+ this.$customer_section.on('click', '.reset-customer-btn', function (e) {
+ me.reset_customer_selector();
});
- this.$customer_section.on('click', '.customer-header', function(e) {
- // don't triggger the event if .add-remove-customer btn is clicked which is under .customer-header
- if ($(e.target).closest('.add-remove-customer').length) return;
+ this.$customer_section.on('click', '.close-details-btn', function (e) {
+ me.toggle_customer_info(false);
+ });
- const show = !me.$cart_container.hasClass('d-none');
+ this.$customer_section.on('click', '.customer-display', function(e) {
+ if ($(e.target).closest('.reset-customer-btn').length) return;
+
+ const show = me.$cart_container.is(':visible');
me.toggle_customer_info(show);
});
@@ -178,7 +170,7 @@
me.toggle_item_highlight(this);
- const payment_section_hidden = me.$totals_section.find('.edit-cart-btn').hasClass('d-none');
+ const payment_section_hidden = !me.$totals_section.find('.edit-cart-btn').is(':visible');
if (!payment_section_hidden) {
// payment section is visible
// edit cart first and then open item details section
@@ -193,23 +185,19 @@
});
this.$component.on('click', '.checkout-btn', function() {
- if (!$(this).hasClass('bg-primary')) return;
+ if ($(this).attr('style').indexOf('--blue-500') == -1) return;
me.events.checkout();
me.toggle_checkout_btn(false);
-
- me.$add_discount_elem.removeClass("d-none");
});
this.$totals_section.on('click', '.edit-cart-btn', () => {
this.events.edit_cart();
this.toggle_checkout_btn(true);
-
- this.$add_discount_elem.addClass("d-none");
});
- this.$component.on('click', '.add-discount', () => {
- const can_edit_discount = this.$add_discount_elem.find('.edit-discount').length;
+ this.$component.on('click', '.add-discount-wrapper', () => {
+ const can_edit_discount = this.$add_discount_elem.find('.edit-discount-btn').length;
if(!this.discount_field || can_edit_discount) this.show_discount_control();
});
@@ -251,7 +239,7 @@
frappe.ui.keys.add_shortcut({
shortcut: "ctrl+enter",
action: () => this.$component.find(".checkout-btn").click(),
- condition: () => this.$component.is(":visible") && this.$totals_section.find('.edit-cart-btn').hasClass('d-none'),
+ condition: () => this.$component.is(":visible") && !this.$totals_section.find('.edit-cart-btn').is(':visible'),
description: __("Checkout Order / Submit Order / New Order"),
ignore_inputs: true,
page: cur_page.page.page
@@ -259,14 +247,15 @@
this.$component.find(".edit-cart-btn").attr("title", `${ctrl_label}+E`);
frappe.ui.keys.on("ctrl+e", () => {
const item_cart_visible = this.$component.is(":visible");
- if (item_cart_visible && this.$totals_section.find('.checkout-btn').hasClass('d-none')) {
- this.$component.find(".edit-cart-btn").click()
+ const checkout_btn_invisible = !this.$totals_section.find('.checkout-btn').is('visible');
+ if (item_cart_visible && checkout_btn_invisible) {
+ this.$component.find(".edit-cart-btn").click();
}
});
- this.$component.find(".add-discount").attr("title", `${ctrl_label}+D`);
+ this.$component.find(".add-discount-wrapper").attr("title", `${ctrl_label}+D`);
frappe.ui.keys.add_shortcut({
shortcut: "ctrl+d",
- action: () => this.$component.find(".add-discount").click(),
+ action: () => this.$component.find(".add-discount-wrapper").click(),
condition: () => this.$add_discount_elem.is(":visible"),
description: __("Add Order Discount"),
ignore_inputs: true,
@@ -282,24 +271,22 @@
toggle_item_highlight(item) {
const $cart_item = $(item);
- const item_is_highlighted = $cart_item.hasClass("shadow");
+ const item_is_highlighted = $cart_item.attr("style") == "background-color:var(--gray-50);";
if (!item || item_is_highlighted) {
this.item_is_selected = false;
- this.$cart_container.find('.cart-item-wrapper').removeClass("shadow").css("opacity", "1");
+ this.$cart_container.find('.cart-item-wrapper').css("background-color", "");
} else {
- $cart_item.addClass("shadow");
+ $cart_item.css("background-color", "var(--gray-50)");
this.item_is_selected = true;
- this.$cart_container.find('.cart-item-wrapper').css("opacity", "1");
- this.$cart_container.find('.cart-item-wrapper').not(item).removeClass("shadow").css("opacity", "0.65");
+ this.$cart_container.find('.cart-item-wrapper').not(item).css("background-color", "");
}
- // highlight with inner shadow
- // $cart_item.addClass("shadow-inner bg-selected");
- // me.$cart_container.find('.cart-item-wrapper').not(this).removeClass("shadow-inner bg-selected");
}
make_customer_selector() {
- this.$customer_section.html(`<div class="customer-search-field flex flex-1 items-center"></div>`);
+ this.$customer_section.html(`
+ <div class="customer-field"></div>
+ `);
const me = this;
const query = { query: 'erpnext.controllers.queries.customer_query' };
const allowed_customer_group = this.events.get_allowed_customer_group() || [];
@@ -332,7 +319,7 @@
}
},
},
- parent: this.$customer_section.find('.customer-search-field'),
+ parent: this.$customer_section.find('.customer-field'),
render_input: true,
});
this.customer_field.toggle_label(false);
@@ -371,9 +358,9 @@
}
show_discount_control() {
- this.$add_discount_elem.removeClass("pr-4 pl-4");
+ this.$add_discount_elem.css({ 'padding': '0px', 'border': 'none' })
this.$add_discount_elem.html(
- `<div class="add-discount-field flex flex-1 items-center"></div>`
+ `<div class="add-discount-field"></div>`
);
const me = this;
@@ -382,14 +369,19 @@
label: __('Discount'),
fieldtype: 'Data',
placeholder: __('Enter discount percentage.'),
+ input_class: 'input-xs',
onchange: function() {
const frm = me.events.get_frm();
- if (this.value.length || this.value === 0) {
+ if (flt(this.value) != 0) {
frappe.model.set_value(frm.doc.doctype, frm.doc.name, 'additional_discount_percentage', flt(this.value));
me.hide_discount_control(this.value);
} else {
frappe.model.set_value(frm.doc.doctype, frm.doc.name, 'additional_discount_percentage', 0);
- me.$add_discount_elem.html(`+ Add Discount`);
+ me.$add_discount_elem.css({
+ 'border': '1px dashed var(--gray-500)',
+ 'padding': 'var(--padding-sm) var(--padding-md)'
+ });
+ me.$add_discount_elem.html(`${me.get_discount_icon()} Add Discount`);
me.discount_field = undefined;
}
},
@@ -403,38 +395,36 @@
hide_discount_control(discount) {
if (!discount) {
- this.$add_discount_elem.removeClass("pr-4 pl-4");
+ this.$add_discount_elem.css({ 'padding': '0px', 'border': 'none' });
this.$add_discount_elem.html(
- `<div class="add-discount-field flex flex-1 items-center"></div>`
+ `<div class="add-discount-field"></div>`
);
} else {
- this.$add_discount_elem.addClass('pr-4 pl-4');
+ this.$add_discount_elem.css({
+ 'border': '1px dashed var(--dark-green-500)',
+ 'padding': 'var(--padding-sm) var(--padding-md)'
+ });
this.$add_discount_elem.html(
- `<svg class="mr-2" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1"
- stroke-linecap="round" stroke-linejoin="round">
- <path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>
- </svg>
- <div class="edit-discount p-1 pr-3 pl-3 text-dark-grey rounded w-fit bg-green-200 mb-2">
- ${String(discount).bold()}% off
- </div>
- `
+ `<div class="edit-discount-btn">
+ ${this.get_discount_icon()} Additional ${String(discount).bold()}% discount applied
+ </div>`
);
}
}
update_customer_section() {
- const { customer, email_id='', mobile_no='', image } = this.customer_info || {};
+ const { customer, email_id='', mobile_no='' } = this.customer_info || {};
if (customer) {
- this.$customer_section.addClass('border pr-4 pl-4').html(
- `<div class="customer-details flex flex-col">
- <div class="customer-header flex items-center rounded h-18 pointer">
- ${get_customer_image()}
- <div class="customer-name flex flex-col flex-1 f-shrink-1 overflow-hidden whitespace-nowrap">
- <div class="text-md text-dark-grey text-bold">${customer}</div>
+ this.$customer_section.html(
+ `<div class="customer-details">
+ <div class="customer-display">
+ ${this.get_customer_image()}
+ <div class="customer-name-desc">
+ <div class="customer-name">${customer}</div>
${get_customer_description()}
</div>
- <div class="f-shrink-0 add-remove-customer flex items-center pointer" data-customer="${escape(customer)}">
+ <div class="reset-customer-btn" data-customer="${escape(customer)}">
<svg width="32" height="32" viewBox="0 0 14 14" fill="none">
<path d="M4.93764 4.93759L7.00003 6.99998M9.06243 9.06238L7.00003 6.99998M7.00003 6.99998L4.93764 9.06238L9.06243 4.93759" stroke="#8D99A6"/>
</svg>
@@ -449,26 +439,24 @@
function get_customer_description() {
if (!email_id && !mobile_no) {
- return `<div class="text-grey-200 italic">Click to add email / phone</div>`
+ return `<div class="customer-desc">Click to add email / phone</div>`
} else if (email_id && !mobile_no) {
- return `<div class="text-grey">${email_id}</div>`
+ return `<div class="customer-desc">${email_id}</div>`
} else if (mobile_no && !email_id) {
- return `<div class="text-grey">${mobile_no}</div>`
+ return `<div class="customer-desc">${mobile_no}</div>`
} else {
- return `<div class="text-grey">${email_id} | ${mobile_no}</div>`
+ return `<div class="customer-desc">${email_id} - ${mobile_no}</div>`
}
}
- function get_customer_image() {
- if (image) {
- return `<div class="icon flex items-center justify-center w-12 h-12 rounded bg-light-grey mr-4 text-grey-200">
- <img class="h-full" src="${image}" alt="${image}" style="object-fit: cover;">
- </div>`
- } else {
- return `<div class="icon flex items-center justify-center w-12 h-12 rounded bg-light-grey mr-4 text-grey-200 text-md">
- ${frappe.get_abbr(customer)}
- </div>`
- }
+ }
+
+ get_customer_image() {
+ const { customer, image } = this.customer_info || {};
+ if (image) {
+ return `<div class="customer-image"><img src="${image}" alt="${image}""></div>`
+ } else {
+ return `<div class="customer-image customer-abbr">${frappe.get_abbr(customer)}</div>`
}
}
@@ -484,57 +472,44 @@
render_net_total(value) {
const currency = this.events.get_frm().doc.currency;
- this.$totals_section.find('.net-total').html(
- `<div class="flex flex-col">
- <div class="text-md text-dark-grey text-bold">Net Total</div>
- </div>
- <div class="flex flex-col text-right">
- <div class="text-md text-dark-grey text-bold">${format_currency(value, currency)}</div>
- </div>`
+ this.$totals_section.find('.net-total-container').html(
+ `<div>Net Total</div><div>${format_currency(value, currency)}</div>`
)
- this.$numpad_section.find('.numpad-net-total').html(`Net Total: <span class="text-bold">${format_currency(value, currency)}</span>`)
+ this.$numpad_section.find('.numpad-net-total').html(
+ `<div>Net Total: <span>${format_currency(value, currency)}</span></div>`
+ );
}
render_grand_total(value) {
const currency = this.events.get_frm().doc.currency;
- this.$totals_section.find('.grand-total').html(
- `<div class="flex flex-col">
- <div class="text-md text-dark-grey text-bold">Grand Total</div>
- </div>
- <div class="flex flex-col text-right">
- <div class="text-md text-dark-grey text-bold">${format_currency(value, currency)}</div>
- </div>`
+ this.$totals_section.find('.grand-total-container').html(
+ `<div>Grand Total</div><div>${format_currency(value, currency)}</div>`
)
- this.$numpad_section.find('.numpad-grand-total').html(`Grand Total: <span class="text-bold">${format_currency(value, currency)}</span>`)
+ this.$numpad_section.find('.numpad-grand-total').html(
+ `<div>Grand Total: <span>${format_currency(value, currency)}</span></div>`
+ )
}
render_taxes(value, taxes) {
if (taxes.length) {
const currency = this.events.get_frm().doc.currency;
- this.$totals_section.find('.taxes').html(
- `<div class="flex items-center justify-between h-16 pr-8 pl-8 border-b-grey">
- <div class="flex overflow-hidden whitespace-nowrap">
- <div class="text-md text-dark-grey text-bold w-fit">Tax Charges</div>
- <div class="flex ml-4 text-dark-grey">
- ${
- taxes.map((t, i) => {
- let margin_left = '';
- if (i !== 0) margin_left = 'ml-2';
- const description = /[0-9]+/.test(t.description) ? t.description : `${t.description} @ ${t.rate}%`;
- return `<span class="border-grey p-1 pl-2 pr-2 rounded ${margin_left}">${description}</span>`
- }).join('')
- }
- </div>
- </div>
- <div class="flex flex-col text-right f-shrink-0 ml-4">
- <div class="text-md text-dark-grey text-bold">${format_currency(value, currency)}</div>
- </div>
- </div>`
+ this.$totals_section.find('.taxes-container').css('display', 'flex').html(
+ `${
+ taxes.map((t, i) => {
+ const description = /[0-9]+/.test(t.description) ? t.description : `${t.description} @ ${t.rate}%`;
+ return `<div class="tax-row">
+ <div class="tax-label">
+ ${description}
+ </div>
+ <div class="tax-value">${format_currency(value, currency)}</div>
+ </div>`
+ }).join('')
+ }`
)
} else {
- this.$totals_section.find('.taxes').html('')
+ this.$totals_section.find('.taxes-container').css('display', 'none').html('');
}
}
@@ -553,7 +528,7 @@
const $item = this.get_cart_item(item);
if (remove_item) {
- $item && $item.remove();
+ $item && $item.next().remove() && $item.remove();
} else {
const { item_code, batch_no, uom } = item;
const search_field = batch_no ? 'batch_no' : 'item_code';
@@ -563,9 +538,9 @@
this.render_cart_item(item_row, $item);
}
- const no_of_cart_items = this.$cart_items_wrapper.children().length;
- no_of_cart_items > 0 && this.highlight_checkout_btn(no_of_cart_items > 0);
-
+ const no_of_cart_items = this.$cart_items_wrapper.find('.cart-item-wrapper').length;
+ this.highlight_checkout_btn(no_of_cart_items > 0);
+
this.update_empty_cart_section(no_of_cart_items);
}
@@ -575,32 +550,33 @@
if (!$item_to_update.length) {
this.$cart_items_wrapper.append(
- `<div class="cart-item-wrapper flex items-center h-18 pr-4 pl-4 rounded border-grey pointer no-select"
+ `<div class="cart-item-wrapper"
data-item-code="${escape(item_data.item_code)}" data-uom="${escape(item_data.uom)}"
data-batch-no="${escape(item_data.batch_no || '')}">
- </div>`
+ </div>
+ <div class="seperator"></div>`
)
$item_to_update = this.get_cart_item(item_data);
}
$item_to_update.html(
- `<div class="flex flex-col flex-1 f-shrink-1 overflow-hidden whitespace-nowrap">
- <div class="text-md text-dark-grey text-bold">
+ `${get_item_image_html()}
+ <div class="item-name-desc">
+ <div class="item-name">
${item_data.item_name}
</div>
${get_description_html()}
</div>
- ${get_rate_discount_html()}
- </div>`
+ ${get_rate_discount_html()}`
)
set_dynamic_rate_header_width();
this.scroll_to_item($item_to_update);
function set_dynamic_rate_header_width() {
- const rate_cols = Array.from(me.$cart_items_wrapper.find(".rate-col"));
- me.$cart_header.find(".rate-list-header").css("width", "");
- me.$cart_items_wrapper.find(".rate-col").css("width", "");
+ const rate_cols = Array.from(me.$cart_items_wrapper.find(".item-rate-amount"));
+ me.$cart_header.find(".rate-amount-header").css("width", "");
+ me.$cart_items_wrapper.find(".item-rate-amount").css("width", "");
let max_width = rate_cols.reduce((max_width, elm) => {
if ($(elm).width() > max_width)
max_width = $(elm).width();
@@ -610,30 +586,26 @@
max_width += 1;
if (max_width == 1) max_width = "";
- me.$cart_header.find(".rate-list-header").css("width", max_width);
- me.$cart_items_wrapper.find(".rate-col").css("width", max_width);
+ me.$cart_header.find(".rate-amount-header").css("width", max_width);
+ me.$cart_items_wrapper.find(".item-rate-amount").css("width", max_width);
}
function get_rate_discount_html() {
if (item_data.rate && item_data.amount && item_data.rate !== item_data.amount) {
return `
- <div class="flex f-shrink-0 ml-4 items-center">
- <div class="flex w-8 h-8 rounded bg-light-grey mr-4 items-center justify-center font-bold f-shrink-0">
- <span>${item_data.qty || 0}</span>
- </div>
- <div class="rate-col flex flex-col f-shrink-0 text-right">
- <div class="text-md text-dark-grey text-bold">${format_currency(item_data.amount, currency)}</div>
- <div class="text-md-0 text-dark-grey">${format_currency(item_data.rate, currency)}</div>
+ <div class="item-qty-rate">
+ <div class="item-qty"><span>${item_data.qty || 0}</span></div>
+ <div class="item-rate-amount">
+ <div class="item-rate">${format_currency(item_data.amount, currency)}</div>
+ <div class="item-amount">${format_currency(item_data.rate, currency)}</div>
</div>
</div>`
} else {
return `
- <div class="flex f-shrink-0 ml-4 text-right">
- <div class="flex w-8 h-8 rounded bg-light-grey mr-4 items-center justify-center font-bold f-shrink-0">
- <span>${item_data.qty || 0}</span>
- </div>
- <div class="rate-col flex flex-col f-shrink-0 text-right">
- <div class="text-md text-dark-grey text-bold">${format_currency(item_data.rate, currency)}</div>
+ <div class="item-qty-rate">
+ <div class="item-qty"><span>${item_data.qty || 0}</span></div>
+ <div class="item-rate-amount">
+ <div class="item-rate">${format_currency(item_data.rate, currency)}</div>
</div>
</div>`
}
@@ -649,10 +621,19 @@
}
}
item_data.description = frappe.ellipsis(item_data.description, 45);
- return `<div class="text-grey">${item_data.description}</div>`
+ return `<div class="item-desc">${item_data.description}</div>`
}
return ``;
}
+
+ function get_item_image_html() {
+ const { image, item_name } = item_data;
+ if (image) {
+ return `<div class="item-image"><img src="${image}" alt="${image}""></div>`
+ } else {
+ return `<div class="item-image item-abbr">${frappe.get_abbr(item_name)}</div>`
+ }
+ }
}
scroll_to_item($item) {
@@ -668,20 +649,25 @@
toggle_checkout_btn(show_checkout) {
if (show_checkout) {
- this.$totals_section.find('.checkout-btn').removeClass('d-none');
- this.$totals_section.find('.edit-cart-btn').addClass('d-none');
+ this.$totals_section.find('.checkout-btn').css('display', 'flex');
+ this.$totals_section.find('.edit-cart-btn').css('display', 'none');
} else {
- this.$totals_section.find('.checkout-btn').addClass('d-none');
- this.$totals_section.find('.edit-cart-btn').removeClass('d-none');
+ this.$totals_section.find('.checkout-btn').css('display', 'none');
+ this.$totals_section.find('.edit-cart-btn').css('display', 'flex');
}
}
highlight_checkout_btn(toggle) {
- const has_primary_class = this.$totals_section.find('.checkout-btn').hasClass('bg-primary');
- if (toggle && !has_primary_class) {
- this.$totals_section.find('.checkout-btn').addClass('bg-primary text-white text-lg');
- } else if (!toggle && has_primary_class) {
- this.$totals_section.find('.checkout-btn').removeClass('bg-primary text-white text-lg');
+ if (toggle) {
+ this.$add_discount_elem.css('display', 'flex');
+ this.$cart_container.find('.checkout-btn').css({
+ 'background-color': 'var(--blue-500)'
+ });
+ } else {
+ this.$add_discount_elem.css('display', 'none');
+ this.$cart_container.find('.checkout-btn').css({
+ 'background-color': 'var(--blue-200)'
+ });
}
}
@@ -689,8 +675,7 @@
const $no_item_element = this.$cart_items_wrapper.find('.no-item-wrapper');
// if cart has items and no item is present
- no_of_cart_items > 0 && $no_item_element && $no_item_element.remove()
- && this.$cart_items_wrapper.removeClass('mt-4 border-grey border-dashed') && this.$cart_header.removeClass('d-none');
+ no_of_cart_items > 0 && $no_item_element && $no_item_element.remove() && this.$cart_header.css('display', 'flex');
no_of_cart_items === 0 && !$no_item_element.length && this.make_no_items_placeholder();
}
@@ -753,36 +738,36 @@
}
highlight_numpad_btn($btn, curr_action) {
- const curr_action_is_highlighted = $btn.hasClass('shadow-inner');
+ const curr_action_is_highlighted = $btn.hasClass('highlighted-numpad-btn');
const curr_action_is_action = ['qty', 'discount_percentage', 'rate', 'done'].includes(curr_action);
if (!curr_action_is_highlighted) {
- $btn.addClass('shadow-inner bg-selected');
+ $btn.addClass('highlighted-numpad-btn');
}
if (this.prev_action === curr_action && curr_action_is_highlighted) {
// if Qty is pressed twice
- $btn.removeClass('shadow-inner bg-selected');
+ $btn.removeClass('highlighted-numpad-btn');
}
if (this.prev_action && this.prev_action !== curr_action && curr_action_is_action) {
// Order: Qty -> Rate then remove Qty highlight
const prev_btn = $(`[data-button-value='${this.prev_action}']`);
- prev_btn.removeClass('shadow-inner bg-selected');
+ prev_btn.removeClass('highlighted-numpad-btn');
}
if (!curr_action_is_action || curr_action === 'done') {
// if numbers are clicked
setTimeout(() => {
- $btn.removeClass('shadow-inner bg-selected');
- }, 100);
+ $btn.removeClass('highlighted-numpad-btn');
+ }, 200);
}
}
toggle_numpad(show) {
if (show) {
- this.$totals_section.addClass('d-none');
- this.$numpad_section.removeClass('d-none');
+ this.$totals_section.css('display', 'none');
+ this.$numpad_section.css('display', 'flex');
} else {
- this.$totals_section.removeClass('d-none');
- this.$numpad_section.addClass('d-none');
+ this.$totals_section.css('display', 'flex');
+ this.$numpad_section.css('display', 'none');
}
this.reset_numpad();
}
@@ -790,7 +775,7 @@
reset_numpad() {
this.numpad_value = '';
this.prev_action = undefined;
- this.$numpad_section.find('.shadow-inner').removeClass('shadow-inner bg-selected');
+ this.$numpad_section.find('.highlighted-numpad-btn').removeClass('highlighted-numpad-btn');
}
toggle_numpad_field_edit(fieldname) {
@@ -801,48 +786,60 @@
toggle_customer_info(show) {
if (show) {
- this.$cart_container.addClass('d-none')
- this.$customer_section.addClass('flex-1 scroll-y').removeClass('mb-0 border pr-4 pl-4')
- this.$customer_section.find('.icon').addClass('w-24 h-24 text-2xl').removeClass('w-12 h-12 text-md')
- this.$customer_section.find('.customer-header').removeClass('h-18');
- this.$customer_section.find('.customer-details').addClass('sticky z-100 bg-white');
+ const { customer } = this.customer_info || {};
- this.$customer_section.find('.customer-name').html(
- `<div class="text-md text-dark-grey text-bold">${this.customer_info.customer}</div>
- <div class="last-transacted-on text-grey-200"></div>`
- )
-
- this.$customer_section.find('.customer-details').append(
- `<div class="customer-form">
- <div class="text-grey mt-4 mb-6">CONTACT DETAILS</div>
- <div class="grid grid-cols-2 gap-4">
- <div class="email_id-field"></div>
- <div class="mobile_no-field"></div>
- <div class="loyalty_program-field"></div>
- <div class="loyalty_points-field"></div>
+ this.$cart_container.css('display', 'none');
+ this.$customer_section.css({
+ 'height': '100%',
+ 'padding-top': '0px',
+ 'overflow-x': 'hidden',
+ 'overflow-y': 'scroll'
+ });
+ this.$customer_section.find('.customer-details').html(
+ `<div class="header">
+ <div class="label">Contact Details</div>
+ <div class="close-details-btn">
+ <svg width="32" height="32" viewBox="0 0 14 14" fill="none">
+ <path d="M4.93764 4.93759L7.00003 6.99998M9.06243 9.06238L7.00003 6.99998M7.00003 6.99998L4.93764 9.06238L9.06243 4.93759" stroke="#8D99A6"/>
+ </svg>
</div>
- <div class="text-grey mt-4 mb-6">RECENT TRANSACTIONS</div>
- </div>`
- )
+ </div>
+ <div class="customer-display">
+ ${this.get_customer_image()}
+ <div class="customer-name-desc">
+ <div class="customer-name">${customer}</div>
+ <div class="customer-desc"></div>
+ </div>
+ </div>
+ <div class="customer-fields-container">
+ <div class="email_id-field"></div>
+ <div class="mobile_no-field"></div>
+ <div class="loyalty_program-field"></div>
+ <div class="loyalty_points-field"></div>
+ </div>
+ <div class="transactions-label">Recent Transactions</div>`
+ );
// transactions need to be in diff div from sticky elem for scrolling
- this.$customer_section.append(`<div class="customer-transactions flex-1 rounded"></div>`)
+ this.$customer_section.append(`<div class="customer-transactions"></div>`)
- this.render_customer_info_form();
+ this.render_customer_fields();
this.fetch_customer_transactions();
} else {
- this.$cart_container.removeClass('d-none');
- this.$customer_section.removeClass('flex-1 scroll-y').addClass('mb-0 border pr-4 pl-4');
- this.$customer_section.find('.icon').addClass('w-12 h-12 text-md').removeClass('w-24 h-24 text-2xl');
- this.$customer_section.find('.customer-header').addClass('h-18')
- this.$customer_section.find('.customer-details').removeClass('sticky z-100 bg-white');
+ this.$cart_container.css('display', 'flex');
+ this.$customer_section.css({
+ 'height': '',
+ 'padding-top': '',
+ 'overflow-x': '',
+ 'overflow-y': ''
+ });
this.update_customer_section();
}
}
- render_customer_info_form() {
- const $customer_form = this.$customer_section.find('.customer-form');
+ render_customer_fields() {
+ const $customer_form = this.$customer_section.find('.customer-fields-container');
const dfs = [{
fieldname: 'email_id',
@@ -864,7 +861,7 @@
},{
fieldname: 'loyalty_points',
label: __('Loyalty Points'),
- fieldtype: 'Int',
+ fieldtype: 'Data',
read_only: 1
}];
@@ -916,41 +913,45 @@
const transaction_container = this.$customer_section.find('.customer-transactions');
if (!res.length) {
- transaction_container.removeClass('flex-1 border rounded').html(
- `<div class="text-grey text-center">No recent transactions found</div>`
+ transaction_container.html(
+ `<div class="no-transactions-placeholder">No recent transactions found</div>`
)
return;
};
const elapsed_time = moment(res[0].posting_date+" "+res[0].posting_time).fromNow();
- this.$customer_section.find('.last-transacted-on').html(`Last transacted ${elapsed_time}`);
+ this.$customer_section.find('.customer-desc').html(`Last transacted ${elapsed_time}`);
res.forEach(invoice => {
const posting_datetime = moment(invoice.posting_date+" "+invoice.posting_time).format("Do MMMM, h:mma");
- let indicator_color = '';
-
- if (in_list(['Paid', 'Consolidated'], invoice.status)) (indicator_color = 'green');
- if (invoice.status === 'Draft') (indicator_color = 'red');
- if (invoice.status === 'Return') (indicator_color = 'grey');
+ let indicator_color = {
+ 'Paid': 'green',
+ 'Draft': 'red',
+ 'Return': 'gray',
+ 'Consolidated': 'blue'
+ };
transaction_container.append(
- `<div class="invoice-wrapper flex p-3 justify-between border-grey rounded pointer no-select" data-invoice-name="${escape(invoice.name)}">
- <div class="flex flex-col justify-end">
- <div class="text-dark-grey text-bold overflow-hidden whitespace-nowrap mb-2">${invoice.name}</div>
- <div class="flex items-center f-shrink-1 text-dark-grey overflow-hidden whitespace-nowrap">
- ${posting_datetime}
- </div>
+ `<div class="invoice-wrapper" data-invoice-name="${escape(invoice.name)}">
+ <div class="invoice-name-date">
+ <div class="invoice-name">${invoice.name}</div>
+ <div class="invoice-date">${posting_datetime}</div>
</div>
- <div class="flex flex-col text-right">
- <div class="f-shrink-0 text-md text-dark-grey text-bold ml-4">
+ <div class="invoice-total-status">
+ <div class="invoice-total">
${format_currency(invoice.grand_total, invoice.currency, 0) || 0}
</div>
- <div class="f-shrink-0 text-grey ml-4 text-bold indicator ${indicator_color}">${invoice.status}</div>
+ <div class="invoice-status">
+ <span class="indicator-pill whitespace-nowrap ${indicator_color[invoice.status]}">
+ <span>${invoice.status}</span>
+ </span>
+ </div>
</div>
- </div>`
+ </div>
+ <div class="seperator"></div>`
)
});
- })
+ });
}
load_invoice() {
@@ -973,20 +974,18 @@
this.update_totals_section(frm);
if(frm.doc.docstatus === 1) {
- this.$totals_section.find('.checkout-btn').addClass('d-none');
- this.$totals_section.find('.edit-cart-btn').addClass('d-none');
- this.$totals_section.find('.grand-total').removeClass('border-b-grey');
+ this.$totals_section.find('.checkout-btn').css('display', 'none');
+ this.$totals_section.find('.edit-cart-btn').css('display', 'none');
} else {
- this.$totals_section.find('.checkout-btn').removeClass('d-none');
- this.$totals_section.find('.edit-cart-btn').addClass('d-none');
- this.$totals_section.find('.grand-total').addClass('border-b-grey');
+ this.$totals_section.find('.checkout-btn').css('display', 'flex');
+ this.$totals_section.find('.edit-cart-btn').css('display', 'none');
}
this.toggle_component(true);
}
toggle_component(show) {
- show ? this.$component.removeClass('d-none') : this.$component.addClass('d-none');
+ show ? this.$component.css('display', 'flex') : this.$component.css('display', 'none');
}
}
diff --git a/erpnext/selling/page/point_of_sale/pos_item_details.js b/erpnext/selling/page/point_of_sale/pos_item_details.js
index a4de9f1..5461543 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_details.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_details.js
@@ -16,35 +16,36 @@
prepare_dom() {
this.wrapper.append(
- `<section class="col-span-4 flex shadow rounded item-details bg-white mx-h-70 h-100 d-none"></section>`
+ `<section class="item-details-container"></section>`
)
- this.$component = this.wrapper.find('.item-details');
+ this.$component = this.wrapper.find('.item-details-container');
}
init_child_components() {
this.$component.html(
- `<div class="details-container flex flex-col p-8 rounded w-full">
- <div class="flex justify-between mb-2">
- <div class="text-grey">ITEM DETAILS</div>
- <div class="close-btn text-grey hover-underline pointer no-select">Close</div>
+ `<div class="item-details-header">
+ <div class="label">Item Details</div>
+ <div class="close-btn">
+ <svg width="32" height="32" viewBox="0 0 14 14" fill="none">
+ <path d="M4.93764 4.93759L7.00003 6.99998M9.06243 9.06238L7.00003 6.99998M7.00003 6.99998L4.93764 9.06238L9.06243 4.93759" stroke="#8D99A6"/>
+ </svg>
</div>
- <div class="item-defaults flex">
- <div class="flex-1 flex flex-col justify-end mr-4 mb-2">
- <div class="item-name text-xl font-weight-450"></div>
- <div class="item-description text-md-0 text-grey-200"></div>
- <div class="item-price text-xl font-bold"></div>
- </div>
- <div class="item-image flex items-center justify-center w-46 h-46 bg-light-grey rounded ml-4 text-6xl text-grey-100"></div>
+ </div>
+ <div class="item-display">
+ <div class="item-name-desc-price">
+ <div class="item-name"></div>
+ <div class="item-desc"></div>
+ <div class="item-price"></div>
</div>
- <div class="discount-section flex items-center"></div>
- <div class="text-grey mt-4 mb-6">STOCK DETAILS</div>
- <div class="form-container grid grid-cols-2 row-gap-2 col-gap-4 grid-auto-row"></div>
- </div>`
+ <div class="item-image"></div>
+ </div>
+ <div class="discount-section"></div>
+ <div class="form-container"></div>`
)
this.$item_name = this.$component.find('.item-name');
- this.$item_description = this.$component.find('.item-description');
+ this.$item_description = this.$component.find('.item-desc');
this.$item_price = this.$component.find('.item-price');
this.$item_image = this.$component.find('.item-image');
this.$form_container = this.$component.find('.form-container');
@@ -52,7 +53,7 @@
}
toggle_item_details_section(item) {
- const { item_code, batch_no, uom } = this.current_item;
+ const { item_code, batch_no, uom } = this.current_item;
const item_code_is_same = item && item_code === item.item_code;
const batch_is_same = item && batch_no == item.batch_no;
const uom_is_same = item && uom === item.uom;
@@ -104,11 +105,11 @@
}
render_dom(item) {
- let { item_code ,item_name, description, image, price_list_rate } = item;
+ let { item_name, description, image, price_list_rate } = item;
function get_description_html() {
if (description) {
- description = description.indexOf('...') === -1 && description.length > 75 ? description.substr(0, 73) + '...' : description;
+ description = description.indexOf('...') === -1 && description.length > 140 ? description.substr(0, 139) + '...' : description;
return description;
}
return ``;
@@ -118,11 +119,9 @@
this.$item_description.html(get_description_html());
this.$item_price.html(format_currency(price_list_rate, this.currency));
if (image) {
- this.$item_image.html(
- `<img class="h-full" src="${image}" alt="${image}" style="object-fit: cover;">`
- );
+ this.$item_image.html(`<img src="${image}" alt="${image}">`);
} else {
- this.$item_image.html(frappe.get_abbr(item_code));
+ this.$item_image.html(`<div class="item-abbr">${frappe.get_abbr(item_name)}</div>`);
}
}
@@ -130,12 +129,8 @@
render_discount_dom(item) {
if (item.discount_percentage) {
this.$dicount_section.html(
- `<div class="text-grey line-through mr-4 text-md mb-2">
- ${format_currency(item.price_list_rate, this.currency)}
- </div>
- <div class="p-1 pr-3 pl-3 rounded w-fit text-bold bg-green-200 mb-2">
- ${item.discount_percentage}% off
- </div>`
+ `<div class="item-rate">${format_currency(item.price_list_rate, this.currency)}</div>
+ <div class="item-discount">${item.discount_percentage}% off</div>`
)
this.$item_price.html(format_currency(item.rate, this.currency));
} else {
@@ -149,9 +144,7 @@
fields_to_display.forEach((fieldname, idx) => {
this.$form_container.append(
- `<div class="">
- <div class="item_detail_field ${fieldname}-control" data-fieldname="${fieldname}"></div>
- </div>`
+ `<div class="${fieldname}-control" data-fieldname="${fieldname}"></div>`
)
const field_meta = this.item_meta.fields.find(df => df.fieldname === fieldname);
@@ -185,22 +178,15 @@
make_auto_serial_selection_btn(item) {
if (item.has_serial_no) {
- this.$form_container.append(
- `<div class="grid-filler no-select"></div>`
- )
if (!item.has_batch_no) {
this.$form_container.append(
`<div class="grid-filler no-select"></div>`
)
}
this.$form_container.append(
- `<div class="auto-fetch-btn bg-grey-100 border border-grey text-bold rounded pt-3 pb-3 pl-6 pr-8 text-grey pointer no-select mt-2"
- style="height: 3.3rem">
- Auto Fetch Serial Numbers
- </div>`
+ `<div class="btn btn-sm btn-secondary auto-fetch-btn">Auto Fetch Serial Numbers</div>`
)
- this.$form_container.find('.serial_no-control').find('textarea').css('height', '9rem');
- this.$form_container.find('.serial_no-control').parent().addClass('row-span-2');
+ this.$form_container.find('.serial_no-control').find('textarea').css('height', '6rem');
}
}
@@ -294,8 +280,13 @@
}
frappe.model.on("POS Invoice Item", "*", (fieldname, value, item_row) => {
- const field_control = me[`${fieldname}_control`];
- if (field_control) {
+ const field_control = this[`${fieldname}_control`];
+ const { item_code, batch_no, uom } = this.current_item;
+ const item_code_is_same = item_code === item_row.item_code;
+ const batch_is_same = batch_no == item_row.batch_no;
+ const uom_is_same = uom === item_row.uom;
+
+ if (field_control && item_code_is_same && batch_is_same && uom_is_same) {
field_control.set_value(value);
cur_pos.update_cart_html(item_row);
}
@@ -409,6 +400,6 @@
}
toggle_component(show) {
- show ? this.$component.removeClass('d-none') : this.$component.addClass('d-none');
+ show ? this.$component.css('display', 'flex') : this.$component.css('display', 'none');
}
}
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_item_selector.js b/erpnext/selling/page/point_of_sale/pos_item_selector.js
index 49d4281..0d0e36c 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_selector.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js
@@ -1,3 +1,5 @@
+import onScan from 'onscan.js';
+
erpnext.PointOfSale.ItemSelector = class {
constructor({ frm, wrapper, events, pos_profile }) {
this.wrapper = wrapper;
@@ -17,18 +19,13 @@
prepare_dom() {
this.wrapper.append(
- `<section class="col-span-6 flex shadow rounded items-selector bg-white mx-h-70 h-100">
- <div class="flex flex-col rounded w-full scroll-y">
- <div class="filter-section flex p-8 pb-2 bg-white sticky z-100">
- <div class="search-field flex f-grow-3 mr-8 items-center text-grey"></div>
- <div class="item-group-field flex f-grow-1 items-center text-grey text-bold"></div>
- </div>
- <div class="flex flex-1 flex-col p-8 pt-2">
- <div class="text-grey mb-6">ALL ITEMS</div>
- <div class="items-container grid grid-cols-4 gap-8">
- </div>
- </div>
+ `<section class="items-selector">
+ <div class="filter-section">
+ <div class="label">All Items</div>
+ <div class="search-field"></div>
+ <div class="item-group-field"></div>
</div>
+ <div class="items-container"></div>
</section>`
);
@@ -51,7 +48,8 @@
}
get_items({start = 0, page_length = 40, search_value=''}) {
- const price_list = this.events.get_frm().doc?.selling_price_list || this.price_list;
+ const doc = this.events.get_frm().doc;
+ const price_list = (doc && doc.selling_price_list) || this.price_list;
let { item_group, pos_profile } = this;
!item_group && (item_group = this.parent_item_group);
@@ -80,27 +78,28 @@
function get_item_image_html() {
if (item_image) {
- return `<div class="flex items-center justify-center h-32 border-b-grey text-6xl text-grey-100">
- <img class="h-full" src="${item_image}" alt="${frappe.get_abbr(item.item_name)}" style="object-fit: cover;">
- </div>`
+ return `<div class="item-display">
+ <img src="${item_image}" alt="${frappe.get_abbr(item.item_name)}">
+ </div>`;
} else {
- return `<div class="flex items-center justify-center h-32 bg-light-grey text-6xl text-grey-100">
- ${frappe.get_abbr(item.item_name)}
- </div>`
+ return `<div class="item-display abbr">${frappe.get_abbr(item.item_name)}</div>`;
}
}
return (
- `<div class="item-wrapper rounded shadow pointer no-select" data-item-code="${escape(item.item_code)}"
- data-serial-no="${escape(serial_no)}" data-batch-no="${escape(batch_no)}" data-uom="${escape(stock_uom)}"
+ `<div class="item-wrapper"
+ data-item-code="${escape(item.item_code)}" data-serial-no="${escape(serial_no)}"
+ data-batch-no="${escape(batch_no)}" data-uom="${escape(stock_uom)}"
title="Avaiable Qty: ${actual_qty}">
+
${get_item_image_html()}
- <div class="flex items-center pr-4 pl-4 h-10 justify-between">
- <div class="flex items-center f-shrink-1 text-dark-grey overflow-hidden whitespace-nowrap">
+
+ <div class="item-detail">
+ <div class="item-name">
<span class="indicator ${indicator_color}"></span>
${frappe.ellipsis(item.item_name, 18)}
</div>
- <div class="f-shrink-0 text-dark-grey text-bold ml-4">${format_currency(item.price_list_rate, item.currency, 0) || 0}</div>
+ <div class="item-rate">${format_currency(item.price_list_rate, item.currency, 0) || 0}</div>
</div>
</div>`
)
@@ -108,6 +107,7 @@
make_search_bar() {
const me = this;
+ const doc = me.events.get_frm().doc;
this.$component.find('.search-field').html('');
this.$component.find('.item-group-field').html('');
@@ -115,7 +115,7 @@
df: {
label: __('Search'),
fieldtype: 'Data',
- placeholder: __('Search by item code, serial number, batch no or barcode')
+ placeholder: __('Search by item code, serial number or barcode')
},
parent: this.$component.find('.search-field'),
render_input: true,
@@ -135,7 +135,7 @@
return {
query: 'erpnext.selling.page.point_of_sale.point_of_sale.item_group_query',
filters: {
- pos_profile: me.events.get_frm().doc?.pos_profile
+ pos_profile: doc ? doc.pos_profile : ''
}
}
},
@@ -149,6 +149,7 @@
bind_events() {
const me = this;
+ window.onScan = onScan;
onScan.attachTo(document, {
onScan: (sScancode) => {
if (this.search_field && this.$component.is(':visible')) {
@@ -252,23 +253,23 @@
resize_selector(minimize) {
minimize ?
- this.$component.find('.search-field').removeClass('mr-8') :
- this.$component.find('.search-field').addClass('mr-8');
+ this.$component.find('.filter-section').css('grid-template-columns', 'repeat(1, minmax(0, 1fr))') :
+ this.$component.find('.filter-section').css('grid-template-columns', 'repeat(12, minmax(0, 1fr))');
minimize ?
- this.$component.find('.filter-section').addClass('flex-col') :
- this.$component.find('.filter-section').removeClass('flex-col');
+ this.$component.find('.search-field').css('margin', 'var(--margin-sm) 0px') :
+ this.$component.find('.search-field').css('margin', '0px var(--margin-sm)');
minimize ?
- this.$component.removeClass('col-span-6').addClass('col-span-2') :
- this.$component.removeClass('col-span-2').addClass('col-span-6')
+ this.$component.css('grid-column', 'span 2 / span 2') :
+ this.$component.css('grid-column', 'span 6 / span 6')
minimize ?
- this.$items_container.removeClass('grid-cols-4').addClass('grid-cols-1') :
- this.$items_container.removeClass('grid-cols-1').addClass('grid-cols-4')
+ this.$items_container.css('grid-template-columns', 'repeat(1, minmax(0, 1fr))') :
+ this.$items_container.css('grid-template-columns', 'repeat(4, minmax(0, 1fr))')
}
toggle_component(show) {
- show ? this.$component.removeClass('d-none') : this.$component.addClass('d-none');
+ show ? this.$component.css('display', 'flex') : this.$component.css('display', 'none');
}
}
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_number_pad.js b/erpnext/selling/page/point_of_sale/pos_number_pad.js
index 4b8e841..edde7d8 100644
--- a/erpnext/selling/page/point_of_sale/pos_number_pad.js
+++ b/erpnext/selling/page/point_of_sale/pos_number_pad.js
@@ -25,14 +25,13 @@
const fieldname = fieldnames && fieldnames[number] ?
fieldnames[number] : typeof number === 'string' ? frappe.scrub(number) : number;
- return a2 + `<div class="numpad-btn pointer no-select rounded ${class_to_append}
- flex items-center justify-center h-16 text-md border-grey border" data-button-value="${fieldname}">${number}</div>`
+ return a2 + `<div class="numpad-btn ${class_to_append}" data-button-value="${fieldname}">${number}</div>`
}, '')
}, '');
}
this.wrapper.html(
- `<div class="grid grid-cols-${cols} gap-4">
+ `<div class="numpad-container">
${get_keys()}
</div>`
)
diff --git a/erpnext/selling/page/point_of_sale/pos_past_order_list.js b/erpnext/selling/page/point_of_sale/pos_past_order_list.js
index b256247..ec39231 100644
--- a/erpnext/selling/page/point_of_sale/pos_past_order_list.js
+++ b/erpnext/selling/page/point_of_sale/pos_past_order_list.js
@@ -14,17 +14,13 @@
prepare_dom() {
this.wrapper.append(
- `<section class="col-span-4 flex flex-col shadow rounded past-order-list bg-white mx-h-70 h-100 d-none">
- <div class="flex flex-col rounded w-full scroll-y">
- <div class="filter-section flex flex-col p-8 pb-2 bg-white sticky z-100">
- <div class="search-field flex items-center text-grey"></div>
- <div class="status-field flex items-center text-grey text-bold"></div>
- </div>
- <div class="flex flex-1 flex-col p-8 pt-2">
- <div class="text-grey mb-6">RECENT ORDERS</div>
- <div class="invoices-container rounded border grid grid-cols-1"></div>
- </div>
+ `<section class="past-order-list">
+ <div class="filter-section">
+ <div class="label">Recent Orders</div>
+ <div class="search-field"></div>
+ <div class="status-field"></div>
</div>
+ <div class="invoices-container"></div>
</section>`
);
@@ -66,7 +62,7 @@
options: `Draft\nPaid\nConsolidated\nReturn`,
placeholder: __('Filter by invoice status'),
onchange: function() {
- me.refresh_list(me.search_field.get_value(), this.value);
+ if (me.$component.is(':visible')) me.refresh_list();
}
},
parent: this.$component.find('.status-field'),
@@ -77,10 +73,6 @@
this.status_field.set_value('Draft');
}
- toggle_component(show) {
- show ? this.$component.removeClass('d-none') && this.refresh_list() : this.$component.addClass('d-none');
- }
-
refresh_list() {
frappe.dom.freeze();
this.events.reset_summary();
@@ -106,23 +98,26 @@
get_invoice_html(invoice) {
const posting_datetime = moment(invoice.posting_date+" "+invoice.posting_time).format("Do MMMM, h:mma");
return (
- `<div class="invoice-wrapper flex p-4 justify-between border-b-grey pointer no-select" data-invoice-name="${escape(invoice.name)}">
- <div class="flex flex-col justify-end">
- <div class="text-dark-grey text-bold overflow-hidden whitespace-nowrap mb-2">${invoice.name}</div>
- <div class="flex items-center">
- <div class="flex items-center f-shrink-1 text-dark-grey overflow-hidden whitespace-nowrap">
- <svg class="mr-2" width="12" height="12" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
- <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>
- </svg>
- ${invoice.customer}
- </div>
+ `<div class="invoice-wrapper" data-invoice-name="${escape(invoice.name)}">
+ <div class="invoice-name-date">
+ <div class="invoice-name">${invoice.name}</div>
+ <div class="invoice-date">
+ <svg class="mr-2" width="12" height="12" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
+ <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>
+ </svg>
+ ${invoice.customer}
</div>
</div>
- <div class="flex flex-col text-right">
- <div class="f-shrink-0 text-lg text-dark-grey text-bold ml-4">${format_currency(invoice.grand_total, invoice.currency, 0) || 0}</div>
- <div class="f-shrink-0 text-grey ml-4">${posting_datetime}</div>
+ <div class="invoice-total-status">
+ <div class="invoice-total">${format_currency(invoice.grand_total, invoice.currency, 0) || 0}</div>
+ <div class="invoice-date">${posting_datetime}</div>
</div>
- </div>`
+ </div>
+ <div class="seperator"></div>`
);
}
+
+ toggle_component(show) {
+ show ? this.$component.css('display', 'flex') && this.refresh_list() : this.$component.css('display', 'none');
+ }
};
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_past_order_summary.js b/erpnext/selling/page/point_of_sale/pos_past_order_summary.js
index 6fd4c26..28076db 100644
--- a/erpnext/selling/page/point_of_sale/pos_past_order_summary.js
+++ b/erpnext/selling/page/point_of_sale/pos_past_order_summary.js
@@ -8,85 +8,39 @@
init_component() {
this.prepare_dom();
- this.init_child_components();
+ this.init_email_print_dialog();
this.bind_events();
this.attach_shortcuts();
}
prepare_dom() {
this.wrapper.append(
- `<section class="col-span-6 flex flex-col items-center shadow rounded past-order-summary bg-white mx-h-70 h-100 d-none">
- <div class="no-summary-placeholder flex flex-1 items-center justify-center p-16">
- <div class="no-item-wrapper flex items-center h-18 pr-4 pl-4">
- <div class="flex-1 text-center text-grey">Select an invoice to load summary data</div>
- </div>
+ `<section class="past-order-summary">
+ <div class="no-summary-placeholder">
+ Select an invoice to load summary data
</div>
- <div class="summary-wrapper d-none flex-1 w-66 text-dark-grey relative">
- <div class="summary-container absolute flex flex-col pt-16 pb-16 pr-8 pl-8 w-full h-full"></div>
+ <div class="invoice-summary-wrapper">
+ <div class="abs-container">
+ <div class="upper-section"></div>
+ <div class="label">Items</div>
+ <div class="items-container summary-container"></div>
+ <div class="label">Totals</div>
+ <div class="totals-container summary-container"></div>
+ <div class="label">Payments</div>
+ <div class="payments-container summary-container"></div>
+ <div class="summary-btns"></div>
+ </div>
</div>
</section>`
);
this.$component = this.wrapper.find('.past-order-summary');
- this.$summary_wrapper = this.$component.find('.summary-wrapper');
- this.$summary_container = this.$component.find('.summary-container');
- }
-
- init_child_components() {
- this.init_upper_section();
- this.init_items_summary();
- this.init_totals_summary();
- this.init_payments_summary();
- this.init_summary_buttons();
- this.init_email_print_dialog();
- }
-
- init_upper_section() {
- this.$summary_container.append(
- `<div class="flex upper-section justify-between w-full h-24"></div>`
- );
-
+ this.$summary_wrapper = this.$component.find('.invoice-summary-wrapper');
+ this.$summary_container = this.$component.find('.abs-container');
this.$upper_section = this.$summary_container.find('.upper-section');
- }
-
- init_items_summary() {
- this.$summary_container.append(
- `<div class="flex flex-col flex-1 mt-6 w-full scroll-y">
- <div class="text-grey mb-4 sticky bg-white">ITEMS</div>
- <div class="items-summary-container border rounded flex flex-col w-full"></div>
- </div>`
- );
-
- this.$items_summary_container = this.$summary_container.find('.items-summary-container');
- }
-
- init_totals_summary() {
- this.$summary_container.append(
- `<div class="flex flex-col mt-6 w-full f-shrink-0">
- <div class="text-grey mb-4">TOTALS</div>
- <div class="summary-totals-container border rounded flex flex-col w-full"></div>
- </div>`
- );
-
- this.$totals_summary_container = this.$summary_container.find('.summary-totals-container');
- }
-
- init_payments_summary() {
- this.$summary_container.append(
- `<div class="flex flex-col mt-6 w-full f-shrink-0">
- <div class="text-grey mb-4">PAYMENTS</div>
- <div class="payments-summary-container border rounded flex flex-col w-full mb-4"></div>
- </div>`
- );
-
- this.$payment_summary_container = this.$summary_container.find('.payments-summary-container');
- }
-
- init_summary_buttons() {
- this.$summary_container.append(
- `<div class="summary-btns flex summary-btns justify-between w-full f-shrink-0"></div>`
- );
-
+ this.$items_container = this.$summary_container.find('.items-container');
+ this.$totals_container = this.$summary_container.find('.totals-container');
+ this.$payment_container = this.$summary_container.find('.payments-container');
this.$summary_btns = this.$summary_container.find('.summary-btns');
}
@@ -121,132 +75,88 @@
}
get_upper_section_html(doc) {
- const { status } = doc; let indicator_color = '';
+ const { status } = doc;
+ let indicator_color = '';
in_list(['Paid', 'Consolidated'], status) && (indicator_color = 'green');
status === 'Draft' && (indicator_color = 'red');
status === 'Return' && (indicator_color = 'grey');
- return `<div class="flex flex-col items-start justify-end pr-4">
- <div class="text-lg text-bold pt-2">${doc.customer}</div>
- <div class="text-grey">${this.customer_email}</div>
- <div class="text-grey mt-auto">Sold by: ${doc.owner}</div>
+ return `<div class="left-section">
+ <div class="customer-name">${doc.customer}</div>
+ <div class="customer-email">${this.customer_email}</div>
+ <div class="cashier">Sold by: ${doc.owner}</div>
</div>
- <div class="flex flex-col flex-1 items-end justify-between">
- <div class="text-2-5xl text-bold">${format_currency(doc.paid_amount, doc.currency)}</div>
- <div class="flex justify-between">
- <div class="text-grey mr-4">${doc.name}</div>
- <div class="text-grey text-bold indicator ${indicator_color}">${doc.status}</div>
- </div>
+ <div class="right-section">
+ <div class="paid-amount">${format_currency(doc.paid_amount, doc.currency)}</div>
+ <div class="invoice-name">${doc.name}</div>
+ <span class="indicator-pill whitespace-nowrap ${indicator_color}"><span>${doc.status}</span></span>
</div>`;
}
+ get_item_html(doc, item_data) {
+ return `<div class="item-row-wrapper">
+ <div class="item-name">${item_data.item_name}</div>
+ <div class="item-qty">${item_data.qty || 0}</div>
+ <div class="item-rate-disc">${get_rate_discount_html()}</div>
+ </div>`;
+
+ function get_rate_discount_html() {
+ if (item_data.rate && item_data.price_list_rate && item_data.rate !== item_data.price_list_rate) {
+ return `<span class="item-disc">(${item_data.discount_percentage}% off)</span>
+ <div class="item-rate">${format_currency(item_data.rate, doc.currency)}</div>`;
+ } else {
+ return `<div class="item-rate">${format_currency(item_data.price_list_rate || item_data.rate, doc.currency)}</div>`;
+ }
+ }
+ }
+
get_discount_html(doc) {
if (doc.discount_amount) {
- return `<div class="total-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
- <div class="flex f-shrink-1 items-center">
- <div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap mr-2">
- Discount
- </div>
- <span class="text-grey">(${doc.additional_discount_percentage} %)</span>
- </div>
- <div class="flex flex-col f-shrink-0 ml-auto text-right">
- <div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.discount_amount, doc.currency)}</div>
- </div>
- </div>`;
+ return `<div class="summary-row-wrapper">
+ <div>Discount (${doc.additional_discount_percentage} %)</div>
+ <div>${format_currency(doc.discount_amount, doc.currency)}</div>
+ </div>`;
} else {
return ``;
}
}
get_net_total_html(doc) {
- return `<div class="total-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
- <div class="flex f-shrink-1 items-center">
- <div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap">
- Net Total
- </div>
- </div>
- <div class="flex flex-col f-shrink-0 ml-auto text-right">
- <div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.net_total, doc.currency)}</div>
- </div>
+ return `<div class="summary-row-wrapper">
+ <div>Net Total</div>
+ <div>${format_currency(doc.net_total, doc.currency)}</div>
</div>`;
}
get_taxes_html(doc) {
- const taxes = doc.taxes.map((t, i) => {
- let margin_left = '';
- if (i !== 0) margin_left = 'ml-2';
- return `<span class="pl-2 pr-2 ${margin_left}">${t.description} @${t.rate}%</span>`;
- }).join('');
+ if (!doc.taxes.length) return '';
return `
- <div class="total-summary-wrapper flex items-center justify-between h-12 pr-4 pl-4 border-b-grey">
- <div class="flex">
- <div class="text-md-0 text-dark-grey text-bold w-fit">Tax Charges</div>
- <div class="flex ml-6 text-dark-grey">${taxes}</div>
- </div>
- <div class="flex flex-col text-right">
- <div class="text-md-0 text-dark-grey text-bold">
- ${format_currency(doc.base_total_taxes_and_charges, doc.currency)}
- </div>
- </div>
+ <div class="taxes-wrapper">
+ ${
+ doc.taxes.map((t, i) => {
+ const description = /[0-9]+/.test(t.description) ? t.description : `${t.description} @ ${t.rate}%`;
+ return `<div class="tax-row">
+ <div class="tax-label">${description}</div>
+ <div class="tax-value">${format_currency(t.tax_amount_after_discount_amount, doc.currency)}</div>
+ </div>`
+ }).join('')
+ }
</div>`;
}
get_grand_total_html(doc) {
- return `<div class="total-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
- <div class="flex f-shrink-1 items-center">
- <div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap">
- Grand Total
- </div>
- </div>
- <div class="flex flex-col f-shrink-0 ml-auto text-right">
- <div class="text-md-0 text-dark-grey text-bold">${format_currency(doc.grand_total, doc.currency)}</div>
- </div>
+ return `<div class="summary-row-wrapper grand-total">
+ <div>Grand Total</div>
+ <div>${format_currency(doc.grand_total, doc.currency)}</div>
</div>`;
}
- get_item_html(doc, item_data) {
- return `<div class="item-summary-wrapper flex items-center h-12 pr-4 pl-4 border-b-grey pointer no-select">
- <div class="flex w-6 h-6 rounded bg-light-grey mr-4 items-center justify-center font-bold f-shrink-0">
- <span>${item_data.qty || 0}</span>
- </div>
- <div class="flex flex-col f-shrink-1">
- <div class="text-md text-dark-grey text-bold overflow-hidden whitespace-nowrap">
- ${item_data.item_name}
- </div>
- </div>
- <div class="flex f-shrink-0 ml-auto text-right">
- ${get_rate_discount_html()}
- </div>
- </div>`;
-
- function get_rate_discount_html() {
- if (item_data.rate && item_data.price_list_rate && item_data.rate !== item_data.price_list_rate) {
- return `<span class="text-grey mr-2">
- (${item_data.discount_percentage}% off)
- </span>
- <div class="text-md-0 text-dark-grey text-bold">
- ${format_currency(item_data.rate, doc.currency)}
- </div>`;
- } else {
- return `<div class="text-md-0 text-dark-grey text-bold">
- ${format_currency(item_data.price_list_rate || item_data.rate, doc.currency)}
- </div>`;
- }
- }
- }
-
get_payment_html(doc, payment) {
- return `<div class="payment-summary-wrapper flex items-center h-12 pr-4 pl-4 pointer border-b-grey no-select">
- <div class="flex f-shrink-1 items-center">
- <div class="text-md-0 text-dark-grey text-bold overflow-hidden whitespace-nowrap">
- ${payment.mode_of_payment}
- </div>
- </div>
- <div class="flex flex-col f-shrink-0 ml-auto text-right">
- <div class="text-md-0 text-dark-grey text-bold">${format_currency(payment.amount, doc.currency)}</div>
- </div>
+ return `<div class="summary-row-wrapper payments">
+ <div>${payment.mode_of_payment}</div>
+ <div>${format_currency(payment.amount, doc.currency)}</div>
</div>`;
}
@@ -254,22 +164,22 @@
this.$summary_container.on('click', '.return-btn', () => {
this.events.process_return(this.doc.name);
this.toggle_component(false);
- this.$component.find('.no-summary-placeholder').removeClass('d-none');
- this.$summary_wrapper.addClass('d-none');
+ this.$component.find('.no-summary-placeholder').css('display', 'flex');
+ this.$summary_wrapper.css('display', 'none');
});
this.$summary_container.on('click', '.edit-btn', () => {
this.events.edit_order(this.doc.name);
this.toggle_component(false);
- this.$component.find('.no-summary-placeholder').removeClass('d-none');
- this.$summary_wrapper.addClass('d-none');
+ this.$component.find('.no-summary-placeholder').css('display', 'flex');
+ this.$summary_wrapper.css('display', 'none');
});
this.$summary_container.on('click', '.new-btn', () => {
this.events.new_order();
this.toggle_component(false);
- this.$component.find('.no-summary-placeholder').removeClass('d-none');
- this.$summary_wrapper.addClass('d-none');
+ this.$component.find('.no-summary-placeholder').css('display', 'flex');
+ this.$summary_wrapper.css('display', 'none');
});
this.$summary_container.on('click', '.email-btn', () => {
@@ -312,10 +222,6 @@
});
}
- toggle_component(show) {
- show ? this.$component.removeClass('d-none') : this.$component.addClass('d-none');
- }
-
send_email() {
const frm = this.events.get_frm();
const recipients = this.email_dialog.get_values().recipients;
@@ -338,8 +244,10 @@
if(!r.exc) {
frappe.utils.play_sound("email");
if(r.message["emails_not_sent_to"]) {
- frappe.msgprint(__("Email not sent to {0} (unsubscribed / disabled)",
- [ frappe.utils.escape_html(r.message["emails_not_sent_to"]) ]) );
+ frappe.msgprint(__(
+ "Email not sent to {0} (unsubscribed / disabled)",
+ [ frappe.utils.escape_html(r.message["emails_not_sent_to"]) ]
+ ));
} else {
frappe.show_alert({
message: __('Email sent successfully.'),
@@ -361,9 +269,7 @@
m.visible_btns.forEach(b => {
const class_name = b.split(' ')[0].toLowerCase();
this.$summary_btns.append(
- `<div class="${class_name}-btn border rounded h-14 flex flex-1 items-center mr-4 justify-center text-md text-bold no-select pointer">
- ${b}
- </div>`
+ `<div class="summary-btn btn btn-default ${class_name}-btn">${b}</div>`
);
});
}
@@ -371,29 +277,14 @@
this.$summary_btns.children().last().removeClass('mr-4');
}
- show_summary_placeholder() {
- this.$summary_wrapper.addClass("d-none");
- this.$component.find('.no-summary-placeholder').removeClass('d-none');
- }
-
- switch_to_post_submit_summary() {
- // switch to full width view
- this.$component.removeClass('col-span-6').addClass('col-span-10');
- this.$summary_wrapper.removeClass('w-66').addClass('w-40');
-
- // switch place holder with summary container
- this.$component.find('.no-summary-placeholder').addClass('d-none');
- this.$summary_wrapper.removeClass('d-none');
- }
-
- switch_to_recent_invoice_summary() {
- // switch full width view with 60% view
- this.$component.removeClass('col-span-10').addClass('col-span-6');
- this.$summary_wrapper.removeClass('w-40').addClass('w-66');
-
- // switch place holder with summary container
- this.$component.find('.no-summary-placeholder').addClass('d-none');
- this.$summary_wrapper.removeClass('d-none');
+ toggle_summary_placeholder(show) {
+ if (show) {
+ this.$summary_wrapper.css('display', 'none');
+ this.$component.find('.no-summary-placeholder').css('display', 'flex');
+ } else {
+ this.$summary_wrapper.css('display', 'flex');
+ this.$component.find('.no-summary-placeholder').css('display', 'none');
+ }
}
get_condition_btn_map(after_submission) {
@@ -408,14 +299,15 @@
}
load_summary_of(doc, after_submission=false) {
- this.$summary_wrapper.removeClass("d-none");
+ this.toggle_summary_placeholder(false)
after_submission ?
- this.switch_to_post_submit_summary() : this.switch_to_recent_invoice_summary();
+ this.$summary_wrapper.css('grid-column', 'span 10 / span 10') :
+ this.$summary_wrapper.css('grid-column', 'span 6 / span 6')
this.doc = doc;
- this.attach_basic_info(doc);
+ this.attach_document_info(doc);
this.attach_items_info(doc);
@@ -428,7 +320,7 @@
this.add_summary_btns(condition_btns_map);
}
- attach_basic_info(doc) {
+ attach_document_info(doc) {
frappe.db.get_value('Customer', this.doc.customer, 'email_id').then(({ message }) => {
this.customer_email = message.email_id || '';
const upper_section_dom = this.get_upper_section_html(doc);
@@ -437,19 +329,19 @@
}
attach_items_info(doc) {
- this.$items_summary_container.html('');
- doc.items.forEach(item => {
+ this.$items_container.html('');
+ doc.items.forEach((item, i) => {
const item_dom = this.get_item_html(doc, item);
- this.$items_summary_container.append(item_dom);
+ this.$items_container.append(item_dom);
});
}
attach_payments_info(doc) {
- this.$payment_summary_container.html('');
+ this.$payment_container.html('');
doc.payments.forEach(p => {
if (p.amount) {
const payment_dom = this.get_payment_html(doc, p);
- this.$payment_summary_container.append(payment_dom);
+ this.$payment_container.append(payment_dom);
}
});
if (doc.redeem_loyalty_points && doc.loyalty_amount) {
@@ -457,20 +349,24 @@
mode_of_payment: 'Loyalty Points',
amount: doc.loyalty_amount,
});
- this.$payment_summary_container.append(payment_dom);
+ this.$payment_container.append(payment_dom);
}
}
attach_totals_info(doc) {
- this.$totals_summary_container.html('');
+ this.$totals_container.html('');
- const discount_dom = this.get_discount_html(doc);
const net_total_dom = this.get_net_total_html(doc);
const taxes_dom = this.get_taxes_html(doc);
+ const discount_dom = this.get_discount_html(doc);
const grand_total_dom = this.get_grand_total_html(doc);
- this.$totals_summary_container.append(discount_dom);
- this.$totals_summary_container.append(net_total_dom);
- this.$totals_summary_container.append(taxes_dom);
- this.$totals_summary_container.append(grand_total_dom);
+ this.$totals_container.append(net_total_dom);
+ this.$totals_container.append(taxes_dom);
+ this.$totals_container.append(discount_dom);
+ this.$totals_container.append(grand_total_dom);
+ }
+
+ toggle_component(show) {
+ show ? this.$component.css('display', 'flex') : this.$component.css('display', 'none');
}
};
\ No newline at end of file
diff --git a/erpnext/selling/page/point_of_sale/pos_payment.js b/erpnext/selling/page/point_of_sale/pos_payment.js
index e4d8965..365c27b 100644
--- a/erpnext/selling/page/point_of_sale/pos_payment.js
+++ b/erpnext/selling/page/point_of_sale/pos_payment.js
@@ -1,5 +1,3 @@
-{% include "erpnext/selling/page/point_of_sale/pos_number_pad.js" %}
-
erpnext.PointOfSale.Payment = class {
constructor({ events, wrapper }) {
this.wrapper = wrapper;
@@ -18,52 +16,37 @@
prepare_dom() {
this.wrapper.append(
- `<section class="col-span-6 flex shadow rounded payment-section bg-white mx-h-70 h-100 d-none">
- <div class="flex flex-col p-16 pt-8 pb-8 w-full">
- <div class="text-grey mb-6 payment-section no-select pointer">
- PAYMENT METHOD<span class="octicon octicon-chevron-down collapse-indicator"></span>
+ `<section class="payment-container">
+ <div class="section-label payment-section">Payment Method</div>
+ <div class="payment-modes"></div>
+ <div class="fields-numpad-container">
+ <div class="fields-section">
+ <div class="section-label">Additional Information</div>
+ <div class="invoice-fields"></div>
</div>
- <div class="payment-modes flex flex-wrap"></div>
- <div class="invoice-details-section"></div>
- <div class="flex mt-auto justify-center w-full">
- <div class="flex flex-col justify-center flex-1 ml-4">
- <div class="flex w-full">
- <div class="totals-remarks items-end justify-end flex flex-1">
- <div class="remarks text-md-0 text-grey mr-auto"></div>
- <div class="totals flex justify-end pt-4"></div>
- </div>
- <div class="number-pad w-40 mb-4 ml-8 d-none"></div>
- </div>
- <div class="flex items-center justify-center mt-4 submit-order h-16 w-full rounded bg-primary text-md text-white no-select pointer text-bold">
- Complete Order
- </div>
- <div class="order-time flex items-center justify-end mt-2 pt-2 pb-2 w-full text-md-0 text-grey no-select pointer d-none"></div>
- </div>
- </div>
+ <div class="number-pad"></div>
</div>
+ <div class="totals-section">
+ <div class="totals"></div>
+ </div>
+ <div class="submit-order-btn">Complete Order</div>
</section>`
)
- this.$component = this.wrapper.find('.payment-section');
+ this.$component = this.wrapper.find('.payment-container');
this.$payment_modes = this.$component.find('.payment-modes');
- this.$totals_remarks = this.$component.find('.totals-remarks');
+ this.$totals_section = this.$component.find('.totals-section');
this.$totals = this.$component.find('.totals');
- this.$remarks = this.$component.find('.remarks');
this.$numpad = this.$component.find('.number-pad');
- this.$invoice_details_section = this.$component.find('.invoice-details-section');
+ this.$invoice_fields_section = this.$component.find('.fields-section');
}
make_invoice_fields_control() {
frappe.db.get_doc("POS Settings", undefined).then((doc) => {
const fields = doc.invoice_fields;
if (!fields.length) return;
-
- this.$invoice_details_section.html(
- `<div class="text-grey pb-6 mt-2 pointer no-select">
- ADDITIONAL INFORMATION<span class="octicon octicon-chevron-down collapse-indicator"></span>
- </div>
- <div class="invoice-fields grid grid-cols-2 gap-4 mb-6 d-none"></div>`
- );
- this.$invoice_fields = this.$invoice_details_section.find('.invoice-fields');
+
+ this.$invoice_fields = this.$invoice_fields_section.find('.invoice-fields');
+ this.$invoice_fields.html('');
const frm = this.events.get_frm();
fields.forEach(df => {
@@ -127,9 +110,9 @@
this.selected_mode.set_value(this.numpad_value);
function highlight_numpad_btn($btn) {
- $btn.addClass('shadow-inner bg-selected');
+ $btn.addClass('shadow-base-inner bg-selected');
setTimeout(() => {
- $btn.removeClass('shadow-inner bg-selected');
+ $btn.removeClass('shadow-base-inner bg-selected');
}, 100);
}
}
@@ -142,13 +125,16 @@
// if clicked element doesn't have .mode-of-payment class then return
if (!$(e.target).is(mode_clicked)) return;
+ const scrollLeft = mode_clicked.offset().left - me.$payment_modes.offset().left + me.$payment_modes.scrollLeft();
+ me.$payment_modes.animate({ scrollLeft });
+
const mode = mode_clicked.attr('data-mode');
// hide all control fields and shortcuts
- $(`.mode-of-payment-control`).addClass('d-none');
- $(`.cash-shortcuts`).addClass('d-none');
- me.$payment_modes.find(`.pay-amount`).removeClass('d-none');
- me.$payment_modes.find(`.loyalty-amount-name`).addClass('d-none');
+ $(`.mode-of-payment-control`).css('display', 'none');
+ $(`.cash-shortcuts`).css('display', 'none');
+ me.$payment_modes.find(`.pay-amount`).css('display', 'inline');
+ me.$payment_modes.find(`.loyalty-amount-name`).css('display', 'none');
// remove highlight from all mode-of-payments
$('.mode-of-payment').removeClass('border-primary');
@@ -157,21 +143,20 @@
// clicked one is selected then unselect it
mode_clicked.removeClass('border-primary');
me.selected_mode = '';
- me.toggle_numpad(false);
} else {
// clicked one is not selected then select it
mode_clicked.addClass('border-primary');
- mode_clicked.find('.mode-of-payment-control').removeClass('d-none');
- mode_clicked.find('.cash-shortcuts').removeClass('d-none');
- me.$payment_modes.find(`.${mode}-amount`).addClass('d-none');
- me.$payment_modes.find(`.${mode}-name`).removeClass('d-none');
- me.toggle_numpad(true);
+ mode_clicked.find('.mode-of-payment-control').css('display', 'flex');
+ mode_clicked.find('.cash-shortcuts').css('display', 'grid');
+ me.$payment_modes.find(`.${mode}-amount`).css('display', 'none');
+ me.$payment_modes.find(`.${mode}-name`).css('display', 'inline');
- me.selected_mode = me[`${mode}_control`];
const doc = me.events.get_frm().doc;
- me.selected_mode?.$input?.get(0).focus();
- const current_value = me.selected_mode?.get_value()
- !current_value && doc.grand_total > doc.paid_amount ? me.selected_mode?.set_value(doc.grand_total - doc.paid_amount) : '';
+ me.selected_mode = me[`${mode}_control`];
+ me.selected_mode && me.selected_mode.$input.get(0).focus();
+ const current_value = me.selected_mode ? me.selected_mode.get_value() : undefined;
+ !current_value && doc.grand_total > doc.paid_amount && me.selected_mode ?
+ me.selected_mode.set_value(doc.grand_total - doc.paid_amount) : '';
}
})
@@ -198,7 +183,7 @@
me.selected_mode.set_value(value);
})
- this.$component.on('click', '.submit-order', () => {
+ this.$component.on('click', '.submit-order-btn', () => {
const doc = this.events.get_frm().doc;
const paid_amount = doc.paid_amount;
const items = doc.items;
@@ -217,9 +202,9 @@
this.update_totals_section(frm.doc);
// need to re calculate cash shortcuts after discount is applied
- const is_cash_shortcuts_invisible = this.$payment_modes.find('.cash-shortcuts').hasClass('d-none');
+ const is_cash_shortcuts_invisible = !this.$payment_modes.find('.cash-shortcuts').is(':visible');
this.attach_cash_shortcuts(frm.doc);
- !is_cash_shortcuts_invisible && this.$payment_modes.find('.cash-shortcuts').removeClass('d-none');
+ !is_cash_shortcuts_invisible && this.$payment_modes.find('.cash-shortcuts').css('display', 'grid');
})
frappe.ui.form.on('POS Invoice', 'loyalty_amount', (frm) => {
@@ -235,29 +220,16 @@
this[`${mode}_control`].set_value(default_mop.amount);
}
});
-
- this.$component.on('click', '.invoice-details-section', function(e) {
- if ($(e.target).closest('.invoice-fields').length) return;
-
- me.$payment_modes.addClass('d-none');
- me.$invoice_fields.toggleClass("d-none");
- me.toggle_numpad(false);
- });
- this.$component.on('click', '.payment-section', () => {
- this.$invoice_fields.addClass("d-none");
- this.$payment_modes.toggleClass('d-none');
- this.toggle_numpad(true);
- })
}
attach_shortcuts() {
const ctrl_label = frappe.utils.is_mac() ? '⌘' : 'Ctrl';
- this.$component.find('.submit-order').attr("title", `${ctrl_label}+Enter`);
+ this.$component.find('.submit-order-btn').attr("title", `${ctrl_label}+Enter`);
frappe.ui.keys.on("ctrl+enter", () => {
const payment_is_visible = this.$component.is(":visible");
const active_mode = this.$payment_modes.find(".border-primary");
if (payment_is_visible && active_mode.length) {
- this.$component.find('.submit-order').click();
+ this.$component.find('.submit-order-btn').click();
}
});
@@ -287,15 +259,13 @@
}
toggle_numpad(show) {
- if (show) {
- this.$numpad.removeClass('d-none');
- this.$remarks.addClass('d-none');
- this.$totals_remarks.addClass('w-60 justify-center').removeClass('justify-end w-full');
- } else {
- this.$numpad.addClass('d-none');
- this.$remarks.removeClass('d-none');
- this.$totals_remarks.removeClass('w-60 justify-center').addClass('justify-end w-full');
- }
+ // if (show) {
+ // this.$numpad.css('display', 'flex');
+ // this.$totals_section.addClass('w-60 justify-center').removeClass('justify-end w-full');
+ // } else {
+ // this.$numpad.css('display', 'none');
+ // this.$totals_section.removeClass('w-60 justify-center').addClass('justify-end w-full');
+ // }
}
render_payment_section() {
@@ -327,7 +297,7 @@
fieldtype: 'Data',
onchange: function() {}
},
- parent: this.$totals_remarks.find(`.remarks`),
+ parent: this.$totals_section.find(`.remarks`),
render_input: true,
});
this[`remark_control`].set_value('');
@@ -348,12 +318,11 @@
const amount = p.amount > 0 ? format_currency(p.amount, currency) : '';
return (
- `<div class="w-half ${margin} bg-white">
- <div class="mode-of-payment rounded border border-grey text-grey text-md
- mb-4 p-8 pt-4 pb-4 no-select pointer" data-mode="${mode}" data-payment-type="${payment_type}">
+ `<div class="payment-mode-wrapper">
+ <div class="mode-of-payment" data-mode="${mode}" data-payment-type="${payment_type}">
${p.mode_of_payment}
- <div class="${mode}-amount pay-amount inline float-right text-bold">${amount}</div>
- <div class="${mode} mode-of-payment-control mt-4 flex flex-1 items-center d-none"></div>
+ <div class="${mode}-amount pay-amount">${amount}</div>
+ <div class="${mode} mode-of-payment-control"></div>
</div>
</div>`
)
@@ -405,12 +374,10 @@
this.$payment_modes.find('.cash-shortcuts').remove();
this.$payment_modes.find('[data-payment-type="Cash"]').find('.mode-of-payment-control').after(
- `<div class="cash-shortcuts grid grid-cols-3 gap-2 flex-1 text-center text-md-0 mb-2 d-none">
+ `<div class="cash-shortcuts">
${
shortcuts.map(s => {
- return `<div class="shortcut rounded bg-light-grey text-dark-grey pt-2 pb-2 no-select pointer" data-value="${s}">
- ${format_currency(s, currency, 0)}
- </div>`
+ return `<div class="shortcut" data-value="${s}">${format_currency(s, currency, 0)}</div>`
}).join('')
}
</div>`
@@ -457,13 +424,12 @@
const margin = this.$payment_modes.children().length % 2 === 0 ? 'pr-2' : 'pl-2';
const amount = doc.loyalty_amount > 0 ? format_currency(doc.loyalty_amount, doc.currency) : '';
this.$payment_modes.append(
- `<div class="w-half ${margin} bg-white">
- <div class="mode-of-payment rounded border border-grey text-grey text-md
- mb-4 p-8 pt-4 pb-4 no-select pointer" data-mode="loyalty-amount" data-payment-type="loyalty-amount">
+ `<div class="payment-mode-wrapper">
+ <div class="mode-of-payment" data-mode="loyalty-amount" data-payment-type="loyalty-amount">
Redeem Loyalty Points
- <div class="loyalty-amount-amount pay-amount inline float-right text-bold">${amount}</div>
- <div class="loyalty-amount-name inline float-right text-bold text-md-0 d-none">${loyalty_program}</div>
- <div class="loyalty-amount mode-of-payment-control mt-4 flex flex-1 items-center d-none"></div>
+ <div class="loyalty-amount-amount pay-amount">${amount}</div>
+ <div class="loyalty-amount-name">${loyalty_program}</div>
+ <div class="loyalty-amount mode-of-payment-control"></div>
</div>
</div>`
)
@@ -520,18 +486,24 @@
const label = change ? __('Change') : __('To Be Paid');
this.$totals.html(
- `<div>
- <div class="pr-8 border-r-grey">Paid Amount</div>
- <div class="pr-8 border-r-grey text-bold text-2xl">${format_currency(paid_amount, currency)}</div>
+ `<div class="col">
+ <div class="total-label">Grand Total</div>
+ <div class="value">${format_currency(doc.grand_total, currency)}</div>
</div>
- <div>
- <div class="pl-8">${label}</div>
- <div class="pl-8 text-green-400 text-bold text-2xl">${format_currency(change || remaining, currency)}</div>
+ <div class="seperator-y"></div>
+ <div class="col">
+ <div class="total-label">Paid Amount</div>
+ <div class="value">${format_currency(paid_amount, currency)}</div>
+ </div>
+ <div class="seperator-y"></div>
+ <div class="col">
+ <div class="total-label">${label}</div>
+ <div class="value">${format_currency(change || remaining, currency)}</div>
</div>`
)
}
toggle_component(show) {
- show ? this.$component.removeClass('d-none') : this.$component.addClass('d-none');
+ show ? this.$component.css('display', 'flex') : this.$component.css('display', 'none');
}
}
\ No newline at end of file
diff --git a/erpnext/setup/page/welcome_to_erpnext/welcome_to_erpnext.html b/erpnext/setup/page/welcome_to_erpnext/welcome_to_erpnext.html
index 5808ce7..7166ba3 100644
--- a/erpnext/setup/page/welcome_to_erpnext/welcome_to_erpnext.html
+++ b/erpnext/setup/page/welcome_to_erpnext/welcome_to_erpnext.html
@@ -21,7 +21,6 @@
<h3>{%= __("Next Steps") %}</h3>
<ul class="list-unstyled">
<li><a class="text-muted" href="#">{%= __("Go to the Desktop and start using ERPNext") %}</a></li>
- <li><a class="text-muted" href="#modules/Learn">{%= __("View a list of all the help videos") %}</a></li>
<li><a class="text-muted" href="https://erpnext.com/docs/user" target="_blank">{%= __("Read the ERPNext Manual") %}</a></li>
<li><a class="text-muted" href="https://discuss.erpnext.com" target="_blank">{%= __("Community Forum") %}</a></li>
</ul>
diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js
index 9bd03d4..faa9b5d 100644
--- a/erpnext/stock/dashboard/item_dashboard.js
+++ b/erpnext/stock/dashboard/item_dashboard.js
@@ -198,7 +198,7 @@
freeze: true,
callback: function(r) {
frappe.show_alert(__('Stock Entry {0} created',
- ['<a href="#Form/Stock Entry/'+r.message.name+'">' + r.message.name+ '</a>']));
+ ['<a href="/desk/Form/Stock Entry/'+r.message.name+'">' + r.message.name+ '</a>']));
dialog.hide();
callback(r);
},
diff --git a/erpnext/stock/doctype/batch/batch.js b/erpnext/stock/doctype/batch/batch.js
index 71a3e7a..7b2edff 100644
--- a/erpnext/stock/doctype/batch/batch.js
+++ b/erpnext/stock/doctype/batch/batch.js
@@ -102,7 +102,7 @@
},
callback: (r) => {
frappe.show_alert(__('Stock Entry {0} created',
- ['<a href="#Form/Stock Entry/'+r.message.name+'">' + r.message.name+ '</a>']));
+ ['<a href="/desk/Form/Stock Entry/'+r.message.name+'">' + r.message.name+ '</a>']));
frm.refresh();
},
});
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index faf4acc..43e18d1 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -85,7 +85,7 @@
}
if (frm.doc.variant_of) {
frm.set_intro(__('This Item is a Variant of {0} (Template).',
- [`<a href="#Form/Item/${frm.doc.variant_of}">${frm.doc.variant_of}</a>`]), true);
+ [`<a href="/desk/Form/Item/${frm.doc.variant_of}">${frm.doc.variant_of}</a>`]), true);
}
if (frappe.defaults.get_default("item_naming_by")!="Naming Series" || frm.doc.variant_of) {
@@ -649,7 +649,7 @@
if (r.message) {
var variant = r.message;
frappe.msgprint_dialog = frappe.msgprint(__("Item Variant {0} already exists with same attributes",
- [repl('<a href="#Form/Item/%(item_encoded)s" class="strong variant-click">%(item)s</a>', {
+ [repl('<a href="/desk/Form/Item/%(item_encoded)s" class="strong variant-click">%(item)s</a>', {
item_encoded: encodeURIComponent(variant),
item: variant
})]
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 3b62c38..1993d56 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -860,7 +860,7 @@
rows = ''
for docname, attr_list in not_included.items():
- link = "<a href='#Form/Item/{0}'>{0}</a>".format(frappe.bold(_(docname)))
+ link = "<a href='/app/Form/Item/{0}'>{0}</a>".format(frappe.bold(_(docname)))
rows += table_row(link, body(attr_list))
error_description = _('The following deleted attributes exist in Variants but not in the Template. You can either delete the Variants or keep the attribute(s) in template.')
diff --git a/erpnext/stock/doctype/item_price/item_price.js b/erpnext/stock/doctype/item_price/item_price.js
index 2729f4b..773fddc 100644
--- a/erpnext/stock/doctype/item_price/item_price.js
+++ b/erpnext/stock/doctype/item_price/item_price.js
@@ -14,6 +14,6 @@
frm.add_fetch("item_code", "stock_uom", "uom");
frm.set_df_property("bulk_import_help", "options",
- '<a href="#data-import-tool/Item Price">' + __("Import in Bulk") + '</a>');
+ '<a href="/desk/data-import-tool/Item Price">' + __("Import in Bulk") + '</a>');
}
});
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index 940b940..e58ac22 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -184,7 +184,7 @@
let url = window.location.href
let arr = url.split("/");
let result = arr[0] + "//" + arr[2]
- frappe.msgprint(`New issue created: <a href="${result}/desk#Form/Issue/${r.message}">${r.message}</a>`)
+ frappe.msgprint(`New issue created: <a href="${result}//desk/Form/Issue/${r.message}">${r.message}</a>`)
frm.reload_doc();
dialog.hide();
});
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index 62b39cc..e4e7b25 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -207,7 +207,7 @@
"comment_type": "Info",
"reference_doctype": "Issue",
"reference_name": replicated_issue.name,
- "content": " - Split the Issue from <a href='#Form/Issue/{0}'>{1}</a>".format(self.name, frappe.bold(self.name)),
+ "content": " - Split the Issue from <a href='/app/Form/Issue/{0}'>{1}</a>".format(self.name, frappe.bold(self.name)),
}).insert(ignore_permissions=True)
return replicated_issue.name
diff --git a/erpnext/utilities/bot.py b/erpnext/utilities/bot.py
index 0e5e95d..b2e74da 100644
--- a/erpnext/utilities/bot.py
+++ b/erpnext/utilities/bot.py
@@ -26,12 +26,12 @@
for warehouse in warehouses:
qty = frappe.db.get_value("Bin", {'item_code': item[0], 'warehouse': warehouse.name}, 'actual_qty')
if qty:
- out.append(_('{0} units of [{1}](#Form/Item/{1}) found in [{2}](#Form/Warehouse/{2})').format(qty,
+ out.append(_('{0} units of [{1}](/app/Form/Item/{1}) found in [{2}](/app/Form/Warehouse/{2})').format(qty,
item[0], warehouse.name))
found = True
if not found:
- out.append(_('[{0}](#Form/Item/{0}) is out of stock').format(item[0]))
+ out.append(_('[{0}](/app/Form/Item/{0}) is out of stock').format(item[0]))
return "\n\n".join(out)
diff --git a/package.json b/package.json
index 1b2dc9e..d12661b 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"snyk": "^1.290.1"
},
"dependencies": {
+ "onscan.js": "^1.5.2"
},
"scripts": {
"snyk-protect": "snyk protect",
diff --git a/yarn.lock b/yarn.lock
index 97a0635..e5a2da1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1217,6 +1217,11 @@
dependencies:
mimic-fn "^1.0.0"
+onscan.js@^1.5.2:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/onscan.js/-/onscan.js-1.5.2.tgz#14ed636e5f4c3f0a78bacbf9a505dad3140ee341"
+ integrity sha512-9oGYy2gXYRjvXO9GYqqVca0VuCTAmWhbmX3egBSBP13rXiMNb+dKPJzKFEeECGqPBpf0m40Zoo+GUQ7eCackdw==
+
opn@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc"