Merge pull request #7991 from mbauskar/develop
[minor] display campaign field only if source is Campaign
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
index ac6240a..c7d1291 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
@@ -117,7 +117,7 @@
def get_account_tree_from_existing_company(existing_company):
all_accounts = frappe.get_all('Account',
- filters={'company': existing_company},
+ filters={'company': existing_company, "warehouse": ""},
fields = ["name", "account_name", "parent_account", "account_type",
"is_group", "root_type", "tax_rate"],
order_by="lft, rgt")
@@ -126,7 +126,6 @@
# fill in tree starting with root accounts (those with no parent)
build_account_tree(account_tree, None, all_accounts)
-
return account_tree
def build_account_tree(tree, parent, all_accounts):
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/ae_uae_chart_template_standard.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/ae_uae_chart_template_standard.json
index 9a93423..9d610dc 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/ae_uae_chart_template_standard.json
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/ae_uae_chart_template_standard.json
@@ -88,10 +88,7 @@
"Items Delivered to Customs on temprary Base": {}
},
"Stock in Hand": {
- "All Warehouses": {
- "account_type": "Stock",
- "is_group": 1
- },
+ "is_group": 1,
"account_type": "Stock"
}
},
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/sg_default_coa.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/sg_default_coa.json
index 58a89b5..976150f 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/sg_default_coa.json
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/sg_default_coa.json
@@ -40,10 +40,7 @@
"Rental Deposits": {}
},
"Stock Assets": {
- "All Warehouses": {
- "account_type": "Stock",
- "is_group": 1
- },
+ "is_group": 1,
"account_type": "Stock"
},
"Tax Assets": {
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 9bb3fe4..06724b1 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -10,6 +10,7 @@
from erpnext.setup.utils import get_company_currency
from erpnext.accounts.party import get_party_account
from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
+from erpnext.hr.doctype.employee_loan.employee_loan import update_disbursement_status
class JournalEntry(AccountsController):
def __init__(self, arg1, arg2=None):
@@ -46,6 +47,7 @@
self.make_gl_entries()
self.update_advance_paid()
self.update_expense_claim()
+ self.update_employee_loan()
def get_title(self):
return self.pay_to_recd_from or self.accounts[0].account
@@ -69,6 +71,7 @@
self.make_gl_entries(1)
self.update_advance_paid()
self.update_expense_claim()
+ self.update_employee_loan()
self.unlink_advance_entry_reference()
def unlink_advance_entry_reference(self):
@@ -503,6 +506,12 @@
doc = frappe.get_doc("Expense Claim", d.reference_name)
update_reimbursed_amount(doc)
+ def update_employee_loan(self):
+ for d in self.accounts:
+ if d.reference_type=="Employee Loan" and flt(d.debit) > 0:
+ doc = frappe.get_doc("Employee Loan", d.reference_name)
+ update_disbursement_status(doc)
+
def validate_expense_claim(self):
for d in self.accounts:
if d.reference_type=="Expense Claim":
diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
index 0bd6f86..54af579 100644
--- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
+++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
@@ -8,6 +8,7 @@
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
+ "document_type": "Document",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
@@ -596,7 +597,7 @@
"label": "Reference Type",
"length": 0,
"no_copy": 0,
- "options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset",
+ "options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset\nEmployee Loan",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -768,7 +769,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2017-02-17 16:28:35.118357",
+ "modified": "2017-03-02 05:02:10.102039",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry Account",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 02d2b6b..d42bcd5 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -684,6 +684,7 @@
pe.paid_amount = paid_amount
pe.received_amount = received_amount
pe.allocate_payment_amount = 1
+ pe.letter_head = doc.get("letter_head")
pe.append("references", {
"reference_doctype": dt,
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json
index a25dd51..9232cd3 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.json
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "hash",
@@ -21,7 +22,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
+ "in_standard_filter": 0,
"label": "Applicable for User",
"length": 0,
"no_copy": 0,
@@ -50,7 +53,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
+ "in_standard_filter": 0,
"label": "Series",
"length": 0,
"no_copy": 1,
@@ -81,7 +86,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Update Stock",
"length": 0,
"no_copy": 0,
@@ -108,7 +115,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Warehouse",
"length": 0,
"no_copy": 0,
@@ -137,7 +146,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Campaign",
"length": 0,
"no_copy": 0,
@@ -165,7 +176,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -191,7 +204,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Customer",
"length": 0,
"no_copy": 0,
@@ -220,7 +235,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
+ "in_standard_filter": 0,
"label": "Company",
"length": 0,
"no_copy": 0,
@@ -243,13 +260,45 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "country",
+ "fieldtype": "Read Only",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Country",
+ "length": 0,
+ "no_copy": 0,
+ "options": "company.country",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "currency",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Currency",
"length": 0,
"no_copy": 0,
@@ -278,7 +327,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Ignore Pricing Rule",
"length": 0,
"no_copy": 0,
@@ -305,7 +356,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Allow Delete",
"length": 0,
"no_copy": 0,
@@ -332,7 +385,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Allow user to edit Rate",
"length": 0,
"no_copy": 0,
@@ -359,7 +414,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -385,7 +442,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Sales Invoice Payment",
"length": 0,
"no_copy": 0,
@@ -413,7 +472,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -439,7 +500,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Item Groups",
"length": 0,
"no_copy": 0,
@@ -467,7 +530,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -493,7 +558,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Customer Groups",
"length": 0,
"no_copy": 0,
@@ -521,7 +588,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -548,7 +617,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Print Format",
"length": 0,
"no_copy": 0,
@@ -576,7 +647,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Letter Head",
"length": 0,
"no_copy": 0,
@@ -605,7 +678,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Print Heading",
"length": 0,
"no_copy": 0,
@@ -634,7 +709,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Terms and Conditions",
"length": 0,
"no_copy": 0,
@@ -663,7 +740,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"oldfieldtype": "Column Break",
@@ -690,7 +769,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 1,
+ "in_standard_filter": 0,
"label": "Territory",
"length": 0,
"no_copy": 0,
@@ -719,7 +800,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Price List",
"length": 0,
"no_copy": 0,
@@ -748,7 +831,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Apply Discount",
"length": 0,
"no_copy": 0,
@@ -777,7 +862,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Apply Discount On",
"length": 0,
"no_copy": 0,
@@ -805,7 +892,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -832,7 +921,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Write Off Account",
"length": 0,
"no_copy": 0,
@@ -860,7 +951,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Write Off Cost Center",
"length": 0,
"no_copy": 0,
@@ -888,7 +981,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Account for Change Amount",
"length": 0,
"no_copy": 0,
@@ -916,7 +1011,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Taxes and Charges",
"length": 0,
"no_copy": 0,
@@ -945,7 +1042,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -971,7 +1070,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Income Account",
"length": 0,
"no_copy": 0,
@@ -1001,7 +1102,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Expense Account",
"length": 0,
"no_copy": 0,
@@ -1028,7 +1131,9 @@
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
+ "in_global_search": 0,
"in_list_view": 0,
+ "in_standard_filter": 0,
"label": "Cost Center",
"length": 0,
"no_copy": 0,
@@ -1047,18 +1152,18 @@
"unique": 0
}
],
+ "has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-cog",
"idx": 1,
"image_view": 0,
"in_create": 0,
- "in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-12-28 15:14:59.411457",
+ "modified": "2017-03-10 16:53:56.390210",
"modified_by": "rohit@erpnext.com",
"module": "Accounts",
"name": "POS Profile",
@@ -1074,7 +1179,6 @@
"export": 0,
"if_owner": 0,
"import": 0,
- "is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
@@ -1095,7 +1199,6 @@
"export": 0,
"if_owner": 0,
"import": 0,
- "is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
@@ -1110,8 +1213,10 @@
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
+ "show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "user",
+ "track_changes": 0,
"track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index 070dbeb..cfbd1b2 100644
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -5,6 +5,7 @@
import frappe, json
from frappe.utils import nowdate
from erpnext.setup.utils import get_exchange_rate
+from frappe.core.doctype.communication.email import make
from erpnext.stock.get_item_details import get_pos_profile
from erpnext.accounts.party import get_party_account_currency
from erpnext.controllers.accounts_controller import get_taxes_and_charges
@@ -25,13 +26,15 @@
update_multi_mode_option(doc, pos_profile)
default_print_format = pos_profile.get('print_format') or "Point of Sale"
print_template = frappe.db.get_value('Print Format', default_print_format, 'html')
+ customers = get_customers_list(pos_profile)
return {
'doc': doc,
'default_customer': pos_profile.get('customer'),
'items': get_items_list(pos_profile),
'item_groups': get_item_group(pos_profile),
- 'customers': get_customers_list(pos_profile),
+ 'customers': customers,
+ 'address': get_customers_address(customers),
'serial_no_data': get_serial_no_data(pos_profile, doc.company),
'batch_no_data': get_batch_no_data(),
'tax_data': get_item_tax_data(),
@@ -60,6 +63,8 @@
def update_pos_profile_data(doc, pos_profile, company_data):
doc.campaign = pos_profile.get('campaign')
+ if not pos_profile.get('country'):
+ pos_profile["country"] = company_data.country
doc.write_off_account = pos_profile.get('write_off_account') or \
company_data.write_off_account
@@ -163,6 +168,19 @@
territory from tabCustomer where disabled = 0
and {cond}""".format(cond=cond), tuple(customer_groups), as_dict=1) or {}
+def get_customers_address(customers):
+ customer_address = {}
+ for data in customers:
+ address = frappe.db.sql(""" select name, address_line1, address_line2, city, state,
+ email_id, phone, fax, pincode from `tabAddress` where is_primary_address =1 and name in
+ (select parent from `tabDynamic Link` where link_doctype = 'Customer' and link_name = %s
+ and parenttype = 'Address')""", data.name, as_dict=1)
+ if address:
+ address_data = address[0]
+ address_data.update({'full_name': data.customer_name})
+ customer_address[data.name] = address_data
+ return customer_address
+
def get_child_nodes(group_type, root):
lft, rgt = frappe.db.get_value(group_type, root, ["lft", "rgt"])
return frappe.db.sql_list(""" Select name from `tab{tab}` where
@@ -257,12 +275,18 @@
return pricing_rules
@frappe.whitelist()
-def make_invoice(doc_list):
+def make_invoice(doc_list={}, email_queue_list={}, customers_list={}):
if isinstance(doc_list, basestring):
doc_list = json.loads(doc_list)
- name_list = []
+ if isinstance(email_queue_list, basestring):
+ email_queue_list = json.loads(email_queue_list)
+ if isinstance(customers_list, basestring):
+ customers_list = json.loads(customers_list)
+
+ customers = make_customer_and_address(customers_list)
+ name_list = []
for docs in doc_list:
for name, doc in docs.items():
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
@@ -270,49 +294,72 @@
si_doc = frappe.new_doc('Sales Invoice')
si_doc.offline_pos_name = name
si_doc.update(doc)
- submit_invoice(si_doc, name)
+ submit_invoice(si_doc, name, doc)
name_list.append(name)
else:
name_list.append(name)
- return name_list
+ email_queue = make_email_queue(email_queue_list)
+ return {
+ 'invoice': name_list,
+ 'email_queue': email_queue,
+ 'customers': customers
+ }
def validate_records(doc):
- validate_customer(doc)
validate_item(doc)
-def validate_customer(doc):
- if not frappe.db.exists('Customer', doc.get('customer')):
- customer_doc = frappe.new_doc('Customer')
- customer_doc.customer_name = doc.get('customer')
- customer_doc.customer_type = 'Company'
- customer_doc.customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group')
- customer_doc.territory = frappe.db.get_single_value('Selling Settings', 'territory')
- customer_doc.flags.ignore_mandatory = True
- customer_doc.save(ignore_permissions = True)
- frappe.db.commit()
- doc['customer'] = customer_doc.name
- if doc.get('contact_details'):
- args = json.loads(doc.get("contact_details"))
- make_address(doc, args, customer_doc.name)
+def make_customer_and_address(customers):
+ customer_list = []
+ for name, data in customers.items():
+ if not frappe.db.exists('Customer', name):
+ name = add_customer(name)
+ data = json.loads(data)
+ make_address(data, name)
+ customer_list.append(name)
+ return customer_list
-def make_address(doc, args, customer):
- if args.get("address_line1"):
+def add_customer(name):
+ customer_doc = frappe.new_doc('Customer')
+ customer_doc.customer_name = name
+ customer_doc.customer_type = 'Company'
+ customer_doc.customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group')
+ customer_doc.territory = frappe.db.get_single_value('Selling Settings', 'territory')
+ customer_doc.flags.ignore_mandatory = True
+ customer_doc.save(ignore_permissions = True)
+ frappe.db.commit()
+
+def make_address(args, customer):
+ if args.get('name'):
+ address = frappe.get_doc('Address', args.get('name'))
+ else:
address = frappe.new_doc('Address')
- address.address_line1 = args.get('address_line1')
- address.address_line2 = args.get('address_line2')
- address.city = args.get('city')
- address.state = args.get('state')
- address.zip_code = args.get('zip_code')
- address.email_id = args.get('email_id')
- address.flags.ignore_mandatory = True
- address.country = frappe.db.get_value('Company', doc.get('company'), 'country')
+ address.country = frappe.db.get_value('Company', args.get('company'), 'country')
address.append('links',{
'link_doctype': 'Customer',
'link_name': customer
})
- address.save(ignore_permissions = True)
- frappe.db.commit()
+
+ address.is_primary_address = 1
+ address.is_shipping_address = 1
+ address.update(args)
+ address.save(ignore_permissions = True)
+
+def make_email_queue(email_queue):
+ name_list = []
+ for key, data in email_queue.items():
+ name = frappe.db.get_value('Sales Invoice', {'offline_pos_name': key}, 'name')
+ data = json.loads(data)
+ sender = frappe.session.user
+ print_format = "POS Invoice"
+ attachments = [frappe.attach_print('Sales Invoice', name, print_format= print_format)]
+
+ make(subject = data.get('subject'), content = data.get('content'), recipients = data.get('recipients'),
+ sender=sender,attachments = attachments, send_email=True,
+ doctype='Sales Invoice', name=name)
+ name_list.append(key)
+
+ return name_list
def validate_item(doc):
for item in doc.get('items'):
@@ -328,7 +375,8 @@
item_doc.save(ignore_permissions=True)
frappe.db.commit()
-def submit_invoice(si_doc, name):
+
+def submit_invoice(si_doc, name, doc):
try:
si_doc.insert()
si_doc.submit()
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 3dfe680..f3d311b 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -558,7 +558,7 @@
{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 330}]
invoice_data = [{'09052016142': pos}]
- si = make_invoice(invoice_data)
+ si = make_invoice(invoice_data).get('invoice')
self.assertEquals(si[0], '09052016142')
sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': '09052016142', 'docstatus': 1})
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index ed54ab4..b86f9e1 100644
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -25,6 +25,7 @@
this.set_indicator();
this.onload();
this.make_menu_list();
+ this.bind_events();
this.si_docs = this.get_doc_from_localstorage();
},
@@ -95,19 +96,76 @@
me.sync_sales_invoice()
});
+ this.page.add_menu_item(__("Email"), function () {
+ if(me.frm.doc.docstatus == 1) {
+ me.email_prompt()
+ }
+ });
+
this.page.add_menu_item(__("POS Profile"), function () {
frappe.set_route('List', 'POS Profile');
});
},
+ email_prompt: function() {
+ var me = this;
+ fields = [{label:__("To"), fieldtype:"Data", reqd: 0, fieldname:"recipients",length:524288},
+ {fieldtype: "Section Break", collapsible: 1, label: "CC & Standard Reply"},
+ {fieldtype: "Section Break"},
+ {label:__("Subject"), fieldtype:"Data", reqd: 1,
+ fieldname:"subject",length:524288},
+ {fieldtype: "Section Break"},
+ {label:__("Message"), fieldtype:"Text Editor", reqd: 1,
+ fieldname:"content"},
+ {fieldtype: "Section Break"},
+ {fieldtype: "Column Break"}];
+
+ this.email_dialog = new frappe.ui.Dialog({
+ title: "Email",
+ fields: fields,
+ primary_action_label: __("Send"),
+ primary_action: function() {
+ me.send_action();
+ }
+ });
+
+ this.email_dialog.show()
+ },
+
+ send_action: function() {
+ this.email_queue = this.get_email_queue()
+ this.email_queue[this.frm.doc.offline_pos_name] = JSON.stringify(this.email_dialog.get_values())
+ this.update_email_queue()
+ this.email_dialog.hide()
+ },
+
+ update_email_queue: function () {
+ try {
+ localStorage.setItem('email_queue', JSON.stringify(this.email_queue));
+ } catch (e) {
+ frappe.throw(__("LocalStorage is full, did not save"))
+ }
+ },
+
+ get_email_queue: function () {
+ try {
+ return JSON.parse(localStorage.getItem('email_queue')) || {};
+ } catch (e) {
+ return {}
+ }
+ },
+
+ get_customers_details: function () {
+ try {
+ return JSON.parse(localStorage.getItem('customer_details')) || {};
+ } catch (e) {
+ return {}
+ }
+ },
+
dialog_actions: function () {
var me = this;
- $(this.list_body).find('.list-column').click(function () {
- me.name = $(this).parents().attr('invoice-name')
- me.edit_record();
- })
-
$(this.list_body).find('.list-select-all').click(function () {
me.removed_items = [];
$(me.list_body).find('.list-delete').prop("checked", $(this).is(":checked"))
@@ -119,7 +177,7 @@
})
}
- me.toggle_primary_action();
+ me.toggle_delete_button();
})
$(this.list_body).find('.list-delete').click(function () {
@@ -130,7 +188,7 @@
me.removed_items.pop(me.name)
}
- me.toggle_primary_action();
+ me.toggle_delete_button();
})
},
@@ -142,26 +200,39 @@
this.frm.doc = doc_data[0][this.name];
this.set_missing_values();
this.refresh(false);
- this.disable_input_field();
+ this.toggle_input_field();
this.list_dialog && this.list_dialog.hide();
}
},
delete_records: function () {
var me = this;
+ this.validate_list()
this.remove_doc_from_localstorage()
this.update_localstorage();
- this.dialog_actions();
- this.toggle_primary_action();
+ // this.dialog_actions();
+ this.toggle_delete_button();
},
- toggle_primary_action: function () {
+ validate_list: function() {
var me = this;
- if(this.frm.doc.allow_delete) {
+ this.si_docs = this.get_submitted_invoice()
+ $.each(this.removed_items, function(index, name){
+ $.each(me.si_docs, function(key, data){
+ if(me.si_docs[key][name] && me.si_docs[key][name].offline_pos_name == name ){
+ frappe.throw(__("Submitted orders can not be deleted"))
+ }
+ })
+ })
+ },
+
+ toggle_delete_button: function () {
+ var me = this;
+ if(this.pos_profile_data["allow_delete"]) {
if (this.removed_items && this.removed_items.length > 0) {
- $(this.wrapper).find('.btn-danger').show();
+ $(this.page.wrapper).find('.btn-danger').show();
} else {
- $(this.wrapper).find('.btn-danger').hide();
+ $(this.page.wrapper).find('.btn-danger').hide();
}
}
},
@@ -215,8 +286,8 @@
freeze: true,
freeze_message: __("Master data syncing, it might take some time"),
callback: function (r) {
- me.init_master_data(r)
localStorage.setItem('doc', JSON.stringify(r.message.doc));
+ me.init_master_data(r)
me.set_interval_for_si_sync();
me.check_internet_connection();
if (callback) {
@@ -228,6 +299,7 @@
init_master_data: function (r) {
var me = this;
+ this.doc = JSON.parse(localStorage.getItem('doc'));
this.meta = r.message.meta;
this.item_data = r.message.items;
this.item_groups = r.message.item_groups;
@@ -235,6 +307,7 @@
this.serial_no_data = r.message.serial_no_data;
this.batch_no_data = r.message.batch_no_data;
this.tax_data = r.message.tax_data;
+ this.address = r.message.address || {};
this.price_list_data = r.message.price_list_data;
this.bin_data = r.message.bin_data;
this.pricing_rules = r.message.pricing_rules;
@@ -243,6 +316,7 @@
this.default_customer = r.message.default_customer || null;
this.print_settings = locals[":Print Settings"]["Print Settings"];
this.letter_head = (this.pos_profile_data.length > 0) ? frappe.boot.letter_heads[this.pos_profile_data[letter_head]] : {};
+ this.make_control()
},
save_previous_entry: function () {
@@ -282,11 +356,12 @@
},
setup: function () {
- this.frm.doc.allow_delete = this.pos_profile_data["allow_delete"];
- this.wrapper.html(frappe.render_template("pos", this.frm.doc));
- this.set_transaction_defaults("Customer");
this.make();
this.set_primary_action();
+ this.party_field.$input.attr('disabled', false);
+ if(this.selected_row) {
+ this.selected_row.hide()
+ }
},
set_transaction_defaults: function (party) {
@@ -299,12 +374,20 @@
},
make: function () {
- this.make_search();
- this.make_list_customers();
- this.make_customer();
this.make_item_list();
this.make_discount_field()
},
+
+ make_control: function() {
+ this.frm = {}
+ this.frm.doc = this.doc
+ this.set_transaction_defaults("Customer");
+ this.wrapper.html(frappe.render_template("pos", this.frm.doc));
+ this.make_search();
+ this.make_customer();
+ this.make_list_customers();
+ this.bind_numeric_keypad();
+ },
make_search: function () {
var me = this;
@@ -327,68 +410,98 @@
}, 1000);
});
- this.search_item_group = frappe.ui.form.make_control({
- df: {
- "fieldtype": "Select",
- "options": me.item_groups,
- "label": __("Item Group"),
- "fieldname": "item_group",
- "placeholder": __("Item Group")
- },
- parent: this.wrapper.find(".search-item-group"),
- only_input: true,
- });
+ this.search_item_group = this.wrapper.find('.search-item-group');
- this.search_item_group.make_input();
- this.search_item_group.$input.on("change", function () {
+ var dropdown_html = me.item_groups.map(function(item_group) {
+ return "<li><a class='option' data-value='"+item_group+"'>"+item_group+"</a></li>";
+ }).join("");
+
+ this.search_item_group.find('.dropdown-menu').html(dropdown_html);
+
+ this.search_item_group.on('click', '.dropdown-menu a', function() {
+ me.selected_item_group = $(this).attr('data-value');
+ me.search_item_group.find('.dropdown-text').text(me.selected_item_group);
+
me.page_len = 20;
me.items = me.get_items();
me.make_item_list();
- });
+ })
- this.party_field = frappe.ui.form.make_control({
- df: {
- "fieldtype": "Data",
- "options": this.party,
- "label": this.party,
- "fieldname": this.party.toLowerCase(),
- "placeholder": __("Select or add new customer")
- },
- parent: this.wrapper.find(".party-area"),
- only_input: true,
- });
+ me.toggle_more_btn();
- this.party_field.make_input();
- setTimeout(this.set_focus.bind(this), 500);
-
- this.wrapper.find(".btn-more").on("click", function() {
+ this.wrapper.on("click", ".btn-more", function() {
me.page_len += 20;
me.items = me.get_items();
me.make_item_list();
+ me.toggle_more_btn();
+ });
+
+ this.page.wrapper.on("click", ".edit-customer-btn", function() {
+ me.update_customer()
})
},
+ toggle_more_btn: function() {
+ if(!this.items || this.items.length <= this.page_len) {
+ this.wrapper.find(".btn-more").hide();
+ } else {
+ this.wrapper.find(".btn-more").show();
+ }
+ },
+
+ toggle_totals_area: function(show) {
+
+ if(show === undefined) {
+ show = this.is_totals_area_collapsed;
+ }
+
+ var totals_area = this.wrapper.find('.totals-area');
+ totals_area.find('.net-total-area, .tax-area, .discount-amount-area')
+ .toggle(show);
+
+ if(show) {
+ totals_area.find('.collapse-btn i')
+ .removeClass('octicon-chevron-down')
+ .addClass('octicon-chevron-up');
+ } else {
+ totals_area.find('.collapse-btn i')
+ .removeClass('octicon-chevron-up')
+ .addClass('octicon-chevron-down');
+ }
+
+ this.is_totals_area_collapsed = !show;
+ },
+
make_list_customers: function () {
var me = this;
- this.list_customers_btn = this.wrapper.find('.list-customers-btn');
+ this.list_customers_btn = this.page.wrapper.find('.list-customers-btn');
this.add_customer_btn = this.wrapper.find('.add-customer-btn');
- this.pos_bill = this.wrapper.find('.pos-bill').hide();
+ this.pos_bill = this.wrapper.find('.pos-bill-wrapper').hide();
this.list_customers = this.wrapper.find('.list-customers');
+ this.numeric_keypad = this.wrapper.find('.numeric_keypad');
- this.list_customers_btn.on('click', function () {
+ me.render_list_customers();
+ me.toggle_totals_area(false);
+
+ this.page.wrapper.on('click', '.list-customers-btn', function() {
$(this).toggleClass("view_customer");
if($(this).hasClass("view_customer")) {
me.render_list_customers();
- me.bind_delete_event()
- me.party_field.$input.attr('disabled', true);
me.list_customers.show();
me.pos_bill.hide();
+ me.numeric_keypad.hide();
+ me.toggle_delete_button()
} else {
if(me.frm.doc.docstatus == 0) {
me.party_field.$input.attr('disabled', false);
}
me.pos_bill.show();
- me.list_customers.hide()
+ me.toggle_totals_area(false);
+ me.toggle_delete_button()
+ me.list_customers.hide();
+ if(me.frm.doc.items.length > 0) {
+ me.numeric_keypad.show();
+ }
}
});
this.add_customer_btn.on('click', function() {
@@ -397,44 +510,86 @@
me.refresh();
me.set_focus();
});
+ this.pos_bill.on('click', '.collapse-btn', function() {
+ me.toggle_totals_area();
+ });
+ },
+
+ bind_numeric_keypad: function() {
+ var me = this;
+ $(this.numeric_keypad).find('.pos-operation').on('click', function(){
+ me.numeric_val = '';
+ })
+
+ $(this.numeric_keypad).find('.numeric-keypad').on('click', function(){
+ me.numeric_id = $(this).attr("id") || me.numeric_id;
+ me.val = $(this).attr("val")
+ if(me.numeric_id) {
+ me.selected_field = $(me.wrapper).find('.selected-item').find('.' + me.numeric_id)
+ }
+
+ if(me.val && me.numeric_id) {
+ me.numeric_val += me.val;
+ me.selected_field.val(flt(me.numeric_val))
+ me.selected_field.trigger("change")
+ // me.render_selected_item()
+ }
+
+ if(me.numeric_id && $(this).hasClass('pos-operation')) {
+ me.numeric_keypad.find('button.pos-operation').removeClass('active');
+ $(this).addClass('active');
+
+ me.selected_row.find('.pos-list-row').removeClass('active');
+ me.selected_field.closest('.pos-list-row').addClass('active');
+ }
+ })
+
+ $(this.numeric_keypad).find('.numeric-del').click(function(){
+ me.selected_field = $(me.wrapper).find('.selected-item').find('.' + me.numeric_id)
+ me.numeric_val = cstr(flt(me.selected_field.val())).slice(0, -1);
+ me.selected_field.val(me.numeric_val);
+ me.selected_field.trigger("change")
+ // me.render_selected_item()
+ })
+
+ $(this.numeric_keypad).find('.pos-pay').click(function(){
+ me.validate();
+ me.update_paid_amount_status(true);
+ me.create_invoice();
+ me.make_payment();
+ })
},
render_list_customers: function () {
var me = this;
this.removed_items = [];
- this.list_customers.empty();
+ // this.list_customers.empty();
this.si_docs = this.get_doc_from_localstorage();
-
if (!this.si_docs.length) {
- this.list_customers.append(
- '<div style="padding: 12px; margin-left:-12px;">' + __("No offline records.") + '</div>'
- )
return;
}
- var html = '<div class="row list-row list-row-head pos-invoice-list">\
- <div class="col-xs-1"><input class="list-select-all" type="checkbox"></div>\
- <div class="col-xs-3">Customer</div>\
- <div class="col-xs-2 text-left">Status</div>\
- <div class="col-xs-3 text-right">Paid Amount</div>\
- <div class="col-xs-3 text-right">Grand Total</div>\
- </div>';
- this.si_docs.forEach(function (data, i) {
- for (key in data) {
- html += frappe.render_template("pos_invoice_list", {
- sr: i + 1,
- name: key,
- customer: data[key].customer,
- paid_amount: format_currency(data[key].paid_amount, me.frm.doc.currency),
- grand_total: format_currency(data[key].grand_total, me.frm.doc.currency),
- data: me.get_doctype_status(data[key])
- });
- }
- });
- this.list_customers.append(html);
- this.list_customers.find('.list-column').click(function () {
+ var html = "";
+ if(this.si_docs.length) {
+ this.si_docs.forEach(function (data, i) {
+ for (key in data) {
+ html += frappe.render_template("pos_invoice_list", {
+ sr: i + 1,
+ name: key,
+ customer: data[key].customer,
+ paid_amount: format_currency(data[key].paid_amount, me.frm.doc.currency),
+ grand_total: format_currency(data[key].grand_total, me.frm.doc.currency),
+ data: me.get_doctype_status(data[key])
+ });
+ }
+ });
+ }
+ this.list_customers.find('.list-customers-table').html(html);
+
+ this.list_customers.on('click', '.customer-row', function () {
me.list_customers.hide();
+ me.numeric_keypad.show();
me.list_customers_btn.toggleClass("view_customer");
me.pos_bill.show();
me.list_customers_btn.show();
@@ -454,7 +609,7 @@
});
}
- me.toggle_primary_action();
+ me.toggle_delete_button();
});
$(this.wrapper).find('.list-delete').click(function () {
@@ -465,16 +620,17 @@
me.removed_items.pop(me.name)
}
- me.toggle_primary_action();
+ me.toggle_delete_button();
});
},
bind_delete_event: function() {
var me = this;
- $(this.wrapper).find('.btn-danger').click(function(){
+ $(this.page.wrapper).on('click', '.btn-danger', function(){
frappe.confirm(__("Delete permanently?"), function () {
me.delete_records();
+ me.list_customers.find('.list-customers-table').html("");
me.render_list_customers();
})
})
@@ -491,6 +647,30 @@
make_customer: function () {
var me = this;
+ if(!this.party_field) {
+ if(this.page.wrapper.find('.pos-bill-toolbar').length === 0) {
+ $(frappe.render_template('customer_toolbar', {
+ allow_delete: this.pos_profile_data["allow_delete"]
+ })).insertAfter(this.page.$title_area.hide());
+ }
+
+ this.party_field = frappe.ui.form.make_control({
+ df: {
+ "fieldtype": "Data",
+ "options": this.party,
+ "label": this.party,
+ "fieldname": this.party.toLowerCase(),
+ "placeholder": __("Select or add new customer")
+ },
+ parent: this.page.wrapper.find(".party-area"),
+ only_input: true,
+ });
+
+ this.party_field.make_input();
+ setTimeout(this.set_focus.bind(this), 500);
+ me.toggle_delete_button();
+ }
+
if (this.default_customer && !this.frm.doc.customer) {
this.party_field.$input.val(this.default_customer);
this.frm.doc.customer = this.default_customer;
@@ -533,7 +713,7 @@
+ __("Create a new Customer")
+ "</span>",
value: 'is_action',
- action: me.new_customer
+ action: me.add_customer
});
this.party_field.awesomeplete.list = customers;
@@ -550,17 +730,23 @@
customer.action.apply(me);
return;
}
+ me.toggle_list_customer(false);
+ me.toggle_edit_button(true);
me.update_customer_data(customer);
me.refresh();
me.set_focus();
})
- .on('change', function (e) {
- if (!e.originalEvent.text) {
- me.frm.doc.customer = $(this).val();
- }
- })
.on('focus', function (e) {
$(e.target).val('').trigger('input');
+ me.toggle_edit_button(false);
+
+ if(me.frm.doc.items.length) {
+ me.toggle_list_customer(false)
+ me.toggle_item_cart(true)
+ } else {
+ me.toggle_list_customer(true)
+ me.toggle_item_cart(false)
+ }
})
.on("awesomplete-selectcomplete", function (e) {
var item = me.party_field.awesomeplete
@@ -572,7 +758,24 @@
});
},
- new_customer: function () {
+ toggle_edit_button: function(flag) {
+ this.page.wrapper.find('.edit-customer-btn').toggle(flag);
+ },
+
+ toggle_list_customer: function(flag) {
+ this.list_customers.toggle(flag);
+ },
+
+ toggle_item_cart: function(flag) {
+ this.wrapper.find('.pos-bill-wrapper').toggle(flag);
+ },
+
+ add_customer: function() {
+ this.frm.doc.customer = "";
+ this.update_customer()
+ },
+
+ update_customer: function () {
var me = this;
if (!this.connection_status) return;
@@ -598,13 +801,19 @@
},
{
"label": __("Contact Number"),
- "fieldname": "contact_no",
+ "fieldname": "phone",
"fieldtype": "Data"
},
{
"fieldtype": "Section Break"
},
{
+ "label": __("Address Name"),
+ "read_only": 1,
+ "fieldname": "name",
+ "fieldtype": "Data"
+ },
+ {
"label": __("Address Line 1"),
"fieldname": "address_line1",
"fieldtype": "Data"
@@ -629,13 +838,14 @@
},
{
"label": __("ZIP Code"),
- "fieldname": "zip_code",
+ "fieldname": "pincode",
"fieldtype": "Data"
}
]
})
this.customer_doc.show()
+ this.render_address_data()
this.customer_doc.set_primary_action(__("Save"), function () {
me.make_offline_customer();
@@ -643,18 +853,41 @@
});
},
+ render_address_data: function() {
+ var me = this;
+ this.address_data = this.address[this.frm.doc.customer] || this.get_address_from_localstorage();
+ this.customer_doc.set_values(this.address_data)
+
+ if(!this.customer_doc.fields_dict.full_name.$input.val()) {
+ this.customer_doc.set_value("full_name", this.frm.doc.customer)
+ }
+ },
+
+ get_address_from_localstorage: function() {
+ this.address_details = this.get_customers_details()
+ return this.address_details[this.frm.doc.customer]
+ },
+
make_offline_customer: function() {
- this.frm.doc.customer = this.customer_doc.get_values().full_name;
- this.frm.doc.contact_details = JSON.stringify(this.customer_doc.get_values());
+ this.frm.doc.customer = this.frm.doc.customer || this.customer_doc.get_values().full_name;
+ this.customer_details = this.get_customers_details();
+ this.customer_details[this.frm.doc.customer] = this.get_prompt_details();
this.party_field.$input.val(this.frm.doc.customer);
this.customers.push({
name: this.frm.doc.customer,
customer_name: this.frm.doc.customer
});
-
+ this.update_customer_in_localstorage()
+ this.update_customer_in_localstorage()
this.customer_doc.hide()
},
+ get_prompt_details: function() {
+ this.prompt_details = this.customer_doc.get_values();
+ this.prompt_details['country'] = this.pos_profile_data.country;
+ return JSON.stringify(this.prompt_details)
+ },
+
update_customer_data: function (doc) {
var me = this;
this.frm.doc.customer = doc.label || doc.name;
@@ -662,6 +895,7 @@
this.frm.doc.customer_group = doc.customer_group;
this.frm.doc.territory = doc.territory;
this.pos_bill.show();
+ this.numeric_keypad.show();
},
get_customers: function (key) {
@@ -698,17 +932,28 @@
if (this.items.length > 0) {
$.each(this.items, function(index, obj) {
- if(index < me.page_len){
+ if(index < me.page_len) {
$(frappe.render_template("pos_item", {
item_code: obj.name,
item_price: format_currency(me.price_list_data[obj.name], me.frm.doc.currency),
item_name: obj.name === obj.item_name ? "" : obj.item_name,
- item_image: obj.image ? "url('" + obj.image + "')" : null,
+ item_image: obj.image,
color: frappe.get_palette(obj.item_name),
abbr: frappe.get_abbr(obj.item_name)
})).tooltip().appendTo($wrap);
}
});
+
+ $wrap.append(`
+ <div class="image-view-item btn-more text-muted text-center">
+ <div class="image-view-body">
+ <i class="mega-octicon octicon-package"></i>
+ <div>Load more items</div>
+ </div>
+ </div>
+ `);
+
+ me.toggle_more_btn();
} else {
$("<p class='text-muted small' style='padding-left: 10px'>"
+__("Not items found")+"</p>").appendTo($wrap)
@@ -719,17 +964,6 @@
this.serach_item.$input.val("");
this.add_to_cart();
}
-
- // if form is local then allow this function
- $(me.wrapper).find("div.pos-item").on("click", function () {
- if(me.list_customers_btn.hasClass("view_customer")) return;
-
- me.customer_validate();
- if (me.frm.doc.docstatus == 0) {
- me.items = me.get_items($(this).attr("data-item-code"))
- me.add_to_cart();
- }
- });
},
get_items: function (item_code) {
@@ -781,7 +1015,7 @@
apply_category: function() {
var me = this;
- category = this.search_item_group.$input.val();
+ category = this.selected_item_group || "All Item Groups";
if(category == 'All Item Groups') {
return this.item_data
@@ -791,14 +1025,30 @@
});
}
},
+
+ bind_items_event: function() {
+ var me = this;
+ $(this.wrapper).on('click', '.pos-bill-item', function() {
+ $(me.wrapper).find('.pos-bill-item').removeClass('active');
+ $(this).addClass('active');
+ me.numeric_val = "";
+ me.numeric_id = ""
+ me.item_code = $(this).attr("data-item-code");
+ me.render_selected_item()
+ me.bind_qty_event()
+ me.update_rate()
+ $(me.wrapper).find(".selected-item").scrollTop(1000);
+ })
+ },
bind_qty_event: function () {
var me = this;
-
- $(this.wrapper).find(".pos-item-qty").on("change", function () {
- var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
+
+ $(this.wrapper).on("change", ".pos-item-qty", function () {
+ var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
var qty = $(this).val();
me.update_qty(item_code, qty)
+ me.render_selected_item()
})
$(this.wrapper).find("[data-action='increase-qty']").on("click", function () {
@@ -812,14 +1062,32 @@
var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) - 1;
me.update_qty(item_code, qty)
})
-
- $(this.wrapper).find(".pos-item-discount").on("change", function () {
- var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
+
+ $(this.wrapper).on("change", ".pos-item-disc", function () {
+ var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
var discount = $(this).val();
me.update_discount(item_code, discount)
+ me.render_selected_item()
})
},
+ bind_events: function() {
+ var me = this;
+ // if form is local then allow this function
+ // $(me.wrapper).find(".pos-item-wrapper").on("click", function () {
+ $(this.wrapper).on("click", ".pos-item-wrapper", function () {
+ if(me.list_customers_btn.hasClass("view_customer")) return;
+
+ me.customer_validate();
+ if (me.frm.doc.docstatus == 0) {
+ me.items = me.get_items($(this).attr("data-item-code"))
+ me.add_to_cart();
+ }
+ });
+
+ me.bind_delete_event()
+ },
+
update_qty: function (item_code, qty) {
var me = this;
this.items = this.get_items(item_code);
@@ -835,13 +1103,30 @@
update_rate: function () {
var me = this;
-
- $(this.wrapper).find(".pos-item-rate").on("change", function () {
- var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
+ $(this.wrapper).on("change", ".pos-item-price", function () {
+ var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
me.set_item_details(item_code, "rate", $(this).val());
})
},
+ render_selected_item: function() {
+ doc = this.get_child_item(this.item_code);
+ $(this.wrapper).find('.selected-item').empty();
+ if(doc.length) {
+ this.selected_row = $(frappe.render_template("pos_selected_item", doc[0]))
+ $(this.wrapper).find('.selected-item').html(this.selected_row)
+ }
+ },
+
+ get_child_item: function(item_code) {
+ var me = this;
+ return $.map(me.frm.doc.items, function(doc){
+ if(doc.item_code == item_code) {
+ return doc
+ }
+ })
+ },
+
set_item_details: function (item_code, field, value) {
var me = this;
if (value < 0) {
@@ -874,7 +1159,6 @@
var me = this;
idx = 0
this.items = []
- idx = 0
$.each(this.frm.doc["items"] || [], function (i, d) {
if (!in_list(me.remove_item, d.idx)) {
d.idx = idx;
@@ -950,6 +1234,7 @@
this.add_new_item_to_grid();
this.update_paid_amount_status(false)
+ this.wrapper.find(".item-cart-items").scrollTop(1000);
},
add_new_item_to_grid: function () {
@@ -959,6 +1244,7 @@
this.child.item_name = this.items[0].item_name;
this.child.stock_uom = this.items[0].stock_uom;
this.child.description = this.items[0].description;
+ this.child.discount_percentage = 0.0;
this.child.qty = 1;
this.child.item_group = this.items[0].item_group;
this.child.cost_center = this.pos_profile_data['cost_center'] || this.items[0].cost_center;
@@ -986,8 +1272,7 @@
refresh: function (update_paid_amount) {
var me = this;
this.refresh_fields(update_paid_amount);
- this.bind_qty_event();
- this.update_rate();
+ this.bind_items_event();
this.set_primary_action();
},
@@ -1013,8 +1298,14 @@
show_items_in_item_cart: function () {
var me = this;
var $items = this.wrapper.find(".items").empty();
+ var $no_items_message = this.wrapper.find(".no-items-message");
+ $no_items_message.toggle(this.frm.doc.items.length === 0);
+
+ var $totals_area = this.wrapper.find('.totals-area');
+ $totals_area.toggle(this.frm.doc.items.length > 0);
+
$.each(this.frm.doc.items || [], function (i, d) {
- $(frappe.render_template("pos_bill_item", {
+ $(frappe.render_template("pos_bill_item_new", {
item_code: d.item_code,
item_name: (d.item_name === d.item_code || !d.item_name) ? "" : ("<br>" + d.item_name),
qty: d.qty,
@@ -1031,11 +1322,11 @@
$(this).select();
});
- this.wrapper.find("input.pos-item-discount").on("focus", function () {
+ this.wrapper.find("input.pos-item-disc").on("focus", function () {
$(this).select();
});
- this.wrapper.find("input.pos-item-rate").on("focus", function () {
+ this.wrapper.find("input.pos-item-price").on("focus", function () {
$(this).select();
});
},
@@ -1068,33 +1359,31 @@
set_primary_action: function () {
var me = this;
+ this.page.set_primary_action(__("New Cart"), function () {
+ me.make_new_cart()
+ }, "fa fa-plus")
- if (this.frm.doc.docstatus == 0) {
- this.page.set_primary_action(__("Pay"), function () {
- me.validate();
- me.update_paid_amount_status(true);
- me.create_invoice();
- me.make_payment();
- }, "fa fa-credit-card");
- } else if (this.frm.doc.docstatus == 1) {
- this.page.set_primary_action(__("Print"), function () {
+ if (this.frm.doc.docstatus == 1) {
+ this.page.set_secondary_action(__("Print"), function () {
html = frappe.render(me.print_template_data, me.frm.doc)
me.print_document(html)
})
- } else {
- this.page.clear_primary_action()
}
+ },
- // this.page.set_secondary_action(__("New"), function () {
- // me.save_previous_entry();
- // me.create_new();
- // }, "fa fa-plus").addClass("btn-primary");
+ make_new_cart: function (){
+ this.save_previous_entry();
+ this.create_new();
+ this.refresh();
+ this.toggle_input_field();
+ this.render_list_customers();
+ this.set_focus();
},
print_dialog: function () {
var me = this;
- msgprint = frappe.msgprint(format('<a class="btn btn-primary print_doc" \
+ this.msgprint = frappe.msgprint(format('<a class="btn btn-primary print_doc" \
style="margin-right: 5px;">{0}</a>\
<a class="btn btn-default new_doc">{1}</a>', [
__('Print'), __('New')
@@ -1106,8 +1395,8 @@
})
$('.new_doc').click(function () {
- msgprint.hide()
- me.create_new();
+ me.msgprint.hide()
+ me.make_new_cart()
})
},
@@ -1133,19 +1422,22 @@
if (this.frm.doc.docstatus == 0) {
this.frm.doc.docstatus = 1;
this.update_invoice();
- this.disable_input_field();
+ this.toggle_input_field();
}
},
- disable_input_field: function () {
+ toggle_input_field: function () {
var pointer_events = 'inherit'
- $(this.wrapper).find('input').attr("disabled", false);
- $(this.wrapper).find('select').attr("disabled", false);
+ disabled = this.frm.doc.docstatus == 1 ? true: false;
+ $(this.wrapper).find('input').attr("disabled", disabled);
+ $(this.wrapper).find('select').attr("disabled", disabled);
+ $(this.wrapper).find('input').attr("disabled", disabled);
+ $(this.wrapper).find('select').attr("disabled", disabled);
+ $(this.wrapper).find('button').attr("disabled", disabled);
+ this.party_field.$input.attr('disabled', disabled);
if (this.frm.doc.docstatus == 1) {
pointer_events = 'none';
- $(this.wrapper).find('input').attr("disabled", true);
- $(this.wrapper).find('select').attr("disabled", true);
}
$(this.wrapper).find('.pos-bill').css('pointer-events', pointer_events);
@@ -1210,18 +1502,26 @@
sync_sales_invoice: function () {
var me = this;
- this.si_docs = this.get_submitted_invoice();
+ this.si_docs = this.get_submitted_invoice() || [];
+ this.email_queue_list = this.get_email_queue() || {};
+ this.customers_list = this.get_customers_details() || {};
- if (this.si_docs.length) {
+ if (this.si_docs.length || this.email_queue_list || this.customers_list) {
frappe.call({
method: "erpnext.accounts.doctype.sales_invoice.pos.make_invoice",
args: {
- doc_list: me.si_docs
+ doc_list: me.si_docs,
+ email_queue_list: me.email_queue_list,
+ customers_list: me.customers_list
},
callback: function (r) {
if (r.message) {
- me.removed_items = r.message;
+ me.removed_items = r.message.invoice;
+ me.removed_email = r.message.email_queue
+ me.removed_customers = r.message.customers
me.remove_doc_from_localstorage();
+ me.remove_email_queue_from_localstorage();
+ me.remove_customer_from_localstorage();
}
}
})
@@ -1259,11 +1559,38 @@
}
}
})
+ this.removed_items = [];
this.si_docs = this.new_si_docs;
this.update_localstorage();
}
},
+ remove_email_queue_from_localstorage: function() {
+ var me = this;
+ this.email_queue = this.get_email_queue()
+ if (this.removed_email) {
+ $.each(this.email_queue_list, function (index, data) {
+ if (in_list(me.removed_email, index)) {
+ delete me.email_queue[index]
+ }
+ })
+ this.update_email_queue();
+ }
+ },
+
+ remove_customer_from_localstorage: function() {
+ var me = this;
+ this.customer_details = this.get_customers_details()
+ if (this.removed_customers) {
+ $.each(this.customers_list, function (index, data) {
+ if (in_list(me.removed_customers, index)) {
+ delete me.customer_details[index]
+ }
+ })
+ this.update_customer_in_localstorage();
+ }
+ },
+
validate: function () {
var me = this;
this.customer_validate();
@@ -1350,13 +1677,18 @@
item.price_list_rate = pricing_rule[0].price || item.price_list_rate;
item.margin_rate_or_amount = pricing_rule[0].margin_rate_or_amount;
item.discount_percentage = pricing_rule[0].discount_percentage || 0.0;
- } else if ((item.discount_percentage > 0 || item.margin_rate_or_amount > 0) && item.pricing_rule) {
+ me.apply_pricing_rule_on_item(item)
+ } else if (item.pricing_rule) {
+ item.price_list_rate = me.price_list_data[item.item_code]
item.margin_rate_or_amount = 0.0;
item.discount_percentage = 0.0;
item.pricing_rule = null;
+ me.apply_pricing_rule_on_item(item)
}
-
- me.apply_pricing_rule_on_item(item)
+
+ if(item.discount_percentage > 0) {
+ me.apply_pricing_rule_on_item(item)
+ }
})
},
@@ -1443,5 +1775,14 @@
}
return this.actual_qty
+ },
+
+ update_customer_in_localstorage: function() {
+ var me = this;
+ try {
+ localStorage.setItem('customer_details', JSON.stringify(this.customer_details));
+ } catch (e) {
+ frappe.throw(__("LocalStorage is full , did not save"))
+ }
}
})
\ No newline at end of file
diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py
index 3c566e9..8b8f257 100644
--- a/erpnext/accounts/report/gross_profit/gross_profit.py
+++ b/erpnext/accounts/report/gross_profit/gross_profit.py
@@ -248,21 +248,31 @@
conditions += " and posting_date >= %(from_date)s"
if self.filters.to_date:
conditions += " and posting_date <= %(to_date)s"
+
+ if self.filters.group_by=="Sales Person":
+ sales_person_cols = ", sales.sales_person, sales.allocated_amount, sales.incentives"
+ sales_team_table = "left join `tabSales Team` sales on sales.parent = si.name"
+ else:
+ sales_person_cols = ""
+ sales_team_table = ""
self.si_list = frappe.db.sql("""select item.parenttype, item.parent,
si.posting_date, si.posting_time, si.project, si.update_stock,
si.customer, si.customer_group, si.territory,
item.item_code, item.item_name, item.description, item.warehouse,
item.item_group, item.brand, item.dn_detail, item.delivery_note,
- item.stock_qty as qty, item.base_net_rate, item.base_net_amount, item.name as "item_row",
- sales.sales_person, sales.allocated_amount, sales.incentives
- from `tabSales Invoice` si
- inner join `tabSales Invoice Item` item on item.parent = si.name
- left join `tabSales Team` sales on sales.parent = si.name
+ item.stock_qty as qty, item.base_net_rate, item.base_net_amount, item.name as "item_row"
+ {sales_person_cols}
+ from
+ `tabSales Invoice` si
+ inner join `tabSales Invoice Item` item on item.parent = si.name
+ {sales_team_table}
where
- si.docstatus = 1 and si.is_return != 1 %s
+ si.docstatus = 1 and si.is_return != 1 {conditions}
order by
- si.posting_date desc, si.posting_time desc""" % (conditions,), self.filters, as_dict=1)
+ si.posting_date desc, si.posting_time desc"""
+ .format(conditions=conditions, sales_person_cols=sales_person_cols,
+ sales_team_table=sales_team_table), self.filters, as_dict=1)
def load_stock_ledger_entries(self):
res = frappe.db.sql("""select item_code, voucher_type, voucher_no,
diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py
index 786a36c..913d2e4 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.py
+++ b/erpnext/crm/doctype/opportunity/opportunity.py
@@ -178,6 +178,7 @@
@frappe.whitelist()
def make_quotation(source_name, target_doc=None):
def set_missing_values(source, target):
+ from erpnext.controllers.accounts_controller import get_default_taxes_and_charges
quotation = frappe.get_doc(target)
company_currency = frappe.db.get_value("Company", quotation.company, "default_currency")
@@ -193,7 +194,11 @@
quotation.transaction_date)
quotation.conversion_rate = exchange_rate
-
+
+ # get default taxes
+ taxes = get_default_taxes_and_charges("Sales Taxes and Charges Template")
+ quotation.extend("taxes", taxes)
+
quotation.run_method("set_missing_values")
quotation.run_method("calculate_taxes_and_totals")
diff --git a/erpnext/hr/doctype/employee_loan/employee_loan.js b/erpnext/hr/doctype/employee_loan/employee_loan.js
index cb9216f..2f87acf 100644
--- a/erpnext/hr/doctype/employee_loan/employee_loan.js
+++ b/erpnext/hr/doctype/employee_loan/employee_loan.js
@@ -36,7 +36,34 @@
})
},
- mode_of_payment: function(frm){
+ refresh: function(frm) {
+ if (frm.doc.docstatus == 1 && (frm.doc.status == "Sanctioned" || frm.doc.status == "Partially Disbursed")) {
+ frm.add_custom_button(__('Make Disbursement Entry'), function() {
+ frm.trigger("make_jv");
+ })
+ }
+ frm.trigger("toggle_fields");
+ },
+
+ make_jv: function(frm) {
+ frappe.call({
+ args: {
+ "employee_loan": frm.doc.name,
+ "company": frm.doc.company,
+ "employee_loan_account": frm.doc.employee_loan_account,
+ "employee": frm.doc.employee,
+ "loan_amount": frm.doc.loan_amount,
+ "payment_account": frm.doc.payment_account
+ },
+ method: "erpnext.hr.doctype.employee_loan.employee_loan.make_jv_entry",
+ callback: function(r) {
+ if (r.message)
+ var doc = frappe.model.sync(r.message)[0];
+ frappe.set_route("Form", doc.doctype, doc.name);
+ }
+ })
+ },
+ mode_of_payment: function(frm) {
frappe.call({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_bank_cash_account",
args: {
@@ -51,23 +78,6 @@
});
},
- refresh: function(frm) {
- frm.trigger("toggle_fields");
-
- if(frm.doc.docstatus==1) {
- frm.add_custom_button(__('Ledger'), function() {
- frappe.route_options = {
- "voucher_no": frm.doc.name,
- "from_date": frm.doc.posting_date,
- "to_date": frm.doc.posting_date,
- "company": frm.doc.company,
- group_by_voucher: 0
- };
- frappe.set_route("query-report", "General Ledger");
- }, "fa fa-table");
- }
- },
-
employee_loan_application: function(frm) {
return frm.call({
method: "erpnext.hr.doctype.employee_loan.employee_loan.get_employee_loan_application",
diff --git a/erpnext/hr/doctype/employee_loan/employee_loan.json b/erpnext/hr/doctype/employee_loan/employee_loan.json
index c052dc0..a14c1e0 100644
--- a/erpnext/hr/doctype/employee_loan/employee_loan.json
+++ b/erpnext/hr/doctype/employee_loan/employee_loan.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "ELN.####",
@@ -237,7 +238,7 @@
"label": "Status",
"length": 0,
"no_copy": 0,
- "options": "Loan Unpaid\nLoan Paid\nEMI in progress\nLoan Repaid",
+ "options": "Sanctioned\nPartially Disbursed\nFully Disbursed\nRepaid/Closed",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -325,6 +326,7 @@
"label": "Loan Amount",
"length": 0,
"no_copy": 0,
+ "options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -506,6 +508,7 @@
"label": "Monthly Repayment Amount",
"length": 0,
"no_copy": 0,
+ "options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -690,7 +693,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 0,
+ "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -801,6 +804,7 @@
"label": "Total Payment",
"length": 0,
"no_copy": 0,
+ "options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -859,6 +863,7 @@
"label": "Total Interest Payable",
"length": 0,
"no_copy": 0,
+ "options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -901,17 +906,17 @@
"unique": 0
}
],
+ "has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
- "in_dialog": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-02-22 04:27:13.174800",
+ "modified": "2017-03-09 01:30:19.231918",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Loan",
diff --git a/erpnext/hr/doctype/employee_loan/employee_loan.py b/erpnext/hr/doctype/employee_loan/employee_loan.py
index 568596e..d4e9a20 100644
--- a/erpnext/hr/doctype/employee_loan/employee_loan.py
+++ b/erpnext/hr/doctype/employee_loan/employee_loan.py
@@ -8,7 +8,6 @@
from frappe import _
from frappe.utils import flt, rounded, add_months, nowdate
from erpnext.controllers.accounts_controller import AccountsController
-from erpnext.accounts.general_ledger import make_gl_entries
class EmployeeLoan(AccountsController):
def validate(self):
@@ -26,33 +25,32 @@
self.set_repayment_period()
self.calculate_totals()
- def on_submit(self):
- self.make_gl_entries()
+ def make_jv_entry(self):
+ self.check_permission('write')
+ journal_entry = frappe.new_doc('Journal Entry')
+ journal_entry.voucher_type = 'Bank Entry'
+ journal_entry.user_remark = _('Against Employee Loan: {0}').format(self.name)
+ journal_entry.company = self.company
+ journal_entry.posting_date = nowdate()
- def on_cancel(self):
- self.make_gl_entries()
+ account_amt_list = []
- def make_gl_entries(self):
- gl_entries = []
- # Gl entries for employee loan account
- gl_entries.append(
- self.get_gl_dict({
- "account": self.employee_loan_account,
- "party_type": "Employee",
- "party": self.employee,
- "debit": self.loan_amount,
- "debit_in_account_currency": self.loan_amount
+ account_amt_list.append({
+ "account": self.employee_loan_account,
+ "party_type": "Employee",
+ "party": self.employee,
+ "debit_in_account_currency": self.loan_amount,
+ "reference_type": "Employee Loan",
+ "reference_name": self.name,
})
- )
- # Gl entries for payment account
- gl_entries.append(
- self.get_gl_dict({
- "account": self.payment_account,
- "credit": self.loan_amount,
- "credit_in_account_currency": self.loan_amount
+ account_amt_list.append({
+ "account": self.payment_account,
+ "credit_in_account_currency": self.loan_amount,
+ "reference_type": "Employee Loan",
+ "reference_name": self.name,
})
- )
- make_gl_entries(gl_entries, cancel=(self.docstatus == 2))
+ journal_entry.set("accounts", account_amt_list)
+ return journal_entry.as_dict()
def make_repayment_schedule(self):
self.repayment_schedule = []
@@ -94,11 +92,19 @@
self.total_payment += data.total_payment
self.total_interest_payable +=data.interest_amount
- def update_status(self):
- if self.disbursement_date:
- self.status = "Loan Paid"
- if len(self.repayment_schedule)>0:
- self.status = "repayment in progress"
+
+def update_disbursement_status(doc):
+ disbursed_amount = frappe.db.sql("""select ifnull(sum(debit_in_account_currency), 0) as disbursed_amount
+ from `tabGL Entry` where against_voucher_type = 'Employee Loan' and against_voucher = %s""",
+ (doc.name), as_dict=1)[0].disbursed_amount
+ if disbursed_amount == doc.loan_amount:
+ frappe.db.set_value("Employee Loan", doc.name , "status", "Fully Disbursed")
+ if disbursed_amount < doc.loan_amount and disbursed_amount != 0:
+ frappe.db.set_value("Employee Loan", doc.name , "status", "Partially Disbursed")
+ if disbursed_amount == 0:
+ frappe.db.set_value("Employee Loan", doc.name , "status", "Sanctioned")
+ if disbursed_amount > doc.loan_amount:
+ frappe.throw(_("Disbursed Amount cannot be greater than Loan Amount {0}").format(doc.loan_amount))
def check_repayment_method(repayment_method, loan_amount, monthly_repayment_amount, repayment_periods):
if repayment_method == "Repay Over Number of Periods" and not repayment_periods:
@@ -124,4 +130,29 @@
def get_employee_loan_application(employee_loan_application):
employee_loan = frappe.get_doc("Employee Loan Application", employee_loan_application)
if employee_loan:
- return employee_loan
\ No newline at end of file
+ return employee_loan
+
+@frappe.whitelist()
+def make_jv_entry(employee_loan, company, employee_loan_account, employee, loan_amount, payment_account):
+ journal_entry = frappe.new_doc('Journal Entry')
+ journal_entry.voucher_type = 'Bank Entry'
+ journal_entry.user_remark = _('Against Employee Loan: {0}').format(employee_loan)
+ journal_entry.company = company
+ journal_entry.posting_date = nowdate()
+
+ account_amt_list = []
+
+ account_amt_list.append({
+ "account": employee_loan_account,
+ "debit_in_account_currency": loan_amount,
+ "reference_type": "Employee Loan",
+ "reference_name": employee_loan,
+ })
+ account_amt_list.append({
+ "account": payment_account,
+ "credit_in_account_currency": loan_amount,
+ "reference_type": "Employee Loan",
+ "reference_name": employee_loan,
+ })
+ journal_entry.set("accounts", account_amt_list)
+ return journal_entry.as_dict()
\ No newline at end of file
diff --git a/erpnext/hr/doctype/employee_loan/test_employee_loan.py b/erpnext/hr/doctype/employee_loan/test_employee_loan.py
index c1c6ba2..8671baa 100644
--- a/erpnext/hr/doctype/employee_loan/test_employee_loan.py
+++ b/erpnext/hr/doctype/employee_loan/test_employee_loan.py
@@ -60,7 +60,8 @@
"disbursement_date": nowdate(),
"mode_of_payment": frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name'),
"payment_account": frappe.db.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name"),
- "employee_loan_account": frappe.db.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
+ "employee_loan_account": frappe.db.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name"),
+ "interest_income_account": frappe.db.get_value('Account', {'account_type': 'Cash', 'company': erpnext.get_default_company(),'is_group':0}, "name")
})
employee_loan.insert()
return employee_loan
diff --git a/erpnext/hr/doctype/employee_loan_application/employee_loan_application.json b/erpnext/hr/doctype/employee_loan_application/employee_loan_application.json
index 29617dd..4c673c3 100644
--- a/erpnext/hr/doctype/employee_loan_application/employee_loan_application.json
+++ b/erpnext/hr/doctype/employee_loan_application/employee_loan_application.json
@@ -266,6 +266,7 @@
"label": "Loan Amount",
"length": 0,
"no_copy": 0,
+ "options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -470,6 +471,7 @@
"label": "Total Payable Interest",
"length": 0,
"no_copy": 0,
+ "options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -528,6 +530,7 @@
"label": "Monthly Repayment Amount",
"length": 0,
"no_copy": 0,
+ "options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -587,6 +590,7 @@
"label": "Total Payable Amount",
"length": 0,
"no_copy": 0,
+ "options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -639,7 +643,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-02-27 04:52:39.344524",
+ "modified": "2017-03-02 04:25:43.397934",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Loan Application",
diff --git a/erpnext/hr/doctype/loan_type/loan_type.json b/erpnext/hr/doctype/loan_type/loan_type.json
index 3809fc1..ce93979 100644
--- a/erpnext/hr/doctype/loan_type/loan_type.json
+++ b/erpnext/hr/doctype/loan_type/loan_type.json
@@ -58,6 +58,7 @@
"label": "Maximum Loan Amount",
"length": 0,
"no_copy": 0,
+ "options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -198,7 +199,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2017-02-27 04:53:51.949600",
+ "modified": "2017-03-02 04:26:05.375693",
"modified_by": "Administrator",
"module": "HR",
"name": "Loan Type",
diff --git a/erpnext/hr/doctype/process_payroll/process_payroll.py b/erpnext/hr/doctype/process_payroll/process_payroll.py
index 0ec5717..915985c 100644
--- a/erpnext/hr/doctype/process_payroll/process_payroll.py
+++ b/erpnext/hr/doctype/process_payroll/process_payroll.py
@@ -148,8 +148,10 @@
ss_obj = frappe.get_doc("Salary Slip",ss[0])
ss_dict = {}
ss_dict["Employee Name"] = ss_obj.employee_name
- ss_dict["Total Pay"] = fmt_money(ss_obj.rounded_total,currency = frappe.defaults.get_global_default("currency"))
+ ss_dict["Total Pay"] = fmt_money(ss_obj.net_pay,
+ currency = frappe.defaults.get_global_default("currency"))
ss_dict["Salary Slip"] = self.format_as_links(ss_obj.name)[0]
+
if ss_obj.net_pay<0:
not_submitted_ss.append(ss_dict)
else:
diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py
index 15d5df8..b8382ec 100644
--- a/erpnext/hr/doctype/salary_slip/salary_slip.py
+++ b/erpnext/hr/doctype/salary_slip/salary_slip.py
@@ -49,13 +49,13 @@
self._salary_structure_doc = frappe.get_doc('Salary Structure', self.salary_structure)
data = self.get_data_for_eval()
+
for key in ('earnings', 'deductions'):
for struct_row in self._salary_structure_doc.get(key):
amount = self.eval_condition_and_formula(struct_row, data)
if amount:
self.update_component_row(struct_row, amount, key)
-
def update_component_row(self, struct_row, amount, key):
component_row = None
for d in self.get(key):
@@ -83,6 +83,7 @@
amount = eval(d.formula, None, data)
if amount:
data[d.abbr] = amount
+
return amount
except NameError as err:
@@ -97,17 +98,20 @@
'''Returns data for evaluating formula'''
data = frappe._dict()
- for d in self._salary_structure_doc.employees:
- if d.employee == self.employee:
- data.update(frappe.get_doc("Salary Structure Employee", {"employee": self.employee}).as_dict())
+ data.update(frappe.get_doc("Salary Structure Employee", {"employee": self.employee}).as_dict())
data.update(frappe.get_doc("Employee", self.employee).as_dict())
data.update(self.as_dict())
# set values for components
salary_components = frappe.get_all("Salary Component", fields=["salary_component_abbr"])
- for salary_component in salary_components:
- data[salary_component.salary_component_abbr] = 0
+ for sc in salary_components:
+ data.setdefault(sc.salary_component_abbr, 0)
+
+ for key in ('earnings', 'deductions'):
+ for d in self.get(key):
+ data[d.abbr] = d.amount
+
return data
@@ -173,13 +177,16 @@
def pull_sal_struct(self):
from erpnext.hr.doctype.salary_structure.salary_structure import make_salary_slip
- make_salary_slip(self._salary_structure_doc.name, self)
if self.salary_slip_based_on_timesheet:
self.salary_structure = self._salary_structure_doc.name
self.hour_rate = self._salary_structure_doc.hour_rate
self.total_working_hours = sum([d.working_hours or 0.0 for d in self.timesheets]) or 0.0
- self.add_earning_for_hourly_wages(self._salary_structure_doc.salary_component)
+ wages_amount = self.hour_rate * self.total_working_hours
+
+ self.add_earning_for_hourly_wages(self, self._salary_structure_doc.salary_component, wages_amount)
+
+ make_salary_slip(self._salary_structure_doc.name, self)
def process_salary_structure(self):
'''Calculate salary after salary structure details have been updated'''
@@ -188,18 +195,21 @@
self.get_leave_details()
self.calculate_net_pay()
- def add_earning_for_hourly_wages(self, salary_component):
- default_type = False
- for data in self.earnings:
- if data.salary_component == salary_component:
- data.amount = self.hour_rate * self.total_working_hours
- default_type = True
+ def add_earning_for_hourly_wages(self, doc, salary_component, amount):
+ row_exists = False
+ for row in doc.earnings:
+ if row.salary_component == salary_component:
+ row.amount = amount
+ row_exists = True
break
- if not default_type:
- earnings = self.append('earnings', {})
- earnings.salary_component = salary_component
- earnings.amount = self.hour_rate * self.total_working_hours
+ if not row_exists:
+ wages_row = {
+ "salary_component": salary_component,
+ "abbr": frappe.db.get_value("Salary Component", salary_component, "salary_component_abbr"),
+ "amount": self.hour_rate * self.total_working_hours
+ }
+ doc.append('earnings', wages_row)
def pull_emp_details(self):
emp = frappe.db.get_value("Employee", self.employee, ["bank_name", "bank_ac_no"], as_dict=1)
@@ -307,8 +317,15 @@
frappe.throw(_("Salary Slip of employee {0} already created for time sheet {1}").format(self.employee, data.time_sheet))
def sum_components(self, component_type, total_field):
+ joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
+ ["date_of_joining", "relieving_date"])
+ if not relieving_date:
+ relieving_date = getdate(self.end_date)
+
for d in self.get(component_type):
- if cint(d.depends_on_lwp) == 1 and not self.salary_slip_based_on_timesheet:
+ if ((cint(d.depends_on_lwp) == 1 and not self.salary_slip_based_on_timesheet) or\
+ getdate(self.start_date) < joining_date or getdate(self.end_date) > relieving_date):
+
d.amount = rounded((flt(d.default_amount) * flt(self.payment_days)
/ cint(self.total_working_days)), self.precision("amount", component_type))
elif not self.payment_days and not self.salary_slip_based_on_timesheet:
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py
index 22697f0..12f8335 100644
--- a/erpnext/hr/doctype/salary_structure/salary_structure.py
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.py
@@ -16,7 +16,7 @@
self.validate_amount()
for e in self.get('employees'):
set_employee_name(e)
- self.validate_joining_date()
+ self.validate_date()
def get_ss_values(self,employee):
basic_info = frappe.db.sql("""select bank_name, bank_ac_no
@@ -29,12 +29,37 @@
if flt(self.net_pay) < 0 and self.salary_slip_based_on_timesheet:
frappe.throw(_("Net pay cannot be negative"))
- def validate_joining_date(self):
- for e in self.get('employees'):
- joining_date = getdate(frappe.db.get_value("Employee", e.employee, "date_of_joining"))
- if e.from_date and getdate(e.from_date) < joining_date:
+ def validate_date(self):
+ for employee in self.get('employees'):
+ joining_date, relieving_date = frappe.db.get_value("Employee", employee.employee,
+ ["date_of_joining", "relieving_date"])
+ if employee.from_date and getdate(employee.from_date) < joining_date:
frappe.throw(_("From Date {0} for Employee {1} cannot be before employee's joining Date {2}")
- .format(e.from_date, e.employee, joining_date))
+ .format(employee.from_date, employee.employee, joining_date))
+
+ st_name = frappe.db.sql("""select parent from `tabSalary Structure Employee`
+ where
+ employee=%(employee)s
+ and (
+ (%(from_date)s between from_date and ifnull(to_date, '2199-12-31'))
+ or (%(to_date)s between from_date and ifnull(to_date, '2199-12-31'))
+ or (from_date between %(from_date)s and %(to_date)s)
+ )
+ and (
+ exists (select name from `tabSalary Structure`
+ where name = `tabSalary Structure Employee`.parent and is_active = 'Yes')
+ )
+ and parent != %(salary_struct)s""",
+ {
+ 'employee': employee.employee,
+ 'from_date': employee.from_date,
+ 'to_date': (employee.to_date or '2199-12-31'),
+ 'salary_struct': self.name
+ })
+
+ if st_name:
+ frappe.throw(_("Active Salary Structure {0} found for employee {1} for the given dates")
+ .format(st_name[0][0], employee.employee))
@frappe.whitelist()
def make_salary_slip(source_name, target_doc = None, employee = None, as_print = False, print_format = None):
diff --git a/erpnext/public/build.json b/erpnext/public/build.json
index c405681..393e90c 100644
--- a/erpnext/public/build.json
+++ b/erpnext/public/build.json
@@ -20,8 +20,11 @@
"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",
diff --git a/erpnext/public/css/erpnext.css b/erpnext/public/css/erpnext.css
index cfe9f63..697c078 100644
--- a/erpnext/public/css/erpnext.css
+++ b/erpnext/public/css/erpnext.css
@@ -12,113 +12,11 @@
height: 32px;
margin: -10px auto;
}
-/* pos */
-.pos-item-area {
- padding: 0px 10px;
-}
-.pos-item-wrapper {
- padding: 5px;
-}
-.pos-item {
- overflow: hidden;
- text-overflow: ellipsis;
- cursor: pointer;
- padding: 5px;
- padding-bottom: 15px;
- border: 1px solid #d1d8dd;
- margin-bottom: 5px;
-}
-.pos-item-text {
- padding: 0px 5px;
-}
-.pos-item .item-code {
- margin-bottom: 0px;
-}
-.pos-item .no-image {
- background-color: #fafbfc;
- border: 1px dashed #d1d8dd;
-}
-.pos-item-image {
- width: 100%;
- height: 0px;
- padding: 50% 0;
- text-align: center;
- line-height: 0;
- color: #d1d8dd;
- font-size: 30px;
- background-size: contain;
- border: 1px solid transparent;
- background-position: center;
- background-repeat: no-repeat;
-}
-.pos-item-area {
- border: 1px solid #d1d8dd;
- border-top: none;
-}
-.pos-item-toolbar {
- padding: 10px 0px;
- border-bottom: 1px solid #d1d8dd;
-}
-.item-list-area {
- padding: 15px 0px;
- overflow-y: scroll;
- height: calc(100vh - 162px);
-}
-.pos-toolbar,
-.pos-bill-toolbar {
- padding: 10px 0px;
- height: 51px;
-}
-.pos-item-toolbar .form-group {
- margin-bottom: 0px;
-}
-.pos-bill-wrapper {
- border: 1px solid #d1d8dd;
- border-top: none;
- margin-right: -1px;
-}
-.pos-bill {
- border-top: 1px solid #d1d8dd;
- margin-left: -15px;
- margin-right: -15px;
-}
-.pos-bill-row {
- margin: 0px;
- padding: 7px 0px;
- border-top: 1px solid #d1d8dd;
-}
-.pos-bill-header {
- border: none !important;
- background-color: #f5f7fa;
-}
-.pos-item-qty {
- display: inline-block;
-}
-.pos-qty-row > div {
- padding: 5px 0px;
-}
-.pos-qty-btn {
- margin-top: 3px;
- cursor: pointer;
- font-size: 120%;
-}
-.pos .search-area .form-group {
- max-width: 100% !important;
-}
-.pos .tax-table {
- margin-bottom: 10px;
-}
.erpnext-icon {
width: 24px;
- ackmargin-right: 0px;
+ margin-right: 0px;
margin-top: -3px;
}
-.pos .discount-amount-area .discount-field-col {
- padding-left: 0px;
-}
-.pos .discount-amount-area .input-group {
- margin-top: 2px;
-}
.dashboard-list-item {
background-color: inherit;
padding: 5px 0px;
@@ -130,91 +28,6 @@
.dashboard-list-item:last-child {
border-bottom: none;
}
-.payment-toolbar .row {
- width: 323px;
- margin: 0 auto;
-}
-.payment-mode {
- cursor: pointer;
- font-family: sans-serif;
- font-size: 15px;
-}
-.pos-payment-row .col-xs-6 {
- padding: 15px;
-}
-.pos-payment-row {
- border-bottom: 1px solid #d1d8dd;
- margin: 2px 0px 5px 0px;
- height: 60px;
- margin-top: 0px;
- margin-bottom: 0px;
-}
-.pos-payment-row:hover,
-.pos-keyboard-key:hover {
- background-color: #FAFBFC;
- cursor: pointer;
-}
-.pos-keyboard-key,
-.delete-btn {
- border: 1px solid #d1d8dd;
- height: 85px;
- width: 85px;
- margin: 10px 10px;
- font-size: 24px;
- font-weight: 200;
- background-color: #FDFDFD;
- border-color: #e8e8e8;
-}
-.multimode-payments {
- padding-left: 30px;
-}
-.payment-toolbar {
- padding-right: 30px;
-}
-.list-row-head.pos-invoice-list {
- border-top: 1px solid #d1d8dd;
-}
-body[data-route="pos"] .modal-dialog {
- width: 750px;
-}
-@media (max-width: 767px) {
- body[data-route="pos"] .modal-dialog {
- width: auto;
- }
- body[data-route="pos"] .modal-dialog .modal-content {
- height: auto;
- }
-}
-@media (max-width: 767px) {
- .amount-row h3 {
- font-size: 15px;
- }
- .pos-keyboard-key,
- .delete-btn {
- height: 50px;
- }
- .multimode-payments {
- padding-left: 15px;
- }
- .payment-toolbar {
- padding-right: 15px;
- }
-}
-.amount-label {
- font-size: 16px;
-}
-.selected-payment-mode {
- background-color: #FAFBFC;
- cursor: pointer;
-}
-.pos-invoice-list {
- padding: 15px 10px;
-}
-.write_off_amount,
-.change_amount {
- margin: 15px;
- width: 130px;
-}
.frappe-control[data-fieldname='result_html'] {
overflow: scroll;
}
@@ -237,3 +50,281 @@
.assessment-result-tool .score {
text-align: right;
}
+/* pos */
+body[data-route="pos"] .pos-bill-toolbar {
+ padding: 10px 0px;
+ height: 51px;
+}
+body[data-route="pos"] .pos-bill-item:hover,
+body[data-route="pos"] .list-customers-table > .pos-list-row:hover {
+ background-color: #f5f7fa;
+ cursor: pointer;
+}
+body[data-route="pos"] .pos-item-qty {
+ display: inline-block;
+}
+body[data-route="pos"] .pos-qty-row > div {
+ padding: 5px 0px;
+}
+body[data-route="pos"] .pos-qty-btn {
+ margin-top: 3px;
+ cursor: pointer;
+ font-size: 120%;
+}
+body[data-route="pos"] .search-area .form-group {
+ max-width: 100% !important;
+}
+body[data-route="pos"] .tax-table {
+ margin-bottom: 10px;
+}
+body[data-route="pos"] .discount-field-col {
+ padding-left: 24px;
+}
+body[data-route="pos"] .discount-amount-area .input-group:first-child {
+ margin-bottom: 2px;
+}
+body[data-route="pos"] .payment-toolbar .row {
+ width: 323px;
+ margin: 0 auto;
+}
+body[data-route="pos"] .payment-mode {
+ cursor: pointer;
+ font-family: sans-serif;
+ font-size: 15px;
+}
+body[data-route="pos"] .pos-payment-row .col-xs-6 {
+ padding: 15px;
+}
+body[data-route="pos"] .pos-payment-row {
+ border-bottom: 1px solid #d1d8dd;
+ margin: 2px 0px 5px 0px;
+ height: 60px;
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+body[data-route="pos"] .pos-payment-row:hover,
+body[data-route="pos"] .pos-keyboard-key:hover {
+ background-color: #FAFBFC;
+ cursor: pointer;
+}
+body[data-route="pos"] .pos-keyboard-key,
+body[data-route="pos"] .delete-btn {
+ border: 1px solid #d1d8dd;
+ height: 85px;
+ width: 85px;
+ margin: 10px 10px;
+ font-size: 24px;
+ font-weight: 200;
+ background-color: #FDFDFD;
+ border-color: #e8e8e8;
+}
+body[data-route="pos"] .numeric-keypad {
+ border: 1px solid #d1d8dd;
+ height: 69px;
+ width: 69px;
+ font-size: 20px;
+ font-weight: 200;
+ background-color: #FDFDFD;
+ border-color: #e8e8e8;
+ margin-left: -4px;
+}
+body[data-route="pos"] .pos-pay {
+ height: 69px;
+ width: 69px;
+ font-size: 17px;
+ font-weight: 200;
+ margin-left: -4px;
+}
+body[data-route="pos"] .numeric-keypad {
+ height: 60px;
+ width: 60px;
+ font-size: 20px;
+ font-weight: 200;
+ border-radius: 0;
+ background-color: #fff;
+ margin-left: -4px;
+}
+body[data-route="pos"] .numeric_keypad {
+ margin-left: -15px;
+}
+body[data-route="pos"] .numeric_keypad > .row > button {
+ border: none;
+ border-right: 1px solid #d1d8dd;
+ border-bottom: 1px solid #d1d8dd;
+}
+body[data-route="pos"] .numeric_keypad > .row > button:first-child {
+ border-left: 1px solid #d1d8dd;
+}
+body[data-route="pos"] .numeric_keypad > .row:first-child > button {
+ border-top: 1px solid #d1d8dd;
+}
+body[data-route="pos"] .pos-pay {
+ background-color: #5E64FF;
+ border: none;
+}
+body[data-route="pos"] .multimode-payments {
+ padding-left: 30px;
+}
+body[data-route="pos"] .payment-toolbar {
+ padding-right: 30px;
+}
+body[data-route="pos"] .list-row-head.pos-invoice-list {
+ border-top: 1px solid #d1d8dd;
+}
+body[data-route="pos"] .modal-dialog {
+ width: 750px;
+}
+@media (max-width: 767px) {
+ body[data-route="pos"] .modal-dialog {
+ width: auto;
+ }
+ body[data-route="pos"] .modal-dialog .modal-content {
+ height: auto;
+ }
+}
+@media (max-width: 767px) {
+ body[data-route="pos"] .amount-row h3 {
+ font-size: 15px;
+ }
+ body[data-route="pos"] .pos-keyboard-key,
+ body[data-route="pos"] .delete-btn {
+ height: 50px;
+ }
+ body[data-route="pos"] .multimode-payments {
+ padding-left: 15px;
+ }
+ body[data-route="pos"] .payment-toolbar {
+ padding-right: 15px;
+ }
+}
+body[data-route="pos"] .amount-label {
+ font-size: 16px;
+}
+body[data-route="pos"] .selected-payment-mode {
+ background-color: #FAFBFC;
+ cursor: pointer;
+}
+body[data-route="pos"] .pos-invoice-list {
+ padding: 15px 10px;
+}
+body[data-route="pos"] .write_off_amount,
+body[data-route="pos"] .change_amount {
+ margin: 15px;
+ width: 130px;
+}
+body[data-route="pos"] .pos-list-row {
+ display: table;
+ table-layout: fixed;
+ width: 100%;
+ padding: 9px 15px;
+ font-size: 12px;
+ margin: 0px;
+ border-bottom: 1px solid #d1d8dd;
+}
+body[data-route="pos"] .pos-list-row .cell {
+ display: table-cell;
+ vertical-align: middle;
+}
+body[data-route="pos"] .pos-list-row .cell.price-cell {
+ width: 50%;
+}
+body[data-route="pos"] .pos-list-row .subject {
+ width: 40%;
+}
+body[data-route="pos"] .pos-list-row .list-row-checkbox,
+body[data-route="pos"] .pos-list-row .list-select-all {
+ margin-right: 7px;
+}
+body[data-route="pos"] .pos-bill-header {
+ background-color: #f5f7fa;
+ border: 1px solid #d1d8dd;
+ padding: 13px 15px;
+}
+body[data-route="pos"] .pos-list-row.active {
+ background-color: #fffce7;
+}
+body[data-route="pos"] .totals-area {
+ border-right: 1px solid #d1d8dd;
+ border-left: 1px solid #d1d8dd;
+ margin-bottom: 15px;
+}
+body[data-route="pos"] .tax-area .pos-list-row {
+ border: none;
+}
+body[data-route="pos"] .item-cart-items {
+ height: calc(100vh - 526px);
+ overflow: auto;
+ border: 1px solid #d1d8dd;
+ border-top: none;
+}
+body[data-route="pos"] .no-items-message {
+ min-height: 200px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+}
+body[data-route="pos"] .pos-list-row:last-child {
+ border-bottom: none;
+}
+body[data-route="pos"] .form-section-heading {
+ padding: 0;
+}
+body[data-route="pos"] .item-list {
+ border: 1px solid #d1d8dd;
+ border-top: none;
+ max-height: calc(100vh - 190px);
+ overflow: auto;
+}
+@media (max-width: 767px) {
+ body[data-route="pos"] .item-list {
+ max-height: initial;
+ }
+}
+body[data-route="pos"] .item-list .image-field {
+ height: 140px;
+}
+body[data-route="pos"] .item-list .pos-item-wrapper {
+ position: relative;
+}
+body[data-route="pos"] .item-list .price-info {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ margin: 0 0 15px 15px;
+ background-color: rgba(141, 153, 166, 0.6);
+ padding: 5px 9px;
+ border-radius: 3px;
+ color: #fff;
+}
+body[data-route="pos"] .pos-bill-toolbar {
+ margin-top: 10px;
+}
+body[data-route="pos"] .search-item .form-group {
+ margin: 0;
+}
+body[data-route="pos"] .item-list-area .pos-bill-header {
+ padding: 5px;
+ padding-left: 15px;
+}
+body[data-route="pos"] .pos-selected-item-action > .pos-list-row {
+ border: none;
+}
+body[data-route="pos"] .edit-customer-btn {
+ position: absolute;
+ right: 57px;
+ top: 15px;
+ z-index: 100;
+}
+body[data-route="pos"] .btn-more {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+ background-color: #fafbfc;
+ min-height: 200px;
+}
+body[data-route="pos"] .collapse-btn {
+ cursor: pointer;
+}
+
diff --git a/erpnext/public/js/pos/customer_toolbar.html b/erpnext/public/js/pos/customer_toolbar.html
new file mode 100644
index 0000000..3ba5ccb
--- /dev/null
+++ b/erpnext/public/js/pos/customer_toolbar.html
@@ -0,0 +1,16 @@
+<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
index 44e42d7..e356d87 100644
--- a/erpnext/public/js/pos/pos.html
+++ b/erpnext/public/js/pos/pos.html
@@ -1,86 +1,127 @@
<div class="pos">
- <div class="row">
- <div class="col-sm-6 pos-bill-wrapper">
- <div class="pos-bill-toolbar" style="display: flex;">
- <div class="party-area" style="flex: 1;"></div>
- <button class="btn btn-default list-customers-btn" style="margin: 0 5px 0 15px;">
- <i class="fa fa-list"></i>
- </button>
- <button class="btn btn-default add-customer-btn">
- <i class="fa fa-plus"></i>
- </button>
- {% if (allow_delete) { %}
- <button class="btn btn-default btn-danger" style="margin: 0 5px 0 5px;display:none">
- <i class="octicon octicon-trashcan"></i>
- </button>
- {% } %}
- </div>
- <div class="pos-bill">
- <div class="item-cart">
- <div class="row pos-bill-row pos-bill-header">
- <div class="col-xs-4"><h6>{%= __("Item") %}</h6></div>
- <div class="col-xs-3"><h6 class="text-right">{%= __("Quantity") %}</h6></div>
- <div class="col-xs-2"><h6 class="text-right">{%= __("Discount") %}</h6></div>
- <div class="col-xs-3"><h6 class="text-right">{%= __("Rate") %}</h6></div>
- </div>
- <div class="items"></div>
- </div>
- <div class="totals-area">
- <div class="row pos-bill-row net-total-area">
- <div class="col-xs-6"><h6 class="text-muted">{%= __("Net Total") %}</h6></div>
- <div class="col-xs-6"><h6 class="net-total text-right"></h6></div>
- </div>
- <div class="row pos-bill-row tax-area hide">
- <div class="col-xs-12 text-muted">
- <h6>{%= __("Taxes") %}</h6>
- <div class="tax-table small"></div>
+ <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>
- {% if (apply_discount_on) { %}
- <div class="row pos-bill-row discount-amount-area">
- <div class="col-xs-6"><h6 class="text-muted">{%= __("Discount") %}</h6></div>
- <div class="col-xs-3 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>
- <div class="col-xs-3 discount-field-col">
- <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="row pos-bill-row grand-total-area">
- <div class="col-xs-6"><h6>{%= __("Grand Total") %}</h6></div>
- <div class="col-xs-6"><h6 class="grand-total text-right"></h6></div>
- </div>
- </div>
- </div>
- <div class="list-customers">
-
+ <div class="items">
+ </div>
+ </div>
+ </div>
</div>
- </div>
- <div class="col-sm-6 pos-items-section">
- <div class="row pos-item-area">
-
+ <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 (apply_discount_on) { %}
+ <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>
- <span id="customer-results" style="color:#68a;"></span>
- <div class="row pos-item-toolbar">
- <div class="search-item-group col-xs-5"></div>
- <div class="search-item col-xs-7"></div>
- </div>
- <div class="item-list-area" style="auto">
- <div class="app-listing item-list"></ul>
- </div>
- </div>
- <div class="row">
- <div class="text-right list-paging-area">
- <button class="btn btn-default btn-more btn-sm" style="margin:5px 20px">{{ __("More") }}</button>
+ <div 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" 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>
+ </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>
\ No newline at end of file
diff --git a/erpnext/public/js/pos/pos_bill_item.html b/erpnext/public/js/pos/pos_bill_item.html
index 1a1f1e2..21868a6 100644
--- a/erpnext/public/js/pos/pos_bill_item.html
+++ b/erpnext/public/js/pos/pos_bill_item.html
@@ -18,13 +18,13 @@
</div>
<div class="col-xs-2 text-right">
<div class="row input-sm">
- <input type="tel" value="{%= discount_percentage %}" class="form-control text-right pos-item-discount">
+ <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-rate text-right">
+ <input type="tel" value="{%= rate %}" class="form-control input-sm pos-item-price text-right">
{% } else { %}
<h6>{%= format_currency(rate) %}</h6>
{% } %}
diff --git a/erpnext/public/js/pos/pos_bill_item_new.html b/erpnext/public/js/pos/pos_bill_item_new.html
new file mode 100644
index 0000000..80a33d4
--- /dev/null
+++ b/erpnext/public/js/pos/pos_bill_item_new.html
@@ -0,0 +1,9 @@
+<div class="pos-list-row pos-bill-item" 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
index 67110a7..13aa520 100644
--- a/erpnext/public/js/pos/pos_invoice_list.html
+++ b/erpnext/public/js/pos/pos_invoice_list.html
@@ -1,7 +1,9 @@
-<div class="row list-row pos-invoice-list" invoice-name = "{{name}}">
- <div class="col-xs-1"><input class="list-delete" type="checkbox"></div>
- <div class="list-column col-xs-3">{%= customer %}</div>
- <div class="list-column col-xs-2 text-left"><span class="indicator {{data.indicator}}">{{ data.status }}</span></div>
- <div class="list-column col-xs-3 text-right">{%= paid_amount %}</div>
- <div class="list-column col-xs-3 text-right">{%= grand_total %}</div>
+<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
index b33076d..fbc380b 100644
--- a/erpnext/public/js/pos/pos_item.html
+++ b/erpnext/public/js/pos/pos_item.html
@@ -1,13 +1,32 @@
-<div class="pos-item-wrapper col-xs-3">
- <div class="pos-item" data-item-code="{%= item_code %}" title="{%= item_name || item_code %}">
- <div class="pos-item-image"
- style="{% if (item_image) { %} background-image: {{ item_image }} {% }
- else { %} background-color: {{ color }} {% } %}">
- {% if (!item_image) { %}{{ abbr }}{% } %}
+<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}}</a>
</div>
- <div class="pos-item-text">
- <h6 class="item-code ellipsis">{%= item_name ? (item_name + " (" + item_code + ")") : item_code %}</h6>
- <div class="small ellipsis">{%= item_price %}</div>
- </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}}
+ </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
new file mode 100644
index 0000000..30cf0f0
--- /dev/null
+++ b/erpnext/public/js/pos/pos_selected_item.html
@@ -0,0 +1,21 @@
+<div class="pos-selected-item-action" data-item-code="{%= item_code %}">
+ <div class="pos-list-row">
+ <span class="cell bold">{{item_name}}</span>
+ </div>
+ <div class="pos-list-row">
+ <div class="cell">Quantity:</div>
+ <input class="form-control cell pos-item-qty" value="{%= qty %}"/>
+ </div>
+ <div class="pos-list-row">
+ <div class="cell">Discount:</div>
+ <input class="form-control cell pos-item-disc" value="{%= discount_percentage %}">
+ </div>
+ <div class="pos-list-row">
+ <div class="cell">Price:</div>
+ <input class="form-control cell pos-item-price" value="{%= rate %}"/>
+ </div>
+ <div class="pos-list-row">
+ <div class="cell">Amount:</div>
+ <input class="form-control cell" 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
index 788eb1f..3752a89 100644
--- a/erpnext/public/js/pos/pos_tax_row.html
+++ b/erpnext/public/js/pos/pos_tax_row.html
@@ -1,4 +1,4 @@
-<div class="row">
- <div class="col-xs-9">{%= description %}</div>
- <div class="col-xs-3 text-right">{%= tax_amount %}</div>
+<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/less/erpnext.less b/erpnext/public/less/erpnext.less
index 495e618..0a48970 100644
--- a/erpnext/public/less/erpnext.less
+++ b/erpnext/public/less/erpnext.less
@@ -17,140 +17,12 @@
margin: -10px auto;
}
-/* pos */
-
-.pos-item-area {
- padding: 0px 10px;
-}
-
-.pos-item-wrapper {
- padding: 5px;
-}
-
-.pos-item {
- overflow: hidden;
- text-overflow: ellipsis;
- cursor: pointer;
- padding: 5px;
- padding-bottom: 15px;
- border: 1px solid #d1d8dd;
- margin-bottom: 5px;
-}
-
-.pos-item-text {
- padding: 0px 5px;
-}
-
-.pos-item .item-code {
- margin-bottom: 0px;
-}
-
-.pos-item .no-image {
- background-color: #fafbfc;
- border: 1px dashed #d1d8dd;
-}
-
-.pos-item-image {
- width: 100%;
- height: 0px;
- padding: 50% 0;
- text-align: center;
- line-height: 0;
- color: @text-extra-muted;
- font-size: 30px;
- background-size: contain;
- border: 1px solid transparent;
- background-position: center;
- background-repeat: no-repeat;
-}
-
-.pos-item-area {
- border: 1px solid #d1d8dd;
- border-top: none;
-}
-
-.pos-item-toolbar {
- padding: 10px 0px;
- border-bottom: 1px solid #d1d8dd;
-}
-
-.item-list-area {
- padding: 15px 0px;
- overflow-y: scroll;
- height: ~"calc(100vh - 162px)";
-}
-
-.pos-toolbar, .pos-bill-toolbar {
- padding: 10px 0px;
- // border-bottom: 1px solid #d1d8dd;
- height: 51px;
-}
-
-.pos-item-toolbar .form-group {
- margin-bottom: 0px;
-}
-
-.pos-bill-wrapper {
- border: 1px solid #d1d8dd;
- border-top: none;
- margin-right: -1px;
-}
-
-.pos-bill {
- border-top: 1px solid @border-color;
- margin-left: -15px;
- margin-right: -15px;
-}
-
-.pos-bill-row {
- margin: 0px;
- padding: 7px 0px;
- border-top: 1px solid #d1d8dd;
-}
-
-.pos-bill-header {
- border: none !important;
- background-color: #f5f7fa;
-}
-
-.pos-item-qty {
- display: inline-block;
-}
-
-.pos-qty-row > div {
- padding: 5px 0px;
-}
-
-.pos-qty-btn {
- margin-top: 3px;
- cursor: pointer;
- font-size: 120%;
-}
-
-.pos .search-area .form-group {
- max-width: 100% !important;
-}
-
-.pos .tax-table {
- margin-bottom: 10px;
-}
-
.erpnext-icon {
- width: 24px;ack
+ width: 24px;
margin-right: 0px;
margin-top: -3px;
}
-.pos .discount-amount-area {
- .discount-field-col {
- padding-left: 0px;
- }
-
- .input-group {
- margin-top: 2px;
- }
-}
-
.dashboard-list-item {
background-color: inherit;
padding: 5px 0px;
@@ -165,104 +37,6 @@
border-bottom: none;
}
-.payment-toolbar {
- .row {
- width: 323px;
- margin: 0 auto;
- }
-}
-
-.payment-mode {
- cursor: pointer;
- font-family: sans-serif;
- font-size: 15px;
-}
-
-.pos-payment-row .col-xs-6 {
- padding :15px;
-}
-
-.pos-payment-row {
- border-bottom:1px solid #d1d8dd;
- margin: 2px 0px 5px 0px;
- height: 60px;
- margin-top: 0px;
- margin-bottom: 0px;
-}
-
-.pos-payment-row:hover, .pos-keyboard-key:hover{
- background-color: #FAFBFC;
- cursor: pointer;
-}
-
-.pos-keyboard-key, .delete-btn {
- border: 1px solid #d1d8dd;
- height:85px;
- width:85px;
- margin:10px 10px;
- font-size:24px;
- font-weight:200;
- background-color: #FDFDFD;
- border-color: #e8e8e8;
-}
-
-.multimode-payments {
- padding-left: 30px;
-}
-
-.payment-toolbar {
- padding-right: 30px;
-}
-
-.list-row-head.pos-invoice-list {
- border-top: 1px solid @border-color;
-}
-
-body[data-route="pos"] .modal-dialog {
- width: 750px;
-
- @media (max-width: @screen-xs) {
- width: auto;
-
- .modal-content {
- height: auto;
- }
- }
-}
-
-@media (max-width: @screen-xs) {
- .amount-row h3 {
- font-size: 15px;
- }
- .pos-keyboard-key, .delete-btn {
- height: 50px;
- }
- .multimode-payments {
- padding-left: 15px;
- }
- .payment-toolbar {
- padding-right: 15px;
- }
-}
-
-.amount-label {
- font-size: 16px;
-}
-
-.selected-payment-mode {
- background-color: #FAFBFC;
- cursor: pointer;
-}
-
-.pos-invoice-list {
- padding: 15px 10px;
-}
-
-.write_off_amount, .change_amount {
- margin: 15px;
- width: 130px;
-}
-
// assessment tool
.frappe-control[data-fieldname='result_html'] {
overflow: scroll;
@@ -286,4 +60,338 @@
.total-score, .grade, .score {
text-align: right;
}
+}
+
+/* pos */
+
+body[data-route="pos"] {
+
+ .pos-bill-toolbar {
+ padding: 10px 0px;
+ height: 51px;
+ }
+
+ .pos-bill-item:hover, .list-customers-table > .pos-list-row:hover {
+ background-color: #f5f7fa;
+ cursor: pointer;
+ }
+
+ .pos-item-qty {
+ display: inline-block;
+ }
+
+ .pos-qty-row > div {
+ padding: 5px 0px;
+ }
+
+ .pos-qty-btn {
+ margin-top: 3px;
+ cursor: pointer;
+ font-size: 120%;
+ }
+
+ .search-area .form-group {
+ max-width: 100% !important;
+ }
+
+ .tax-table {
+ margin-bottom: 10px;
+ }
+
+ .discount-field-col {
+ padding-left: 24px;
+ }
+
+ .discount-amount-area {
+ .input-group:first-child {
+ margin-bottom: 2px;
+ }
+ }
+
+ .payment-toolbar {
+ .row {
+ width: 323px;
+ margin: 0 auto;
+ }
+ }
+
+ .payment-mode {
+ cursor: pointer;
+ font-family: sans-serif;
+ font-size: 15px;
+ }
+
+ .pos-payment-row .col-xs-6 {
+ padding :15px;
+ }
+
+ .pos-payment-row {
+ border-bottom:1px solid #d1d8dd;
+ margin: 2px 0px 5px 0px;
+ height: 60px;
+ margin-top: 0px;
+ margin-bottom: 0px;
+ }
+
+ .pos-payment-row:hover, .pos-keyboard-key:hover{
+ background-color: #FAFBFC;
+ cursor: pointer;
+ }
+
+ .pos-keyboard-key, .delete-btn {
+ border: 1px solid #d1d8dd;
+ height:85px;
+ width:85px;
+ margin:10px 10px;
+ font-size:24px;
+ font-weight:200;
+ background-color: #FDFDFD;
+ border-color: #e8e8e8;
+ }
+
+ .numeric-keypad {
+ border: 1px solid #d1d8dd;
+ height:69px;
+ width:69px;
+ font-size:20px;
+ font-weight:200;
+ background-color: #FDFDFD;
+ border-color: #e8e8e8;
+ margin-left:-4px;
+ }
+
+ .pos-pay {
+ height:69px;
+ width:69px;
+ font-size:17px;
+ font-weight:200;
+ margin-left:-4px;
+ }
+
+ .numeric-keypad {
+ height: 60px;
+ width: 60px;
+ font-size: 20px;
+ font-weight: 200;
+ border-radius: 0;
+ background-color: #fff;
+ margin-left:-4px;
+ }
+
+ .numeric_keypad {
+ margin-left: -15px;
+
+ & > .row > button {
+ border: none;
+ border-right: 1px solid @border-color;
+ border-bottom: 1px solid @border-color;
+
+ &:first-child {
+ border-left: 1px solid @border-color;
+ }
+ }
+
+ & > .row:first-child > button {
+ border-top: 1px solid @border-color;
+ }
+ }
+
+ .pos-pay {
+ background-color: @brand-primary;
+ border: none;
+ }
+
+ .multimode-payments {
+ padding-left: 30px;
+ }
+
+ .payment-toolbar {
+ padding-right: 30px;
+ }
+
+ .list-row-head.pos-invoice-list {
+ border-top: 1px solid @border-color;
+ }
+
+ .modal-dialog {
+ width: 750px;
+
+ @media (max-width: @screen-xs) {
+ width: auto;
+
+ .modal-content {
+ height: auto;
+ }
+ }
+ }
+
+ @media (max-width: @screen-xs) {
+ .amount-row h3 {
+ font-size: 15px;
+ }
+ .pos-keyboard-key, .delete-btn {
+ height: 50px;
+ }
+ .multimode-payments {
+ padding-left: 15px;
+ }
+ .payment-toolbar {
+ padding-right: 15px;
+ }
+ }
+
+ .amount-label {
+ font-size: 16px;
+ }
+
+ .selected-payment-mode {
+ background-color: #FAFBFC;
+ cursor: pointer;
+ }
+
+ .pos-invoice-list {
+ padding: 15px 10px;
+ }
+
+ .write_off_amount, .change_amount {
+ margin: 15px;
+ width: 130px;
+ }
+
+ .pos-list-row {
+ display: table;
+ table-layout: fixed;
+ width: 100%;
+ padding: 9px 15px;
+ font-size: 12px;
+ margin: 0px;
+ border-bottom: 1px solid @border-color;
+
+ .cell {
+ display: table-cell;
+ vertical-align: middle;
+
+ &.price-cell {
+ width: 50%;
+ }
+ }
+
+ .subject {
+ width: 40%
+ }
+
+ .list-row-checkbox, .list-select-all {
+ margin-right: 7px;
+ }
+ }
+
+ .pos-bill-header {
+ background-color: #f5f7fa;
+ border: 1px solid @border-color;
+ padding: 13px 15px;
+ }
+
+ .pos-list-row.active {
+ background-color: @light-yellow;
+ }
+
+ .totals-area {
+ border-right: 1px solid @border-color;
+ border-left: 1px solid @border-color;
+ margin-bottom: 15px;
+ }
+
+ .tax-area .pos-list-row {
+ border: none;
+ }
+
+ .item-cart-items {
+ height: ~"calc(100vh - 526px)";
+ overflow: auto;
+ border: 1px solid @border-color;
+ border-top: none;
+ }
+
+ .no-items-message {
+ min-height: 200px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ }
+
+ .pos-list-row:last-child {
+ border-bottom: none;
+ }
+
+ .form-section-heading {
+ padding: 0;
+ }
+
+ .item-list {
+ border: 1px solid @border-color;
+ border-top: none;
+ max-height: ~"calc(100vh - 190px)";
+ overflow: auto;
+
+ @media (max-width: @screen-xs) {
+ max-height: initial;
+ }
+
+ .image-field {
+ height: 140px;
+ }
+
+ .pos-item-wrapper {
+ position: relative;
+ }
+
+ .price-info {
+ position: absolute;
+ left: 0;
+ bottom: 0;
+ margin: 0 0 15px 15px;
+ background-color: rgba(141, 153, 166, 0.6);
+ padding: 5px 9px;
+ border-radius: 3px;
+ color: #fff;
+ }
+ }
+
+ .pos-bill-toolbar {
+ margin-top: 10px;
+ }
+
+ .search-item .form-group {
+ margin: 0;
+ }
+
+ .item-list-area .pos-bill-header {
+ padding: 5px;
+ padding-left: 15px;
+ }
+
+ .pos-selected-item-action > .pos-list-row {
+ border: none;
+ }
+
+ .edit-customer-btn {
+ position: absolute;
+ right: 57px;
+ top: 15px;
+ z-index: 100;
+ }
+
+ .btn-more {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ cursor: pointer;
+ background-color: @light-bg;
+ min-height: 200px;
+ }
+
+ .collapse-btn {
+ cursor: pointer;
+ }
}
\ No newline at end of file
diff --git a/erpnext/schools/doctype/student/student.js b/erpnext/schools/doctype/student/student.js
index c7b1d46..d3d248b 100644
--- a/erpnext/schools/doctype/student/student.js
+++ b/erpnext/schools/doctype/student/student.js
@@ -1,6 +1,17 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
+frappe.ui.form.on('Student', {
+ setup: function(frm) {
+ frm.set_query("student", "siblings", function(doc, cdt, cdn) {
+ return {
+ "filters": {
+ "name": ["!=", doc.name]
+ }
+ };
+ })
+ }
+});
frappe.ui.form.on("Student Guardian", {
guardian: function(frm) {
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 0d8b41f..0b0a020 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -31,7 +31,8 @@
},
onload_post_render: function(frm) {
- frm.get_field("delete_company_transactions").$input.addClass("btn-danger");
+ if(frm.get_field("delete_company_transactions").$input)
+ frm.get_field("delete_company_transactions").$input.addClass("btn-danger");
},
country: function(frm) {
erpnext.company.set_chart_of_accounts_options(frm.doc);
diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index f52d71e..7497a81 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:company_name",
@@ -407,7 +408,7 @@
"label": "Create Chart Of Accounts Based On",
"length": 0,
"no_copy": 0,
- "options": "Standard Template\nExisting Company",
+ "options": "\nStandard Template\nExisting Company",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -415,7 +416,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 0,
+ "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -1680,19 +1681,19 @@
"unique": 0
}
],
+ "has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-building",
"idx": 1,
"image_view": 0,
"in_create": 0,
- "in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
- "modified": "2017-03-02 15:24:52.908559",
+ "modified": "2017-03-12 15:50:23.099622",
"modified_by": "Administrator",
"module": "Setup",
"name": "Company",
@@ -1846,4 +1847,4 @@
"sort_order": "ASC",
"track_changes": 0,
"track_seen": 0
-}
+}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/company/test_company.py b/erpnext/setup/doctype/company/test_company.py
index d2e7d23..4b864c4 100644
--- a/erpnext/setup/doctype/company/test_company.py
+++ b/erpnext/setup/doctype/company/test_company.py
@@ -28,7 +28,7 @@
"root_type": "Asset",
"parent_account": "Accounts Receivable - CFEC",
},
- "_Test Cash - CFEC": {
+ "Cash - CFEC": {
"account_type": "Cash",
"is_group": 0,
"root_type": "Asset",