Merge branch 'develop' into backport-github-action
diff --git a/.travis.yml b/.travis.yml
index 365eb67..213445b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -77,5 +77,6 @@
- bench --site test_site reinstall --yes
after_script:
+ - pip install coverage==4.5.4
- pip install python-coveralls
- coveralls -b apps/erpnext -d ../../sites/.coverage
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 80be2c8..a68c368 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -1058,7 +1058,7 @@
@frappe.whitelist()
-def block_invoice(name, hold_comment, release_date):
+def block_invoice(name, release_date, hold_comment=None):
if frappe.db.exists('Purchase Invoice', name):
pi = frappe.get_doc('Purchase Invoice', name)
pi.block_invoice(hold_comment, release_date)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 8b4923f..ad3640c 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1243,25 +1243,28 @@
precision = self.precision("outstanding_amount")
outstanding_amount = flt(self.outstanding_amount, precision)
+ due_date = getdate(self.due_date)
+ nowdate = getdate()
+ discountng_status = self.get_discounting_status()
if not status:
if self.docstatus == 2:
status = "Cancelled"
elif self.docstatus == 1:
- if outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
+ if outstanding_amount > 0 and due_date < nowdate and self.is_discounted and discountng_status=='Disbursed':
self.status = "Overdue and Discounted"
- elif outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()):
+ elif outstanding_amount > 0 and due_date < nowdate:
self.status = "Overdue"
- elif outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
+ elif outstanding_amount > 0 and due_date >= nowdate and self.is_discounted and discountng_status=='Disbursed':
self.status = "Unpaid and Discounted"
- elif outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()):
+ elif outstanding_amount > 0 and due_date >= nowdate:
self.status = "Unpaid"
#Check if outstanding amount is 0 due to credit note issued against invoice
elif outstanding_amount <= 0 and self.is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}):
self.status = "Credit Note Issued"
elif self.is_return == 1:
self.status = "Return"
- elif outstanding_amount <=0:
+ elif outstanding_amount<=0:
self.status = "Paid"
else:
self.status = "Submitted"
diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py
index 62a04f3..df143ee 100644
--- a/erpnext/buying/doctype/supplier/supplier.py
+++ b/erpnext/buying/doctype/supplier/supplier.py
@@ -58,7 +58,9 @@
frappe.db.set(self, "supplier_name", newdn)
def create_onboarding_docs(self, args):
- defaults = frappe.defaults.get_defaults()
+ company = frappe.defaults.get_defaults().get('company') or \
+ frappe.db.get_single_value('Global Defaults', 'default_company')
+
for i in range(1, args.get('max_count')):
supplier = args.get('supplier_name_' + str(i))
if supplier:
@@ -67,7 +69,7 @@
'doctype': self.doctype,
'supplier_name': supplier,
'supplier_group': _('Local'),
- 'company': defaults.get('company')
+ 'company': company
}).insert()
if args.get('supplier_email_' + str(i)):
diff --git a/erpnext/education/doctype/student_group/student_group.py b/erpnext/education/doctype/student_group/student_group.py
index aa542dd..2925469 100644
--- a/erpnext/education/doctype/student_group/student_group.py
+++ b/erpnext/education/doctype/student_group/student_group.py
@@ -26,6 +26,8 @@
frappe.throw(_("Please select Program"))
def validate_strength(self):
+ if self.max_strength <= 0:
+ frappe.throw(_("""Max strength must be greater than zero."""))
if self.max_strength and len(self.students) > self.max_strength:
frappe.throw(_("""Cannot enroll more than {0} students for this student group.""").format(self.max_strength))
diff --git a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
index 28c2ab9..4422d23 100644
--- a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
+++ b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
@@ -47,11 +47,12 @@
return "success"
if event == "created":
+ sys_lang = frappe.get_single("System Settings").language or 'en'
raw_billing_data = order.get("billing")
customer_name = raw_billing_data.get("first_name") + " " + raw_billing_data.get("last_name")
link_customer_and_address(raw_billing_data, customer_name)
- link_items(order.get("line_items"), woocommerce_settings)
- create_sales_order(order, woocommerce_settings, customer_name)
+ link_items(order.get("line_items"), woocommerce_settings, sys_lang)
+ create_sales_order(order, woocommerce_settings, customer_name, sys_lang)
def link_customer_and_address(raw_billing_data, customer_name):
customer_woo_com_email = raw_billing_data.get("email")
@@ -100,7 +101,7 @@
frappe.rename_doc("Address", old_address_title, new_address_title)
-def link_items(items_list, woocommerce_settings):
+def link_items(items_list, woocommerce_settings, sys_lang):
for item_data in items_list:
item_woo_com_id = item_data.get("product_id")
@@ -112,14 +113,14 @@
item = frappe.new_doc("Item")
item.item_name = item_data.get("name")
- item.item_code = _("woocommerce - {0}").format(item_data.get("product_id"))
+ item.item_code = _("woocommerce - {0}", sys_lang).format(item_data.get("product_id"))
item.woocommerce_id = item_data.get("product_id")
- item.item_group = _("WooCommerce Products")
- item.stock_uom = woocommerce_settings.uom or _("Nos")
+ item.item_group = _("WooCommerce Products", sys_lang)
+ item.stock_uom = woocommerce_settings.uom or _("Nos", sys_lang)
item.flags.ignore_mandatory = True
item.save()
-def create_sales_order(order, woocommerce_settings, customer_name):
+def create_sales_order(order, woocommerce_settings, customer_name, sys_lang):
new_sales_order = frappe.new_doc("Sales Order")
new_sales_order.customer = customer_name
@@ -133,14 +134,14 @@
new_sales_order.company = woocommerce_settings.company
- set_items_in_sales_order(new_sales_order, woocommerce_settings, order)
+ set_items_in_sales_order(new_sales_order, woocommerce_settings, order, sys_lang)
new_sales_order.flags.ignore_mandatory = True
new_sales_order.insert()
new_sales_order.submit()
frappe.db.commit()
-def set_items_in_sales_order(new_sales_order, woocommerce_settings, order):
+def set_items_in_sales_order(new_sales_order, woocommerce_settings, order, sys_lang):
company_abbr = frappe.db.get_value('Company', woocommerce_settings.company, 'abbr')
for item in order.get("line_items"):
@@ -154,10 +155,10 @@
"item_name": found_item.item_name,
"description": found_item.item_name,
"delivery_date": new_sales_order.delivery_date,
- "uom": woocommerce_settings.uom or _("Nos"),
+ "uom": woocommerce_settings.uom or _("Nos", sys_lang),
"qty": item.get("quantity"),
"rate": item.get("price"),
- "warehouse": woocommerce_settings.warehouse or _("Stores - {0}").format(company_abbr)
+ "warehouse": woocommerce_settings.warehouse or _("Stores - {0}", sys_lang).format(company_abbr)
})
add_tax_details(new_sales_order, ordered_items_tax, "Ordered Item tax", woocommerce_settings.tax_account)
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py
index 2f39dc5..3bc8db5 100644
--- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_methods.py
@@ -165,6 +165,9 @@
return item.name
def create_manufacturer(amazon_item_json):
+ if not amazon_item_json.Product.AttributeSets.ItemAttributes.Manufacturer:
+ return None
+
existing_manufacturer = frappe.db.get_value("Manufacturer",
filters={"short_name":amazon_item_json.Product.AttributeSets.ItemAttributes.Manufacturer})
@@ -177,6 +180,9 @@
return existing_manufacturer
def create_brand(amazon_item_json):
+ if not amazon_item_json.Product.AttributeSets.ItemAttributes.Brand:
+ return None
+
existing_brand = frappe.db.get_value("Brand",
filters={"brand":amazon_item_json.Product.AttributeSets.ItemAttributes.Brand})
if not existing_brand:
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py
index 249a73f..c222afb 100644
--- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/amazon_mws_settings.py
@@ -7,7 +7,6 @@
from frappe.model.document import Document
import dateutil
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
-from erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_methods import get_products_details, get_orders
class AmazonMWSSettings(Document):
def validate(self):
@@ -19,12 +18,12 @@
def get_products_details(self):
if self.enable_amazon == 1:
- get_products_details()
+ frappe.enqueue('erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_methods.get_products_details')
def get_order_details(self):
if self.enable_amazon == 1:
after_date = dateutil.parser.parse(self.after_date).strftime("%Y-%m-%d")
- get_orders(after_date = after_date)
+ frappe.enqueue('erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_methods.get_orders', after_date=after_date)
def schedule_get_order_details():
mws_settings = frappe.get_doc("Amazon MWS Settings")
diff --git a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py
index 58db669..a25a29f 100644
--- a/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py
+++ b/erpnext/erpnext_integrations/doctype/amazon_mws_settings/xml_utils.py
@@ -33,7 +33,10 @@
def __getattr__(self, item):
- d = self.__getitem__(item)
+ try:
+ d = self.__getitem__(item)
+ except KeyError:
+ return None
if isinstance(d, dict) and 'value' in d and len(d) == 1:
return d['value']
diff --git a/erpnext/hr/doctype/attendance/attendance.json b/erpnext/hr/doctype/attendance/attendance.json
index ab2dc4a..eaca9f6 100644
--- a/erpnext/hr/doctype/attendance/attendance.json
+++ b/erpnext/hr/doctype/attendance/attendance.json
@@ -58,11 +58,12 @@
{
"fetch_from": "employee.employee_name",
"fieldname": "employee_name",
- "fieldtype": "Read Only",
+ "fieldtype": "Data",
"in_global_search": 1,
"label": "Employee Name",
"oldfieldname": "employee_name",
- "oldfieldtype": "Data"
+ "oldfieldtype": "Data",
+ "read_only": 1
},
{
"depends_on": "working_hours",
@@ -174,8 +175,7 @@
"icon": "fa fa-ok",
"idx": 1,
"is_submittable": 1,
- "links": [],
- "modified": "2020-01-27 20:25:29.572281",
+ "modified": "2020-02-19 14:25:32.945842",
"modified_by": "Administrator",
"module": "HR",
"name": "Attendance",
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py
index b621642..6e909c3 100644
--- a/erpnext/hr/doctype/leave_application/test_leave_application.py
+++ b/erpnext/hr/doctype/leave_application/test_leave_application.py
@@ -409,7 +409,7 @@
self.assertEqual(get_leave_balance_on(employee.name, leave_type.name, nowdate(), add_days(nowdate(), 8)), 21)
- def test_earned_leave(self):
+ def test_earned_leaves_creation(self):
leave_period = get_leave_period()
employee = get_employee()
leave_type = 'Test Earned Leave Type'
@@ -437,6 +437,14 @@
i += 1
self.assertEqual(get_leave_balance_on(employee.name, leave_type, nowdate()), 6)
+ # validate earned leaves creation without maximum leaves
+ frappe.db.set_value('Leave Type', leave_type, 'max_leaves_allowed', 0)
+ i = 0
+ while(i<6):
+ allocate_earned_leaves()
+ i += 1
+ self.assertEqual(get_leave_balance_on(employee.name, leave_type, nowdate()), 9)
+
# test to not consider current leave in leave balance while submitting
def test_current_leave_on_submit(self):
employee = get_employee()
diff --git a/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py b/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py
index 35400b0..3770da7 100644
--- a/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py
+++ b/erpnext/hr/doctype/vehicle_log/test_vehicle_log.py
@@ -8,25 +8,9 @@
from frappe.utils import nowdate,flt, cstr,random_string
# test_records = frappe.get_test_records('Vehicle Log')
class TestVehicleLog(unittest.TestCase):
- def test_make_vehicle_log(self):
- license_plate=random_string(10).upper()
+ def test_make_vehicle_log_and_syncing_of_odometer_value(self):
employee_id=frappe.db.sql("""select name from `tabEmployee` order by modified desc limit 1""")[0][0]
- vehicle = frappe.get_doc({
- "doctype": "Vehicle",
- "license_plate": cstr(license_plate),
- "make": "Maruti",
- "model": "PCM",
- "last_odometer":5000,
- "acquisition_date":frappe.utils.nowdate(),
- "location": "Mumbai",
- "chassis_no": "1234ABCD",
- "uom": "Litre",
- "vehicle_value":frappe.utils.flt(500000)
- })
- try:
- vehicle.insert()
- except frappe.DuplicateEntryError:
- pass
+ license_plate = get_vehicle(employee_id)
vehicle_log = frappe.get_doc({
"doctype": "Vehicle Log",
"license_plate": cstr(license_plate),
@@ -36,5 +20,41 @@
"fuel_qty":frappe.utils.flt(50),
"price": frappe.utils.flt(500)
})
- vehicle_log.insert()
- vehicle_log.submit()
\ No newline at end of file
+ vehicle_log.save()
+ vehicle_log.submit()
+
+ #checking value of vehicle odometer value on submit.
+ vehicle = frappe.get_doc("Vehicle", license_plate)
+ self.assertEqual(vehicle.last_odometer, vehicle_log.odometer)
+
+ #checking value vehicle odometer on vehicle log cancellation.
+ last_odometer = vehicle_log.last_odometer
+ current_odometer = vehicle_log.odometer
+ distance_travelled = current_odometer - last_odometer
+
+ vehicle_log.cancel()
+ vehicle.reload()
+
+ self.assertEqual(vehicle.last_odometer, current_odometer - distance_travelled)
+
+
+def get_vehicle(employee_id):
+ license_plate=random_string(10).upper()
+ vehicle = frappe.get_doc({
+ "doctype": "Vehicle",
+ "license_plate": cstr(license_plate),
+ "make": "Maruti",
+ "model": "PCM",
+ "employee": employee_id,
+ "last_odometer":5000,
+ "acquisition_date":frappe.utils.nowdate(),
+ "location": "Mumbai",
+ "chassis_no": "1234ABCD",
+ "uom": "Litre",
+ "vehicle_value":frappe.utils.flt(500000)
+ })
+ try:
+ vehicle.insert()
+ except frappe.DuplicateEntryError:
+ pass
+ return license_plate
\ No newline at end of file
diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.js b/erpnext/hr/doctype/vehicle_log/vehicle_log.js
index 7694cfe..bdb37d2 100644
--- a/erpnext/hr/doctype/vehicle_log/vehicle_log.js
+++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.js
@@ -2,29 +2,41 @@
// For license information, please see license.txt
frappe.ui.form.on("Vehicle Log", {
- refresh: function(frm,cdt,cdn) {
- var vehicle_log=frappe.model.get_doc(cdt,cdn);
- if (vehicle_log.license_plate) {
- frappe.call({
- method: "erpnext.hr.doctype.vehicle_log.vehicle_log.get_make_model",
- args: {
- license_plate: vehicle_log.license_plate
- },
- callback: function(r) {
- frappe.model.set_value(cdt, cdn, ("model"), r.message[0]);
- frappe.model.set_value(cdt, cdn, ("make"), r.message[1]);
- }
- })
+ refresh: function(frm) {
+
+ if(frm.doc.license_plate && frm.doc.__islocal){
+ frm.events.set_vehicle_details(frm);
}
if(frm.doc.docstatus == 1) {
frm.add_custom_button(__('Expense Claim'), function() {
- frm.events.expense_claim(frm)
+ frm.events.expense_claim(frm);
}, __('Create'));
frm.page.set_inner_btn_group_as_primary(__('Create'));
}
},
+ license_plate: function(frm) {
+ if(frm.doc.license_plate){
+ frm.events.set_vehicle_details(frm);
+ }
+ },
+
+ set_vehicle_details: function(frm) {
+ frappe.call({
+ method: "erpnext.hr.doctype.vehicle_log.vehicle_log.get_make_model",
+ args: {
+ license_plate: frm.doc.license_plate
+ },
+ callback: function(r) {
+ frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "make", r.message[0]);
+ frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "model", r.message[1]);
+ frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "last_odometer", r.message[2]);
+ frappe.model.set_value(cur_frm.doctype, cur_frm.docname, "employee", r.message[3]);
+ }
+ });
+ },
+
expense_claim: function(frm){
frappe.call({
method: "erpnext.hr.doctype.vehicle_log.vehicle_log.make_expense_claim",
diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.json b/erpnext/hr/doctype/vehicle_log/vehicle_log.json
index cde39e7..52effff 100644
--- a/erpnext/hr/doctype/vehicle_log/vehicle_log.json
+++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.json
@@ -1,706 +1,192 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "naming_series:",
- "beta": 0,
- "creation": "2016-09-03 14:14:51.788550",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Document",
- "editable_grid": 1,
+ "actions": [],
+ "autoname": "naming_series:",
+ "creation": "2016-09-03 14:14:51.788550",
+ "doctype": "DocType",
+ "document_type": "Document",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "vehicle_section",
+ "naming_series",
+ "license_plate",
+ "employee",
+ "column_break_4",
+ "column_break_7",
+ "model",
+ "make",
+ "odometer_reading",
+ "date",
+ "odometer",
+ "column_break_12",
+ "last_odometer",
+ "refuelling_details",
+ "fuel_qty",
+ "price",
+ "column_break_15",
+ "supplier",
+ "invoice",
+ "service_details",
+ "service_detail",
+ "amended_from"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "vehicle_section",
- "fieldtype": "Section Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "options": "fa fa-user",
- "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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "vehicle_section",
+ "fieldtype": "Section Break",
+ "options": "fa fa-user"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "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": "Series",
- "length": 0,
- "no_copy": 1,
- "options": "HR-VLOG-.YYYY.-",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 1,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Series",
+ "no_copy": 1,
+ "options": "HR-VLOG-.YYYY.-",
+ "print_hide": 1,
+ "reqd": 1,
+ "set_only_once": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "license_plate",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "License Plate",
- "length": 0,
- "no_copy": 0,
- "options": "Vehicle",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "license_plate",
+ "fieldtype": "Link",
+ "in_global_search": 1,
+ "in_list_view": 1,
+ "label": "License Plate",
+ "options": "Vehicle",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "employee",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Employee",
- "length": 0,
- "no_copy": 0,
- "options": "Employee",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "employee",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Employee",
+ "options": "Employee",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_4",
- "fieldtype": "Column Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_4",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_7",
- "fieldtype": "Column Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_7",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "model",
- "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": "Model",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "model",
+ "fieldtype": "Read Only",
+ "label": "Model"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "make",
- "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": "Make",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "make",
+ "fieldtype": "Read Only",
+ "label": "Make"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "odometer_reading",
- "fieldtype": "Section Break",
- "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": "Odometer Reading",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "odometer_reading",
+ "fieldtype": "Section Break",
+ "label": "Odometer Reading"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "date",
- "fieldtype": "Date",
- "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": "Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "date",
+ "fieldtype": "Date",
+ "label": "Date",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "odometer",
- "fieldtype": "Int",
- "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": "Odometer",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "odometer",
+ "fieldtype": "Int",
+ "label": "Current Odometer value ",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "refuelling_details",
- "fieldtype": "Section Break",
- "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": "Refuelling Details",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "collapsible": 1,
+ "fieldname": "refuelling_details",
+ "fieldtype": "Section Break",
+ "label": "Refuelling Details"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "fuel_qty",
- "fieldtype": "Float",
- "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": "Fuel Qty",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "fuel_qty",
+ "fieldtype": "Float",
+ "label": "Fuel Qty"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "price",
- "fieldtype": "Currency",
- "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": "Fuel Price",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "price",
+ "fieldtype": "Currency",
+ "label": "Fuel Price"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_15",
- "fieldtype": "Column Break",
- "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,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_15",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "supplier",
- "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": "Supplier",
- "length": 0,
- "no_copy": 0,
- "options": "Supplier",
- "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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "supplier",
+ "fieldtype": "Link",
+ "label": "Supplier",
+ "options": "Supplier"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "invoice",
- "fieldtype": "Data",
- "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": "Invoice Ref",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "invoice",
+ "fieldtype": "Data",
+ "label": "Invoice Ref"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 1,
- "columns": 0,
- "fieldname": "service_details",
- "fieldtype": "Section Break",
- "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": "Service Details",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "collapsible": 1,
+ "fieldname": "service_details",
+ "fieldtype": "Section Break",
+ "label": "Service Details"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "service_detail",
- "fieldtype": "Table",
- "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": "Service Detail",
- "length": 0,
- "no_copy": 0,
- "options": "Vehicle Service",
- "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,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "service_detail",
+ "fieldtype": "Table",
+ "label": "Service Detail",
+ "options": "Vehicle Service"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amended_from",
- "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": "Amended From",
- "length": 0,
- "no_copy": 1,
- "options": "Vehicle Log",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Vehicle Log",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "last_odometer",
+ "fieldtype": "Int",
+ "label": "last Odometer Value ",
+ "read_only": 1,
+ "reqd": 1
+ },
+ {
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2018-08-21 14:44:51.131186",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Vehicle Log",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-01-28 12:43:34.419647",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Vehicle Log",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Fleet Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Fleet Manager",
+ "share": 1,
+ "submit": 1,
"write": 1
}
- ],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/hr/doctype/vehicle_log/vehicle_log.py b/erpnext/hr/doctype/vehicle_log/vehicle_log.py
index df63361..12cc1dd 100644
--- a/erpnext/hr/doctype/vehicle_log/vehicle_log.py
+++ b/erpnext/hr/doctype/vehicle_log/vehicle_log.py
@@ -11,22 +11,33 @@
class VehicleLog(Document):
def validate(self):
- last_odometer=frappe.db.get_value("Vehicle", self.license_plate, "last_odometer")
- if flt(self.odometer) < flt(last_odometer):
- frappe.throw(_("Current Odometer reading entered should be greater than initial Vehicle Odometer {0}").format(last_odometer))
+ if flt(self.odometer) < flt(self.last_odometer):
+ frappe.throw(_("Current Odometer reading entered should be greater than initial Vehicle Odometer {0}").format(self.last_odometer))
for service_detail in self.service_detail:
if (service_detail.service_item or service_detail.type or service_detail.frequency or service_detail.expense_amount):
if not (service_detail.service_item and service_detail.type and service_detail.frequency and service_detail.expense_amount):
frappe.throw(_("Service Item,Type,frequency and expense amount are required"))
+ def before_insert(self):
+ model_details = get_make_model(self.license_plate)
+ self.make = model_details[0]
+ self.model = model_details[1]
+ self.last_odometer = model_details[2]
+ self.employee = model_details[3]
+
def on_submit(self):
- frappe.db.sql("update `tabVehicle` set last_odometer=%s where license_plate=%s",
- (self.odometer, self.license_plate))
+ frappe.db.set_value("Vehicle", self.license_plate, "last_odometer", self.odometer)
+
+ def on_cancel(self):
+ distance_travelled = self.odometer - self.last_odometer
+ if(distance_travelled > 0):
+ updated_odometer_value = int(frappe.db.get_value("Vehicle", self.license_plate, "last_odometer")) - distance_travelled
+ frappe.db.set_value("Vehicle", self.license_plate, "last_odometer", updated_odometer_value)
@frappe.whitelist()
def get_make_model(license_plate):
vehicle=frappe.get_doc("Vehicle",license_plate)
- return (vehicle.make,vehicle.model)
+ return (vehicle.make, vehicle.model, vehicle.last_odometer, vehicle.employee)
@frappe.whitelist()
def make_expense_claim(docname):
diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py
index c3e8d27..ef27600 100644
--- a/erpnext/hr/utils.py
+++ b/erpnext/hr/utils.py
@@ -316,7 +316,9 @@
allocation = frappe.get_doc('Leave Allocation', allocation.name)
new_allocation = flt(allocation.total_leaves_allocated) + flt(earned_leaves)
- new_allocation = new_allocation if new_allocation <= e_leave_type.max_leaves_allowed else e_leave_type.max_leaves_allowed
+
+ if new_allocation > e_leave_type.max_leaves_allowed and e_leave_type.max_leaves_allowed > 0:
+ new_allocation = e_leave_type.max_leaves_allowed
if new_allocation == allocation.total_leaves_allocated:
continue
diff --git a/erpnext/public/js/conf.js b/erpnext/public/js/conf.js
index 0f88f13..615f6a4 100644
--- a/erpnext/public/js/conf.js
+++ b/erpnext/public/js/conf.js
@@ -29,19 +29,6 @@
});
-
-
-// doctypes created via tree
-$.extend(frappe.create_routes, {
- "Customer Group": "Tree/Customer Group",
- "Territory": "Tree/Territory",
- "Item Group": "Tree/Item Group",
- "Sales Person": "Tree/Sales Person",
- "Account": "Tree/Account",
- "Cost Center": "Tree/Cost Center",
- "Department": "Tree/Department",
-});
-
// preferred modules for breadcrumbs
$.extend(frappe.breadcrumbs.preferred, {
"Item Group": "Stock",
diff --git a/erpnext/regional/report/datev/datev.py b/erpnext/regional/report/datev/datev.py
index bd70639..7ceaf50 100644
--- a/erpnext/regional/report/datev/datev.py
+++ b/erpnext/regional/report/datev/datev.py
@@ -72,17 +72,16 @@
case gl.debit when 0 then 'H' else 'S' end as 'Soll/Haben-Kennzeichen',
/* account number or, if empty, party account number */
- coalesce(acc.account_number, acc_pa.account_number) as 'Kontonummer',
+ coalesce(acc.account_number, acc_pa.account_number) as 'Konto',
/* against number or, if empty, party against number */
coalesce(acc_against.account_number, acc_against_pa.account_number) as 'Gegenkonto (ohne BU-Schlüssel)',
gl.posting_date as 'Belegdatum',
+ gl.voucher_no as 'Belegfeld 1',
gl.remarks as 'Buchungstext',
- gl.voucher_type as 'Beleginfo - Art 1',
- gl.voucher_no as 'Beleginfo - Inhalt 1',
- gl.against_voucher_type as 'Beleginfo - Art 2',
- gl.against_voucher as 'Beleginfo - Inhalt 2'
+ gl.against_voucher_type as 'Beleginfo - Art 1',
+ gl.against_voucher as 'Beleginfo - Inhalt 1'
FROM `tabGL Entry` gl
@@ -240,8 +239,6 @@
filters -- dict
csv_class -- defines DATA_CATEGORY, FORMAT_NAME and COLUMNS
"""
- header = get_header(filters, csv_class)
-
empty_df = pd.DataFrame(columns=csv_class.COLUMNS)
data_df = pd.DataFrame.from_records(data)
@@ -253,7 +250,6 @@
if csv_class.DATA_CATEGORY == DataCategory.ACCOUNT_NAMES:
result['Sprach-ID'] = 'de-DE'
- header = ';'.join(header).encode('latin_1')
data = result.to_csv(
# Reason for str(';'): https://github.com/pandas-dev/pandas/issues/6035
sep=str(';'),
@@ -274,66 +270,91 @@
if not six.PY2:
data = data.encode('latin_1')
+ header = get_header(filters, csv_class)
+ header = ';'.join(header).encode('latin_1')
+
+ # 1st Row: Header with meta data
+ # 2nd Row: Data heading (Überschrift der Nutzdaten), included in `data` here.
+ # 3rd - nth Row: Data (Nutzdaten)
return header + b'\r\n' + data
def get_header(filters, csv_class):
+ coa = frappe.get_value("Company", filters.get("company"), "chart_of_accounts")
+ coa_used = "SKR04" if "SKR04" in coa else ("SKR03" if "SKR03" in coa else "")
+
header = [
- # A = DATEV format
- # DTVF = created by DATEV software,
- # EXTF = created by other software
- "EXTF",
- # B = version of the DATEV format
+ # DATEV format
+ # "DTVF" = created by DATEV software,
+ # "EXTF" = created by other software
+ '"EXTF"',
+ # version of the DATEV format
# 141 = 1.41,
# 510 = 5.10,
# 720 = 7.20
- "510",
+ '700',
csv_class.DATA_CATEGORY,
- csv_class.FORMAT_NAME,
- # E = Format version (regarding format name)
- "",
- # F = Generated on
- datetime.datetime.now().strftime("%Y%m%d"),
- # G = Imported on -- stays empty
- "",
- # H = Origin (SV = other (?), RE = KARE)
- "SV",
+ '"%s"' % csv_class.FORMAT_NAME,
+ # Format version (regarding format name)
+ csv_class.FORMAT_VERSION,
+ # Generated on
+ datetime.datetime.now().strftime("%Y%m%d%H%M%S"),
+ # Imported on -- stays empty
+ '',
+ # Origin. Any two symbols, will be replaced by "SV" on import.
+ '"EN"',
# I = Exported by
- frappe.session.user,
+ '"%s"' % frappe.session.user,
# J = Imported by -- stays empty
- "",
+ '',
# K = Tax consultant number (Beraternummer)
- frappe.get_value("DATEV Settings", filters.get("company"), "consultant_number") or "",
- "",
+ frappe.get_value("DATEV Settings", filters.get("company"), "consultant_number"),
# L = Tax client number (Mandantennummer)
- frappe.get_value("DATEV Settings", filters.get("company"), "client_number") or "",
- "",
+ frappe.get_value("DATEV Settings", filters.get("company"), "client_number"),
# M = Start of the fiscal year (Wirtschaftsjahresbeginn)
frappe.utils.formatdate(frappe.defaults.get_user_default("year_start_date"), "yyyyMMdd"),
# N = Length of account numbers (Sachkontenlänge)
- "4",
+ '4',
# O = Transaction batch start date (YYYYMMDD)
frappe.utils.formatdate(filters.get('from_date'), "yyyyMMdd"),
# P = Transaction batch end date (YYYYMMDD)
frappe.utils.formatdate(filters.get('to_date'), "yyyyMMdd"),
# Q = Description (for example, "January - February 2019 Transactions")
- "{} - {} {}".format(
+ '"{} - {} {}"'.format(
frappe.utils.formatdate(filters.get('from_date'), "MMMM yyyy"),
frappe.utils.formatdate(filters.get('to_date'), "MMMM yyyy"),
csv_class.FORMAT_NAME
),
# R = Diktatkürzel
- "",
+ '',
# S = Buchungstyp
- # 1 = Transaction batch (Buchungsstapel),
+ # 1 = Transaction batch (Finanzbuchführung),
# 2 = Annual financial statement (Jahresabschluss)
- "1" if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else "",
+ '1' if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
# T = Rechnungslegungszweck
- "",
+ '',
# U = Festschreibung
- "",
- # V = Kontoführungs-Währungskennzeichen des Geldkontos
- frappe.get_value("Company", filters.get("company"), "default_currency")
+ '',
+ # V = Default currency, for example, "EUR"
+ '"%s"' % frappe.get_value("Company", filters.get("company"), "default_currency"),
+ # reserviert
+ '',
+ # Derivatskennzeichen
+ '',
+ # reserviert
+ '',
+ # reserviert
+ '',
+ # SKR
+ '"%s"' % coa_used,
+ # Branchen-Lösungs-ID
+ '',
+ # reserviert
+ '',
+ # reserviert
+ '',
+ # Anwendungsinformation (Verarbeitungskennzeichen der abgebenden Anwendung)
+ ''
]
return header
diff --git a/erpnext/regional/report/datev/datev_constants.py b/erpnext/regional/report/datev/datev_constants.py
index 1c9bd23..a4cd5fc 100644
--- a/erpnext/regional/report/datev/datev_constants.py
+++ b/erpnext/regional/report/datev/datev_constants.py
@@ -13,24 +13,27 @@
"Basis-Umsatz",
"WKZ Basis-Umsatz",
# Konto/Gegenkonto
- "Kontonummer",
+ "Konto",
"Gegenkonto (ohne BU-Schlüssel)",
"BU-Schlüssel",
# Datum
"Belegdatum",
- # Belegfelder
+ # Rechnungs- / Belegnummer
"Belegfeld 1",
+ # z.B. Fälligkeitsdatum Format: TTMMJJ
"Belegfeld 2",
- # Weitere Felder
+ # Skonto-Betrag / -Abzug (Der Wert 0 ist unzulässig)
"Skonto",
+ # Beschreibung des Buchungssatzes
"Buchungstext",
- # OPOS-Informationen
+ # Mahn- / Zahl-Sperre (1 = Postensperre)
"Postensperre",
"Diverse Adressnummer",
"Geschäftspartnerbank",
"Sachverhalt",
+ # Keine Mahnzinsen
"Zinssperre",
- # Digitaler Beleg
+ # Link auf den Buchungsbeleg (Programmkürzel + GUID)
"Beleglink",
# Beleginfo
"Beleginfo - Art 1",
@@ -49,22 +52,30 @@
"Beleginfo - Inhalt 7",
"Beleginfo - Art 8",
"Beleginfo - Inhalt 8",
- # Kostenrechnung
- "Kost 1 - Kostenstelle",
- "Kost 2 - Kostenstelle",
- "Kost-Menge",
- # Steuerrechnung
- "EU-Land u. UStID",
+ # Zuordnung des Geschäftsvorfalls für die Kostenrechnung
+ "KOST1 - Kostenstelle",
+ "KOST2 - Kostenstelle",
+ "KOST-Menge",
+ # USt-ID-Nummer (Beispiel: DE133546770)
+ "EU-Mitgliedstaat u. USt-IdNr.",
+ # Der im EU-Bestimmungsland gültige Steuersatz
"EU-Steuersatz",
+ # I = Ist-Versteuerung,
+ # K = keine Umsatzsteuerrechnung
+ # P = Pauschalierung (z. B. für Land- und Forstwirtschaft),
+ # S = Soll-Versteuerung
"Abw. Versteuerungsart",
- # L+L Sachverhalt
+ # Sachverhalte gem. § 13b Abs. 1 Satz 1 Nrn. 1.-5. UStG
"Sachverhalt L+L",
+ # Steuersatz / Funktion zum L+L-Sachverhalt (Beispiel: Wert 190 für 19%)
"Funktionsergänzung L+L",
- # Funktion Steuerschlüssel 49
+ # Bei Verwendung des BU-Schlüssels 49 für „andere Steuersätze“ muss der
+ # steuerliche Sachverhalt mitgegeben werden
"BU 49 Hauptfunktionstyp",
"BU 49 Hauptfunktionsnummer",
"BU 49 Funktionsergänzung",
- # Zusatzinformationen
+ # Zusatzinformationen, besitzen den Charakter eines Notizzettels und können
+ # frei erfasst werden.
"Zusatzinformation - Art 1",
"Zusatzinformation - Inhalt 1",
"Zusatzinformation - Art 2",
@@ -105,54 +116,76 @@
"Zusatzinformation - Inhalt 19",
"Zusatzinformation - Art 20",
"Zusatzinformation - Inhalt 20",
- # Mengenfelder LuF
+ # Wirkt sich nur bei Sachverhalt mit SKR 14 Land- und Forstwirtschaft aus,
+ # für andere SKR werden die Felder beim Import / Export überlesen bzw.
+ # leer exportiert.
"Stück",
"Gewicht",
- # Forderungsart
+ # 1 = Lastschrift
+ # 2 = Mahnung
+ # 3 = Zahlung
"Zahlweise",
"Forderungsart",
+ # JJJJ
"Veranlagungsjahr",
+ # TTMMJJJJ
"Zugeordnete Fälligkeit",
- # Weitere Felder
+ # 1 = Einkauf von Waren
+ # 2 = Erwerb von Roh-Hilfs- und Betriebsstoffen
"Skontotyp",
- # Anzahlungen
+ # Allgemeine Bezeichnung, des Auftrags / Projekts.
"Auftragsnummer",
+ # AA = Angeforderte Anzahlung / Abschlagsrechnung
+ # AG = Erhaltene Anzahlung (Geldeingang)
+ # AV = Erhaltene Anzahlung (Verbindlichkeit)
+ # SR = Schlussrechnung
+ # SU = Schlussrechnung (Umbuchung)
+ # SG = Schlussrechnung (Geldeingang)
+ # SO = Sonstige
"Buchungstyp",
"USt-Schlüssel (Anzahlungen)",
- "EU-Land (Anzahlungen)",
+ "EU-Mitgliedstaat (Anzahlungen)",
"Sachverhalt L+L (Anzahlungen)",
"EU-Steuersatz (Anzahlungen)",
"Erlöskonto (Anzahlungen)",
- # Stapelinformationen
+ # Wird beim Import durch SV (Stapelverarbeitung) ersetzt.
"Herkunft-Kz",
- # Technische Identifikation
- "Buchungs GUID",
- # Kostenrechnung
- "Kost-Datum",
- # OPOS-Informationen
+ # Wird von DATEV verwendet.
+ "Leerfeld",
+ # Format TTMMJJJJ
+ "KOST-Datum",
+ # Vom Zahlungsempfänger individuell vergebenes Kennzeichen eines Mandats
+ # (z.B. Rechnungs- oder Kundennummer).
"SEPA-Mandatsreferenz",
+ # 1 = Skontosperre
+ # 0 = Keine Skontosperre
"Skontosperre",
# Gesellschafter und Sonderbilanzsachverhalt
"Gesellschaftername",
+ # Amtliche Nummer aus der Feststellungserklärung
"Beteiligtennummer",
"Identifikationsnummer",
"Zeichnernummer",
- # OPOS-Informationen
+ # Format TTMMJJJJ
"Postensperre bis",
# Gesellschafter und Sonderbilanzsachverhalt
"Bezeichnung SoBil-Sachverhalt",
"Kennzeichen SoBil-Buchung",
- # Stapelinformationen
+ # 0 = keine Festschreibung
+ # 1 = Festschreibung
"Festschreibung",
- # Datum
+ # Format TTMMJJJJ
"Leistungsdatum",
+ # Format TTMMJJJJ
"Datum Zuord. Steuerperiode",
- # OPOS-Informationen
+ # OPOS-Informationen, Format TTMMJJJJ
"Fälligkeit",
- # Konto/Gegenkonto
+ # G oder 1 = Generalumkehr
+ # 0 = keine Generalumkehr
"Generalumkehr (GU)",
# Steuersatz für Steuerschlüssel
"Steuersatz",
+ # Beispiel: DE für Deutschland
"Land"
]
@@ -439,8 +472,8 @@
"fieldtype": "Data",
},
{
- "label": "Kontonummer",
- "fieldname": "Kontonummer",
+ "label": "Konto",
+ "fieldname": "Konto",
"fieldtype": "Data",
},
{
@@ -454,27 +487,22 @@
"fieldtype": "Date",
},
{
+ "label": "Belegfeld 1",
+ "fieldname": "Belegfeld 1",
+ "fieldtype": "Data",
+ },
+ {
"label": "Buchungstext",
"fieldname": "Buchungstext",
"fieldtype": "Text",
},
{
"label": "Beleginfo - Art 1",
- "fieldname": "Beleginfo - Art 1",
- "fieldtype": "Data",
- },
- {
- "label": "Beleginfo - Inhalt 1",
- "fieldname": "Beleginfo - Inhalt 1",
- "fieldtype": "Data",
- },
- {
- "label": "Beleginfo - Art 2",
"fieldname": "Beleginfo - Art 2",
"fieldtype": "Data",
},
{
- "label": "Beleginfo - Inhalt 2",
+ "label": "Beleginfo - Inhalt 1",
"fieldname": "Beleginfo - Inhalt 2",
"fieldtype": "Data",
}
@@ -499,14 +527,17 @@
class Transactions():
DATA_CATEGORY = DataCategory.TRANSACTIONS
FORMAT_NAME = FormatName.TRANSACTIONS
+ FORMAT_VERSION = "9"
COLUMNS = TRANSACTION_COLUMNS
class DebtorsCreditors():
DATA_CATEGORY = DataCategory.DEBTORS_CREDITORS
FORMAT_NAME = FormatName.DEBTORS_CREDITORS
+ FORMAT_VERSION = "5"
COLUMNS = DEBTOR_CREDITOR_COLUMNS
class AccountNames():
DATA_CATEGORY = DataCategory.ACCOUNT_NAMES
FORMAT_NAME = FormatName.ACCOUNT_NAMES
+ FORMAT_VERSION = "2"
COLUMNS = ACCOUNT_NAME_COLUMNS
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index 7f2fe60..9261289 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -213,6 +213,9 @@
def create_onboarding_docs(self, args):
defaults = frappe.defaults.get_defaults()
+ company = defaults.get('company') or \
+ frappe.db.get_single_value('Global Defaults', 'default_company')
+
for i in range(1, args.get('max_count')):
customer = args.get('customer_name_' + str(i))
if customer:
@@ -223,7 +226,7 @@
'customer_type': 'Company',
'customer_group': _('Commercial'),
'territory': defaults.get('country'),
- 'company': defaults.get('company')
+ 'company': company
}).insert()
if args.get('customer_email_' + str(i)):
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index d036a0a..a2a913a 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -877,14 +877,16 @@
frappe.msgprint(msg=_("You have to enable auto re-order in Stock Settings to maintain re-order levels."), title=_("Enable Auto Re-Order"), indicator="orange")
def create_onboarding_docs(self, args):
- defaults = frappe.defaults.get_defaults()
+ company = frappe.defaults.get_defaults().get('company') or \
+ frappe.db.get_single_value('Global Defaults', 'default_company')
+
for i in range(1, args.get('max_count')):
item = args.get('item_' + str(i))
if item:
default_warehouse = ''
default_warehouse = frappe.db.get_value('Warehouse', filters={
'warehouse_name': _('Finished Goods'),
- 'company': defaults.get('company_name')
+ 'company': company
})
try:
@@ -901,7 +903,7 @@
'stock_uom': _(args.get('item_uom_' + str(i))),
'item_defaults': [{
'default_warehouse': default_warehouse,
- 'company': defaults.get('company_name')
+ 'company': company
}]
}).insert()
@@ -909,7 +911,7 @@
pass
else:
if args.get('item_price_' + str(i)):
- item_price = flt(args.get('tem_price_' + str(i)))
+ item_price = flt(args.get('item_price_' + str(i)))
price_list_name = frappe.db.get_value('Price List', {'selling': 1})
make_item_price(item, price_list_name, item_price)
diff --git a/erpnext/support/doctype/issue/issue.json b/erpnext/support/doctype/issue/issue.json
index 222554b..53af80c 100644
--- a/erpnext/support/doctype/issue/issue.json
+++ b/erpnext/support/doctype/issue/issue.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "naming_series:",
@@ -119,6 +120,7 @@
"default": "Medium",
"fieldname": "priority",
"fieldtype": "Link",
+ "in_list_view": 1,
"in_standard_filter": 1,
"label": "Priority",
"options": "Issue Priority"
@@ -363,8 +365,9 @@
],
"icon": "fa fa-ticket",
"idx": 7,
- "modified": "2019-09-11 09:03:57.465623",
- "modified_by": "himanshu@erpnext.com",
+ "links": [],
+ "modified": "2020-02-18 21:26:35.636013",
+ "modified_by": "Administrator",
"module": "Support",
"name": "Issue",
"owner": "Administrator",
diff --git a/erpnext/templates/includes/projects/project_row.html b/erpnext/templates/includes/projects/project_row.html
index 55b02e2..73c83ef 100644
--- a/erpnext/templates/includes/projects/project_row.html
+++ b/erpnext/templates/includes/projects/project_row.html
@@ -1,6 +1,6 @@
{% if doc.status=="Open" %}
<div class="web-list-item">
- <a class="no-decoration" href="/projects?project={{ doc.name }}">
+ <a class="no-decoration" href="/projects?project={{ doc.name | urlencode }}">
<div class="row">
<div class="col-xs-6">
diff --git a/erpnext/utilities/product.py b/erpnext/utilities/product.py
index 1c0d4c3..c23c1f7 100644
--- a/erpnext/utilities/product.py
+++ b/erpnext/utilities/product.py
@@ -129,6 +129,7 @@
#if item belongs to product bundle, check if bundle items are in stock
if frappe.db.exists("Product Bundle", item_code):
items = frappe.get_doc("Product Bundle", item_code).get_all_children()
- return all([ get_qty_in_stock(d.item_code, item_warehouse_field).in_stock for d in items ])
+ bundle_warehouse = frappe.db.get_value('Item', item_code, item_warehouse_field)
+ return all([ get_qty_in_stock(d.item_code, item_warehouse_field, bundle_warehouse).in_stock for d in items ])
else:
return 1