Merge branch 'develop' of https://github.com/frappe/erpnext into loan_top_up_fixes
This commit is contained in:
commit
a2249e013d
@ -302,10 +302,10 @@
|
|||||||
"fieldname": "warehouse",
|
"fieldname": "warehouse",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Warehouse",
|
"label": "Warehouse",
|
||||||
|
"mandatory_depends_on": "update_stock",
|
||||||
"oldfieldname": "warehouse",
|
"oldfieldname": "warehouse",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "Warehouse",
|
"options": "Warehouse"
|
||||||
"reqd": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
|
|||||||
@ -1621,6 +1621,7 @@ def update_multi_mode_option(doc, pos_profile):
|
|||||||
pos_payment_method = pos_payment_method.as_dict()
|
pos_payment_method = pos_payment_method.as_dict()
|
||||||
|
|
||||||
payment_mode = get_mode_of_payment_info(pos_payment_method.mode_of_payment, doc.company)
|
payment_mode = get_mode_of_payment_info(pos_payment_method.mode_of_payment, doc.company)
|
||||||
|
if payment_mode:
|
||||||
payment_mode[0].default = pos_payment_method.default
|
payment_mode[0].default = pos_payment_method.default
|
||||||
append_payment(payment_mode[0])
|
append_payment(payment_mode[0])
|
||||||
|
|
||||||
|
|||||||
@ -206,10 +206,19 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
"rate": 14,
|
"rate": 14,
|
||||||
'included_in_print_rate': 1
|
'included_in_print_rate': 1
|
||||||
})
|
})
|
||||||
|
si.append("taxes", {
|
||||||
|
"charge_type": "On Item Quantity",
|
||||||
|
"account_head": "_Test Account Education Cess - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "CESS",
|
||||||
|
"rate": 5,
|
||||||
|
'included_in_print_rate': 1
|
||||||
|
})
|
||||||
si.insert()
|
si.insert()
|
||||||
|
|
||||||
# with inclusive tax
|
# with inclusive tax
|
||||||
self.assertEqual(si.net_total, 4385.96)
|
self.assertEqual(si.items[0].net_amount, 3947.368421052631)
|
||||||
|
self.assertEqual(si.net_total, 3947.37)
|
||||||
self.assertEqual(si.grand_total, 5000)
|
self.assertEqual(si.grand_total, 5000)
|
||||||
|
|
||||||
si.reload()
|
si.reload()
|
||||||
@ -222,8 +231,8 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
si.save()
|
si.save()
|
||||||
|
|
||||||
# with inclusive tax and additional discount
|
# with inclusive tax and additional discount
|
||||||
self.assertEqual(si.net_total, 4285.96)
|
self.assertEqual(si.net_total, 3847.37)
|
||||||
self.assertEqual(si.grand_total, 4885.99)
|
self.assertEqual(si.grand_total, 4886)
|
||||||
|
|
||||||
si.reload()
|
si.reload()
|
||||||
|
|
||||||
@ -235,7 +244,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
si.save()
|
si.save()
|
||||||
|
|
||||||
# with inclusive tax and additional discount
|
# with inclusive tax and additional discount
|
||||||
self.assertEqual(si.net_total, 4298.25)
|
self.assertEqual(si.net_total, 3859.65)
|
||||||
self.assertEqual(si.grand_total, 4900.00)
|
self.assertEqual(si.grand_total, 4900.00)
|
||||||
|
|
||||||
def test_sales_invoice_discount_amount(self):
|
def test_sales_invoice_discount_amount(self):
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from erpnext.assets.doctype.asset_maintenance.asset_maintenance import calculate
|
|||||||
|
|
||||||
class AssetMaintenanceLog(Document):
|
class AssetMaintenanceLog(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if getdate(self.due_date) < getdate(nowdate()):
|
if getdate(self.due_date) < getdate(nowdate()) and self.maintenance_status not in ["Completed", "Cancelled"]:
|
||||||
self.maintenance_status = "Overdue"
|
self.maintenance_status = "Overdue"
|
||||||
|
|
||||||
if self.maintenance_status == "Completed" and not self.completion_date:
|
if self.maintenance_status == "Completed" and not self.completion_date:
|
||||||
|
|||||||
@ -1,14 +1,15 @@
|
|||||||
frappe.listview_settings['Asset Maintenance Log'] = {
|
frappe.listview_settings['Asset Maintenance Log'] = {
|
||||||
add_fields: ["maintenance_status"],
|
add_fields: ["maintenance_status"],
|
||||||
|
has_indicator_for_draft: 1,
|
||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
if(doc.maintenance_status=="Pending") {
|
if (doc.maintenance_status=="Planned") {
|
||||||
return [__("Pending"), "orange"];
|
return [__(doc.maintenance_status), "orange", "status,=," + doc.maintenance_status];
|
||||||
} else if (doc.maintenance_status=="Completed") {
|
} else if (doc.maintenance_status=="Completed") {
|
||||||
return [__("Completed"), "green"];
|
return [__(doc.maintenance_status), "green", "status,=," + doc.maintenance_status];
|
||||||
} else if (doc.maintenance_status=="Cancelled") {
|
} else if (doc.maintenance_status=="Cancelled") {
|
||||||
return [__("Cancelled"), "red"];
|
return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status];
|
||||||
} else if (doc.maintenance_status=="Overdue") {
|
} else if (doc.maintenance_status=="Overdue") {
|
||||||
return [__("Overdue"), "red"];
|
return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -94,7 +94,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
|||||||
if(this.frm.doc.status !== 'Closed' && flt(this.frm.doc.per_received) < 100 && flt(this.frm.doc.per_billed) < 100) {
|
if(this.frm.doc.status !== 'Closed' && flt(this.frm.doc.per_received) < 100 && flt(this.frm.doc.per_billed) < 100) {
|
||||||
this.frm.add_custom_button(__('Update Items'), () => {
|
this.frm.add_custom_button(__('Update Items'), () => {
|
||||||
erpnext.utils.update_child_items({
|
erpnext.utils.update_child_items({
|
||||||
frm: frm,
|
frm: this.frm,
|
||||||
child_docname: "items",
|
child_docname: "items",
|
||||||
child_doctype: "Purchase Order Detail",
|
child_doctype: "Purchase Order Detail",
|
||||||
cannot_add_row: false,
|
cannot_add_row: false,
|
||||||
|
|||||||
@ -985,7 +985,7 @@ def validate_inclusive_tax(tax, doc):
|
|||||||
# all rows about the reffered tax should be inclusive
|
# all rows about the reffered tax should be inclusive
|
||||||
_on_previous_row_error("1 - %d" % (tax.row_id,))
|
_on_previous_row_error("1 - %d" % (tax.row_id,))
|
||||||
elif tax.get("category") == "Valuation":
|
elif tax.get("category") == "Valuation":
|
||||||
frappe.throw(_("Valuation type charges can not marked as Inclusive"))
|
frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
|
||||||
|
|
||||||
|
|
||||||
def set_balance_in_account_currency(gl_dict, account_currency=None, conversion_rate=None, company_currency=None):
|
def set_balance_in_account_currency(gl_dict, account_currency=None, conversion_rate=None, company_currency=None):
|
||||||
|
|||||||
@ -161,8 +161,9 @@ class calculate_taxes_and_totals(object):
|
|||||||
for item in self.doc.get("items"):
|
for item in self.doc.get("items"):
|
||||||
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
|
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
|
||||||
cumulated_tax_fraction = 0
|
cumulated_tax_fraction = 0
|
||||||
|
total_inclusive_tax_amount_per_qty = 0
|
||||||
for i, tax in enumerate(self.doc.get("taxes")):
|
for i, tax in enumerate(self.doc.get("taxes")):
|
||||||
tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax, item_tax_map)
|
tax.tax_fraction_for_current_item, inclusive_tax_amount_per_qty = self.get_current_tax_fraction(tax, item_tax_map)
|
||||||
|
|
||||||
if i==0:
|
if i==0:
|
||||||
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item
|
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item
|
||||||
@ -172,9 +173,12 @@ class calculate_taxes_and_totals(object):
|
|||||||
+ tax.tax_fraction_for_current_item
|
+ tax.tax_fraction_for_current_item
|
||||||
|
|
||||||
cumulated_tax_fraction += tax.tax_fraction_for_current_item
|
cumulated_tax_fraction += tax.tax_fraction_for_current_item
|
||||||
|
total_inclusive_tax_amount_per_qty += inclusive_tax_amount_per_qty * flt(item.qty)
|
||||||
|
|
||||||
if cumulated_tax_fraction and not self.discount_amount_applied and item.qty:
|
if not self.discount_amount_applied and item.qty and (cumulated_tax_fraction or total_inclusive_tax_amount_per_qty):
|
||||||
item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction))
|
amount = flt(item.amount) - total_inclusive_tax_amount_per_qty
|
||||||
|
|
||||||
|
item.net_amount = flt(amount / (1 + cumulated_tax_fraction))
|
||||||
item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate"))
|
item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate"))
|
||||||
item.discount_percentage = flt(item.discount_percentage,
|
item.discount_percentage = flt(item.discount_percentage,
|
||||||
item.precision("discount_percentage"))
|
item.precision("discount_percentage"))
|
||||||
@ -190,6 +194,7 @@ class calculate_taxes_and_totals(object):
|
|||||||
from tax inclusive amount
|
from tax inclusive amount
|
||||||
"""
|
"""
|
||||||
current_tax_fraction = 0
|
current_tax_fraction = 0
|
||||||
|
inclusive_tax_amount_per_qty = 0
|
||||||
|
|
||||||
if cint(tax.included_in_print_rate):
|
if cint(tax.included_in_print_rate):
|
||||||
tax_rate = self._get_tax_rate(tax, item_tax_map)
|
tax_rate = self._get_tax_rate(tax, item_tax_map)
|
||||||
@ -205,9 +210,14 @@ class calculate_taxes_and_totals(object):
|
|||||||
current_tax_fraction = (tax_rate / 100.0) * \
|
current_tax_fraction = (tax_rate / 100.0) * \
|
||||||
self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
|
self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
|
||||||
|
|
||||||
if getattr(tax, "add_deduct_tax", None):
|
elif tax.charge_type == "On Item Quantity":
|
||||||
current_tax_fraction *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
|
inclusive_tax_amount_per_qty = flt(tax_rate)
|
||||||
return current_tax_fraction
|
|
||||||
|
if getattr(tax, "add_deduct_tax", None) and tax.add_deduct_tax == "Deduct":
|
||||||
|
current_tax_fraction *= -1.0
|
||||||
|
inclusive_tax_amount_per_qty *= -1.0
|
||||||
|
|
||||||
|
return current_tax_fraction, inclusive_tax_amount_per_qty
|
||||||
|
|
||||||
def _get_tax_rate(self, tax, item_tax_map):
|
def _get_tax_rate(self, tax, item_tax_map):
|
||||||
if tax.account_head in item_tax_map:
|
if tax.account_head in item_tax_map:
|
||||||
@ -321,7 +331,7 @@ class calculate_taxes_and_totals(object):
|
|||||||
current_tax_amount = (tax_rate / 100.0) * \
|
current_tax_amount = (tax_rate / 100.0) * \
|
||||||
self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_for_current_item
|
self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_for_current_item
|
||||||
elif tax.charge_type == "On Item Quantity":
|
elif tax.charge_type == "On Item Quantity":
|
||||||
current_tax_amount = tax_rate * item.stock_qty
|
current_tax_amount = tax_rate * item.qty
|
||||||
|
|
||||||
self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount)
|
self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount)
|
||||||
|
|
||||||
@ -472,7 +482,7 @@ class calculate_taxes_and_totals(object):
|
|||||||
actual_taxes_dict = {}
|
actual_taxes_dict = {}
|
||||||
|
|
||||||
for tax in self.doc.get("taxes"):
|
for tax in self.doc.get("taxes"):
|
||||||
if tax.charge_type == "Actual":
|
if tax.charge_type in ["Actual", "On Item Quantity"]:
|
||||||
tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(tax.tax_amount, tax)
|
tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(tax.tax_amount, tax)
|
||||||
actual_taxes_dict.setdefault(tax.idx, tax_amount)
|
actual_taxes_dict.setdefault(tax.idx, tax_amount)
|
||||||
elif tax.row_id in actual_taxes_dict:
|
elif tax.row_id in actual_taxes_dict:
|
||||||
|
|||||||
@ -50,9 +50,9 @@
|
|||||||
"contact_email",
|
"contact_email",
|
||||||
"contact_mobile",
|
"contact_mobile",
|
||||||
"more_info",
|
"more_info",
|
||||||
|
"company",
|
||||||
"campaign",
|
"campaign",
|
||||||
"column_break1",
|
"column_break1",
|
||||||
"company",
|
|
||||||
"transaction_date",
|
"transaction_date",
|
||||||
"amended_from",
|
"amended_from",
|
||||||
"lost_reasons"
|
"lost_reasons"
|
||||||
@ -344,7 +344,7 @@
|
|||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"fieldname": "more_info",
|
"fieldname": "more_info",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Source",
|
"label": "More Information",
|
||||||
"oldfieldtype": "Section Break",
|
"oldfieldtype": "Section Break",
|
||||||
"options": "fa fa-file-text"
|
"options": "fa fa-file-text"
|
||||||
},
|
},
|
||||||
@ -411,7 +411,7 @@
|
|||||||
"fieldname": "lost_reasons",
|
"fieldname": "lost_reasons",
|
||||||
"fieldtype": "Table MultiSelect",
|
"fieldtype": "Table MultiSelect",
|
||||||
"label": "Lost Reasons",
|
"label": "Lost Reasons",
|
||||||
"options": "Lost Reason Detail",
|
"options": "Opportunity Lost Reason Detail",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -424,7 +424,7 @@
|
|||||||
"icon": "fa fa-info-sign",
|
"icon": "fa fa-info-sign",
|
||||||
"idx": 195,
|
"idx": 195,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-08-11 14:49:13.496297",
|
"modified": "2020-08-11 17:34:35.066961",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "CRM",
|
"module": "CRM",
|
||||||
"name": "Opportunity",
|
"name": "Opportunity",
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"creation": "2020-07-16 16:11:39.830389",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"lost_reason"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "lost_reason",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Opportunity Lost Reason",
|
||||||
|
"options": "Opportunity Lost Reason"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"istable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2020-07-26 17:58:26.313242",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "CRM",
|
||||||
|
"name": "Opportunity Lost Reason Detail",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"quick_entry": 1,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 1
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
# import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class OpportunityLostReasonDetail(Document):
|
||||||
|
pass
|
||||||
@ -78,7 +78,7 @@
|
|||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"label": "HR",
|
"label": "HR",
|
||||||
"modified": "2020-06-16 19:20:50.976045",
|
"modified": "2020-08-11 17:04:38.655417",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "HR",
|
"name": "HR",
|
||||||
@ -88,7 +88,7 @@
|
|||||||
"pin_to_top": 0,
|
"pin_to_top": 0,
|
||||||
"shortcuts": [
|
"shortcuts": [
|
||||||
{
|
{
|
||||||
"color": "#9deca2",
|
"color": "#cef6d1",
|
||||||
"format": "{} Active",
|
"format": "{} Active",
|
||||||
"label": "Employee",
|
"label": "Employee",
|
||||||
"link_to": "Employee",
|
"link_to": "Employee",
|
||||||
@ -96,18 +96,19 @@
|
|||||||
"type": "DocType"
|
"type": "DocType"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Attendance",
|
"color": "#ffe8cd",
|
||||||
"link_to": "Attendance",
|
|
||||||
"stats_filter": "",
|
|
||||||
"type": "DocType"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"format": "{} Open",
|
"format": "{} Open",
|
||||||
"label": "Leave Application",
|
"label": "Leave Application",
|
||||||
"link_to": "Leave Application",
|
"link_to": "Leave Application",
|
||||||
"stats_filter": "{\"status\":\"Open\"}",
|
"stats_filter": "{\"status\":\"Open\"}",
|
||||||
"type": "DocType"
|
"type": "DocType"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "Attendance",
|
||||||
|
"link_to": "Attendance",
|
||||||
|
"stats_filter": "",
|
||||||
|
"type": "DocType"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "Job Applicant",
|
"label": "Job Applicant",
|
||||||
"link_to": "Job Applicant",
|
"link_to": "Job Applicant",
|
||||||
|
|||||||
@ -5,20 +5,23 @@ cur_frm.add_fetch('employee','employee_name','employee_name');
|
|||||||
|
|
||||||
frappe.ui.form.on("Leave Allocation", {
|
frappe.ui.form.on("Leave Allocation", {
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
|
// Ignore cancellation of doctype on cancel all.
|
||||||
|
frm.ignore_doctypes_on_cancel_all = ["Leave Ledger Entry"];
|
||||||
|
|
||||||
if(!frm.doc.from_date) frm.set_value("from_date", frappe.datetime.get_today());
|
if(!frm.doc.from_date) frm.set_value("from_date", frappe.datetime.get_today());
|
||||||
|
|
||||||
frm.set_query("employee", function() {
|
frm.set_query("employee", function() {
|
||||||
return {
|
return {
|
||||||
query: "erpnext.controllers.queries.employee_query"
|
query: "erpnext.controllers.queries.employee_query"
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
frm.set_query("leave_type", function() {
|
frm.set_query("leave_type", function() {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
is_lwp: 0
|
is_lwp: 0
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
|
|||||||
@ -19,6 +19,10 @@ frappe.ui.form.on("Leave Application", {
|
|||||||
frm.set_query("employee", erpnext.queries.employee);
|
frm.set_query("employee", erpnext.queries.employee);
|
||||||
},
|
},
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
|
|
||||||
|
// Ignore cancellation of doctype on cancel all.
|
||||||
|
frm.ignore_doctypes_on_cancel_all = ["Leave Ledger Entry"];
|
||||||
|
|
||||||
if (!frm.doc.posting_date) {
|
if (!frm.doc.posting_date) {
|
||||||
frm.set_value("posting_date", frappe.datetime.get_today());
|
frm.set_value("posting_date", frappe.datetime.get_today());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,10 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Leave Encashment', {
|
frappe.ui.form.on('Leave Encashment', {
|
||||||
|
onload: function(frm) {
|
||||||
|
// Ignore cancellation of doctype on cancel all.
|
||||||
|
frm.ignore_doctypes_on_cancel_all = ["Leave Ledger Entry"];
|
||||||
|
},
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frm.set_query("leave_type", function() {
|
frm.set_query("leave_type", function() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -16,14 +16,16 @@ from six import string_types
|
|||||||
|
|
||||||
class LoanApplication(Document):
|
class LoanApplication(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
self.set_pledge_amount()
|
||||||
|
self.set_loan_amount()
|
||||||
|
self.validate_loan_amount()
|
||||||
|
|
||||||
|
if self.is_term_loan:
|
||||||
validate_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount,
|
validate_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount,
|
||||||
self.repayment_periods, self.is_term_loan)
|
self.repayment_periods, self.is_term_loan)
|
||||||
|
|
||||||
self.validate_loan_type()
|
self.validate_loan_type()
|
||||||
self.set_pledge_amount()
|
|
||||||
self.set_loan_amount()
|
|
||||||
self.validate_loan_amount()
|
|
||||||
self.get_repayment_details()
|
self.get_repayment_details()
|
||||||
self.check_sanctioned_amount_limit()
|
self.check_sanctioned_amount_limit()
|
||||||
|
|
||||||
@ -106,7 +108,7 @@ class LoanApplication(Document):
|
|||||||
if self.is_secured_loan and self.proposed_pledges:
|
if self.is_secured_loan and self.proposed_pledges:
|
||||||
self.maximum_loan_amount = 0
|
self.maximum_loan_amount = 0
|
||||||
for security in self.proposed_pledges:
|
for security in self.proposed_pledges:
|
||||||
self.maximum_loan_amount += security.post_haircut_amount
|
self.maximum_loan_amount += flt(security.post_haircut_amount)
|
||||||
|
|
||||||
if not self.loan_amount and self.is_secured_loan and self.proposed_pledges:
|
if not self.loan_amount and self.is_secured_loan and self.proposed_pledges:
|
||||||
self.loan_amount = self.maximum_loan_amount
|
self.loan_amount = self.maximum_loan_amount
|
||||||
|
|||||||
@ -718,3 +718,6 @@ erpnext.patches.v13_0.delete_report_requested_items_to_order
|
|||||||
erpnext.patches.v12_0.update_item_tax_template_company
|
erpnext.patches.v12_0.update_item_tax_template_company
|
||||||
erpnext.patches.v13_0.move_branch_code_to_bank_account
|
erpnext.patches.v13_0.move_branch_code_to_bank_account
|
||||||
erpnext.patches.v13_0.healthcare_lab_module_rename_doctypes
|
erpnext.patches.v13_0.healthcare_lab_module_rename_doctypes
|
||||||
|
erpnext.patches.v13_0.stock_entry_enhancements
|
||||||
|
erpnext.patches.v12_0.update_state_code_for_daman_and_diu
|
||||||
|
erpnext.patches.v12_0.rename_lost_reason_detail
|
||||||
|
|||||||
17
erpnext/patches/v12_0/rename_lost_reason_detail.py
Normal file
17
erpnext/patches/v12_0/rename_lost_reason_detail.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
if frappe.db.exists("DocType", "Lost Reason Detail"):
|
||||||
|
frappe.reload_doc("crm", "doctype", "opportunity_lost_reason_detail")
|
||||||
|
frappe.reload_doc("setup", "doctype", "quotation_lost_reason_detail")
|
||||||
|
|
||||||
|
frappe.db.sql("""INSERT INTO `tabOpportunity Lost Reason Detail` SELECT * FROM `tabLost Reason Detail` WHERE `parenttype` = 'Opportunity'""")
|
||||||
|
|
||||||
|
frappe.db.sql("""INSERT INTO `tabQuotation Lost Reason Detail` SELECT * FROM `tabLost Reason Detail` WHERE `parenttype` = 'Quotation'""")
|
||||||
|
|
||||||
|
frappe.db.sql("""INSERT INTO `tabQuotation Lost Reason` (`name`, `creation`, `modified`, `modified_by`, `owner`, `docstatus`, `parent`, `parentfield`, `parenttype`, `idx`, `_comments`, `_assign`, `_user_tags`, `_liked_by`, `order_lost_reason`)
|
||||||
|
SELECT o.`name`, o.`creation`, o.`modified`, o.`modified_by`, o.`owner`, o.`docstatus`, o.`parent`, o.`parentfield`, o.`parenttype`, o.`idx`, o.`_comments`, o.`_assign`, o.`_user_tags`, o.`_liked_by`, o.`lost_reason`
|
||||||
|
FROM `tabOpportunity Lost Reason` o LEFT JOIN `tabQuotation Lost Reason` q ON q.name = o.name WHERE q.name IS NULL""")
|
||||||
|
|
||||||
|
frappe.delete_doc("DocType", "Lost Reason Detail")
|
||||||
@ -19,7 +19,7 @@ def create_stock_entry_types():
|
|||||||
|
|
||||||
for purpose in ["Material Issue", "Material Receipt", "Material Transfer",
|
for purpose in ["Material Issue", "Material Receipt", "Material Transfer",
|
||||||
"Material Transfer for Manufacture", "Material Consumption for Manufacture", "Manufacture",
|
"Material Transfer for Manufacture", "Material Consumption for Manufacture", "Manufacture",
|
||||||
"Repack", "Send to Subcontractor", "Send to Warehouse", "Receive at Warehouse"]:
|
"Repack", "Send to Subcontractor"]:
|
||||||
|
|
||||||
ste_type = frappe.get_doc({
|
ste_type = frappe.get_doc({
|
||||||
'doctype': 'Stock Entry Type',
|
'doctype': 'Stock Entry Type',
|
||||||
|
|||||||
22
erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py
Normal file
22
erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import frappe
|
||||||
|
from erpnext.regional.india import states
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
|
||||||
|
company = frappe.get_all('Company', filters = {'country': 'India'})
|
||||||
|
if not company:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Update options in gst_state custom field
|
||||||
|
gst_state = frappe.get_doc('Custom Field', 'Address-gst_state')
|
||||||
|
gst_state.options = '\n'.join(states)
|
||||||
|
gst_state.save()
|
||||||
|
|
||||||
|
# Update gst_state and state code in existing address
|
||||||
|
frappe.db.sql("""
|
||||||
|
UPDATE `tabAddress`
|
||||||
|
SET
|
||||||
|
gst_state = 'Dadra and Nagar Haveli and Daman and Diu',
|
||||||
|
gst_state_number = 26
|
||||||
|
WHERE gst_state = 'Daman and Diu'
|
||||||
|
""")
|
||||||
27
erpnext/patches/v13_0/stock_entry_enhancements.py
Normal file
27
erpnext/patches/v13_0/stock_entry_enhancements.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Copyright(c) 2020, Frappe Technologies Pvt.Ltd.and Contributors
|
||||||
|
# License: GNU General Public License v3.See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc("stock", "doctype", "stock_entry")
|
||||||
|
if frappe.db.has_column("Stock Entry", "add_to_transit"):
|
||||||
|
frappe.db.sql("""
|
||||||
|
UPDATE `tabStock Entry` SET
|
||||||
|
stock_entry_type = 'Material Transfer',
|
||||||
|
purpose = 'Material Transfer',
|
||||||
|
add_to_transit = 1 WHERE stock_entry_type = 'Send to Warehouse'
|
||||||
|
""")
|
||||||
|
|
||||||
|
frappe.db.sql("""UPDATE `tabStock Entry` SET
|
||||||
|
stock_entry_type = 'Material Transfer',
|
||||||
|
purpose = 'Material Transfer'
|
||||||
|
WHERE stock_entry_type = 'Receive at Warehouse'
|
||||||
|
""")
|
||||||
|
|
||||||
|
frappe.reload_doc("stock", "doctype", "warehouse_type")
|
||||||
|
if not frappe.db.exists('Warehouse Type', 'Transit'):
|
||||||
|
doc = frappe.new_doc('Warehouse Type')
|
||||||
|
doc.name = 'Transit'
|
||||||
|
doc.insert()
|
||||||
@ -8,7 +8,7 @@
|
|||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"label": "Taxation",
|
"label": "Taxation",
|
||||||
"links": "[\n {\n \"label\": \"Payroll Period\",\n \"name\": \"Payroll Period\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Income Tax Slab\",\n \"name\": \"Income Tax Slab\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Declaration\",\n \"name\": \"Employee Tax Exemption Declaration\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Proof Submission\",\n \"name\": \"Employee Tax Exemption Proof Submission\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Category\",\n \"name\": \"Employee Tax Exemption Category\",\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Sub Category\",\n \"name\": \"Employee Tax Exemption Sub Category\",\n \"type\": \"doctype\"\n \n }\n]"
|
"links": "[\n {\n \"label\": \"Payroll Period\",\n \"name\": \"Payroll Period\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Income Tax Slab\",\n \"name\": \"Income Tax Slab\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Other Income\",\n \"name\": \"Employee Other Income\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Declaration\",\n \"name\": \"Employee Tax Exemption Declaration\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Proof Submission\",\n \"name\": \"Employee Tax Exemption Proof Submission\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Category\",\n \"name\": \"Employee Tax Exemption Category\",\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Sub Category\",\n \"name\": \"Employee Tax Exemption Sub Category\",\n \"type\": \"doctype\"\n \n }\n]"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -38,7 +38,7 @@
|
|||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"label": "Payroll",
|
"label": "Payroll",
|
||||||
"modified": "2020-06-19 12:23:06.034046",
|
"modified": "2020-08-10 19:38:45.976209",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Payroll",
|
"module": "Payroll",
|
||||||
"name": "Payroll",
|
"name": "Payroll",
|
||||||
|
|||||||
@ -94,13 +94,6 @@ frappe.ui.form.on("Timesheet", {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
company: function(frm) {
|
|
||||||
frappe.db.get_value('Company', { 'company_name' : frm.doc.company }, 'standard_working_hours')
|
|
||||||
.then(({ message }) => {
|
|
||||||
(frappe.working_hours = message.standard_working_hours || 0);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
make_invoice: function(frm) {
|
make_invoice: function(frm) {
|
||||||
let dialog = new frappe.ui.Dialog({
|
let dialog = new frappe.ui.Dialog({
|
||||||
title: __("Select Item (optional)"),
|
title: __("Select Item (optional)"),
|
||||||
|
|||||||
@ -163,9 +163,11 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
$.each(me.frm.doc["items"] || [], function(n, item) {
|
$.each(me.frm.doc["items"] || [], function(n, item) {
|
||||||
var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
|
var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
|
||||||
var cumulated_tax_fraction = 0.0;
|
var cumulated_tax_fraction = 0.0;
|
||||||
|
var total_inclusive_tax_amount_per_qty = 0;
|
||||||
$.each(me.frm.doc["taxes"] || [], function(i, tax) {
|
$.each(me.frm.doc["taxes"] || [], function(i, tax) {
|
||||||
tax.tax_fraction_for_current_item = me.get_current_tax_fraction(tax, item_tax_map);
|
var current_tax_fraction = me.get_current_tax_fraction(tax, item_tax_map);
|
||||||
|
tax.tax_fraction_for_current_item = current_tax_fraction[0];
|
||||||
|
var inclusive_tax_amount_per_qty = current_tax_fraction[1];
|
||||||
|
|
||||||
if(i==0) {
|
if(i==0) {
|
||||||
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item;
|
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item;
|
||||||
@ -176,10 +178,12 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
cumulated_tax_fraction += tax.tax_fraction_for_current_item;
|
cumulated_tax_fraction += tax.tax_fraction_for_current_item;
|
||||||
|
total_inclusive_tax_amount_per_qty += inclusive_tax_amount_per_qty * flt(item.qty);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(cumulated_tax_fraction && !me.discount_amount_applied) {
|
if(!me.discount_amount_applied && item.qty && (total_inclusive_tax_amount_per_qty || cumulated_tax_fraction)) {
|
||||||
item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction));
|
var amount = flt(item.amount) - total_inclusive_tax_amount_per_qty;
|
||||||
|
item.net_amount = flt(amount / (1 + cumulated_tax_fraction));
|
||||||
item.net_rate = item.qty ? flt(item.net_amount / item.qty, precision("net_rate", item)) : 0;
|
item.net_rate = item.qty ? flt(item.net_amount / item.qty, precision("net_rate", item)) : 0;
|
||||||
|
|
||||||
me.set_in_company_currency(item, ["net_rate", "net_amount"]);
|
me.set_in_company_currency(item, ["net_rate", "net_amount"]);
|
||||||
@ -191,6 +195,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
// Get tax fraction for calculating tax exclusive amount
|
// Get tax fraction for calculating tax exclusive amount
|
||||||
// from tax inclusive amount
|
// from tax inclusive amount
|
||||||
var current_tax_fraction = 0.0;
|
var current_tax_fraction = 0.0;
|
||||||
|
var inclusive_tax_amount_per_qty = 0;
|
||||||
|
|
||||||
if(cint(tax.included_in_print_rate)) {
|
if(cint(tax.included_in_print_rate)) {
|
||||||
var tax_rate = this._get_tax_rate(tax, item_tax_map);
|
var tax_rate = this._get_tax_rate(tax, item_tax_map);
|
||||||
@ -205,13 +210,16 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
} else if(tax.charge_type == "On Previous Row Total") {
|
} else if(tax.charge_type == "On Previous Row Total") {
|
||||||
current_tax_fraction = (tax_rate / 100.0) *
|
current_tax_fraction = (tax_rate / 100.0) *
|
||||||
this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_fraction_for_current_item;
|
this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_fraction_for_current_item;
|
||||||
|
} else if (tax.charge_type == "On Item Quantity") {
|
||||||
|
inclusive_tax_amount_per_qty = flt(tax_rate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tax.add_deduct_tax) {
|
if(tax.add_deduct_tax && tax.add_deduct_tax == "Deduct") {
|
||||||
current_tax_fraction *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
|
current_tax_fraction *= -1;
|
||||||
|
inclusive_tax_amount_per_qty *= -1;
|
||||||
}
|
}
|
||||||
return current_tax_fraction;
|
return [current_tax_fraction, inclusive_tax_amount_per_qty];
|
||||||
},
|
},
|
||||||
|
|
||||||
_get_tax_rate: function(tax, item_tax_map) {
|
_get_tax_rate: function(tax, item_tax_map) {
|
||||||
@ -360,8 +368,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
} else if(tax.charge_type == "On Previous Row Total") {
|
} else if(tax.charge_type == "On Previous Row Total") {
|
||||||
current_tax_amount = (tax_rate / 100.0) *
|
current_tax_amount = (tax_rate / 100.0) *
|
||||||
this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_for_current_item;
|
this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_for_current_item;
|
||||||
|
} else if (tax.charge_type == "On Item Quantity") {
|
||||||
|
current_tax_amount = tax_rate * item.qty;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set_item_wise_tax(item, tax, tax_rate, current_tax_amount);
|
this.set_item_wise_tax(item, tax, tax_rate, current_tax_amount);
|
||||||
|
|
||||||
return current_tax_amount;
|
return current_tax_amount;
|
||||||
@ -573,7 +582,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
var actual_taxes_dict = {};
|
var actual_taxes_dict = {};
|
||||||
|
|
||||||
$.each(this.frm.doc["taxes"] || [], function(i, tax) {
|
$.each(this.frm.doc["taxes"] || [], function(i, tax) {
|
||||||
if (tax.charge_type == "Actual") {
|
if (in_list(["Actual", "On Item Quantity"], tax.charge_type)) {
|
||||||
var tax_amount = (tax.category == "Valuation") ? 0.0 : tax.tax_amount;
|
var tax_amount = (tax.category == "Valuation") ? 0.0 : tax.tax_amount;
|
||||||
tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
|
tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
|
||||||
actual_taxes_dict[tax.idx] = tax_amount;
|
actual_taxes_dict[tax.idx] = tax_amount;
|
||||||
|
|||||||
@ -10,8 +10,7 @@ states = [
|
|||||||
'Bihar',
|
'Bihar',
|
||||||
'Chandigarh',
|
'Chandigarh',
|
||||||
'Chhattisgarh',
|
'Chhattisgarh',
|
||||||
'Dadra and Nagar Haveli',
|
'Dadra and Nagar Haveli and Daman and Diu',
|
||||||
'Daman and Diu',
|
|
||||||
'Delhi',
|
'Delhi',
|
||||||
'Goa',
|
'Goa',
|
||||||
'Gujarat',
|
'Gujarat',
|
||||||
@ -50,8 +49,7 @@ state_numbers = {
|
|||||||
"Bihar": "10",
|
"Bihar": "10",
|
||||||
"Chandigarh": "04",
|
"Chandigarh": "04",
|
||||||
"Chhattisgarh": "22",
|
"Chhattisgarh": "22",
|
||||||
"Dadra and Nagar Haveli": "26",
|
"Dadra and Nagar Haveli and Daman and Diu": "26",
|
||||||
"Daman and Diu": "25",
|
|
||||||
"Delhi": "07",
|
"Delhi": "07",
|
||||||
"Goa": "30",
|
"Goa": "30",
|
||||||
"Gujarat": "24",
|
"Gujarat": "24",
|
||||||
|
|||||||
@ -134,15 +134,10 @@
|
|||||||
"state_code": "DL",
|
"state_code": "DL",
|
||||||
"state_name": "Delhi"
|
"state_name": "Delhi"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"state_number": "25",
|
|
||||||
"state_code": "DD",
|
|
||||||
"state_name": "Daman and Diu"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"state_number": "26",
|
"state_number": "26",
|
||||||
"state_code": "DN",
|
"state_code": "DN",
|
||||||
"state_name": "Dadra and Nagar Haveli"
|
"state_name": "Dadra and Nagar Haveli and Daman and Diu"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"state_number": "22",
|
"state_number": "22",
|
||||||
|
|||||||
@ -185,6 +185,14 @@ class Customer(TransactionBase):
|
|||||||
if self.get("__islocal") or not self.credit_limits:
|
if self.get("__islocal") or not self.credit_limits:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
past_credit_limits = [d.credit_limit
|
||||||
|
for d in frappe.db.get_all("Customer Credit Limit", filters={'parent': self.name}, fields=["credit_limit"], order_by="company")]
|
||||||
|
|
||||||
|
current_credit_limits = [d.credit_limit for d in sorted(self.credit_limits, key=lambda k: k.company)]
|
||||||
|
|
||||||
|
if past_credit_limits == current_credit_limits:
|
||||||
|
return
|
||||||
|
|
||||||
company_record = []
|
company_record = []
|
||||||
for limit in self.credit_limits:
|
for limit in self.credit_limits:
|
||||||
if limit.company in company_record:
|
if limit.company in company_record:
|
||||||
|
|||||||
@ -923,7 +923,7 @@
|
|||||||
"fieldname": "lost_reasons",
|
"fieldname": "lost_reasons",
|
||||||
"fieldtype": "Table MultiSelect",
|
"fieldtype": "Table MultiSelect",
|
||||||
"label": "Lost Reasons",
|
"label": "Lost Reasons",
|
||||||
"options": "Lost Reason Detail",
|
"options": "Quotation Lost Reason Detail",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -932,7 +932,7 @@
|
|||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"max_attachments": 1,
|
"max_attachments": 1,
|
||||||
"modified": "2020-07-18 04:59:09.960118",
|
"modified": "2020-07-26 17:46:19.951223",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Quotation",
|
"name": "Quotation",
|
||||||
|
|||||||
@ -68,7 +68,7 @@ class Quotation(SellingController):
|
|||||||
|
|
||||||
def declare_enquiry_lost(self, lost_reasons_list, detailed_reason=None):
|
def declare_enquiry_lost(self, lost_reasons_list, detailed_reason=None):
|
||||||
if not self.has_sales_order():
|
if not self.has_sales_order():
|
||||||
get_lost_reasons = frappe.get_list('Opportunity Lost Reason',
|
get_lost_reasons = frappe.get_list('Quotation Lost Reason',
|
||||||
fields = ["name"])
|
fields = ["name"])
|
||||||
lost_reasons_lst = [reason.get('name') for reason in get_lost_reasons]
|
lost_reasons_lst = [reason.get('name') for reason in get_lost_reasons]
|
||||||
frappe.db.set(self, 'status', 'Lost')
|
frappe.db.set(self, 'status', 'Lost')
|
||||||
|
|||||||
@ -494,13 +494,18 @@ frappe.ui.form.on(cur_frm.doctype, {
|
|||||||
var dialog = new frappe.ui.Dialog({
|
var dialog = new frappe.ui.Dialog({
|
||||||
title: __("Set as Lost"),
|
title: __("Set as Lost"),
|
||||||
fields: [
|
fields: [
|
||||||
{"fieldtype": "Table MultiSelect",
|
{
|
||||||
|
"fieldtype": "Table MultiSelect",
|
||||||
"label": __("Lost Reasons"),
|
"label": __("Lost Reasons"),
|
||||||
"fieldname": "lost_reason",
|
"fieldname": "lost_reason",
|
||||||
"options": "Lost Reason Detail",
|
"options": frm.doctype === 'Opportunity' ? 'Opportunity Lost Reason Detail': 'Quotation Lost Reason Detail',
|
||||||
"reqd": 1},
|
"reqd": 1
|
||||||
|
},
|
||||||
{"fieldtype": "Text", "label": __("Detailed Reason"), "fieldname": "detailed_reason"},
|
{
|
||||||
|
"fieldtype": "Text",
|
||||||
|
"label": __("Detailed Reason"),
|
||||||
|
"fieldname": "detailed_reason"
|
||||||
|
},
|
||||||
],
|
],
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
var values = dialog.get_values();
|
var values = dialog.get_values();
|
||||||
|
|||||||
@ -34,6 +34,16 @@ frappe.ui.form.on("Company", {
|
|||||||
frm.set_query("default_buying_terms", function() {
|
frm.set_query("default_buying_terms", function() {
|
||||||
return { filters: { buying: 1 } };
|
return { filters: { buying: 1 } };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frm.set_query("default_in_transit_warehouse", function() {
|
||||||
|
return {
|
||||||
|
filters:{
|
||||||
|
'warehouse_type' : 'Transit',
|
||||||
|
'is_group': 0,
|
||||||
|
'company': frm.doc.company
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
company_name: function(frm) {
|
company_name: function(frm) {
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
"default_selling_terms",
|
"default_selling_terms",
|
||||||
"default_buying_terms",
|
"default_buying_terms",
|
||||||
"default_warehouse_for_sales_return",
|
"default_warehouse_for_sales_return",
|
||||||
|
"default_in_transit_warehouse",
|
||||||
"column_break_10",
|
"column_break_10",
|
||||||
"country",
|
"country",
|
||||||
"create_chart_of_accounts_based_on",
|
"create_chart_of_accounts_based_on",
|
||||||
@ -733,6 +734,12 @@
|
|||||||
"fieldname": "enable_perpetual_inventory_for_non_stock_items",
|
"fieldname": "enable_perpetual_inventory_for_non_stock_items",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Enable Perpetual Inventory For Non Stock Items"
|
"label": "Enable Perpetual Inventory For Non Stock Items"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "default_in_transit_warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Default In Transit Warehouse",
|
||||||
|
"options": "Warehouse"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-building",
|
"icon": "fa fa-building",
|
||||||
@ -740,7 +747,7 @@
|
|||||||
"image_field": "company_logo",
|
"image_field": "company_logo",
|
||||||
"is_tree": 1,
|
"is_tree": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-06-24 12:45:31.462195",
|
"modified": "2020-08-06 00:38:08.311216",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "Company",
|
"name": "Company",
|
||||||
|
|||||||
@ -140,7 +140,8 @@ class Company(NestedSet):
|
|||||||
{"warehouse_name": _("All Warehouses"), "is_group": 1},
|
{"warehouse_name": _("All Warehouses"), "is_group": 1},
|
||||||
{"warehouse_name": _("Stores"), "is_group": 0},
|
{"warehouse_name": _("Stores"), "is_group": 0},
|
||||||
{"warehouse_name": _("Work In Progress"), "is_group": 0},
|
{"warehouse_name": _("Work In Progress"), "is_group": 0},
|
||||||
{"warehouse_name": _("Finished Goods"), "is_group": 0}]:
|
{"warehouse_name": _("Finished Goods"), "is_group": 0},
|
||||||
|
{"warehouse_name": _("Goods In Transit"), "is_group": 0, "warehouse_type": "Transit"}]:
|
||||||
|
|
||||||
if not frappe.db.exists("Warehouse", "{0} - {1}".format(wh_detail["warehouse_name"], self.abbr)):
|
if not frappe.db.exists("Warehouse", "{0} - {1}".format(wh_detail["warehouse_name"], self.abbr)):
|
||||||
warehouse = frappe.get_doc({
|
warehouse = frappe.get_doc({
|
||||||
@ -149,7 +150,8 @@ class Company(NestedSet):
|
|||||||
"is_group": wh_detail["is_group"],
|
"is_group": wh_detail["is_group"],
|
||||||
"company": self.name,
|
"company": self.name,
|
||||||
"parent_warehouse": "{0} - {1}".format(_("All Warehouses"), self.abbr) \
|
"parent_warehouse": "{0} - {1}".format(_("All Warehouses"), self.abbr) \
|
||||||
if not wh_detail["is_group"] else ""
|
if not wh_detail["is_group"] else "",
|
||||||
|
"warehouse_type" : wh_detail["warehouse_type"] if "warehouse_type" in wh_detail else None
|
||||||
})
|
})
|
||||||
warehouse.flags.ignore_permissions = True
|
warehouse.flags.ignore_permissions = True
|
||||||
warehouse.flags.ignore_mandatory = True
|
warehouse.flags.ignore_mandatory = True
|
||||||
|
|||||||
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"creation": "2020-07-14 09:21:44.057724",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"lost_reason"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "lost_reason",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Quotation Lost Reason",
|
||||||
|
"options": "Quotation Lost Reason"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"istable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2020-07-26 17:58:56.373775",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Setup",
|
||||||
|
"name": "Quotation Lost Reason Detail",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"quick_entry": 1,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"track_changes": 1
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
# import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class QuotationLostReasonDetail(Document):
|
||||||
|
pass
|
||||||
@ -95,8 +95,6 @@ def install(country=None):
|
|||||||
{'doctype': 'Stock Entry Type', 'name': 'Send to Subcontractor', 'purpose': 'Send to Subcontractor'},
|
{'doctype': 'Stock Entry Type', 'name': 'Send to Subcontractor', 'purpose': 'Send to Subcontractor'},
|
||||||
{'doctype': 'Stock Entry Type', 'name': 'Material Transfer for Manufacture', 'purpose': 'Material Transfer for Manufacture'},
|
{'doctype': 'Stock Entry Type', 'name': 'Material Transfer for Manufacture', 'purpose': 'Material Transfer for Manufacture'},
|
||||||
{'doctype': 'Stock Entry Type', 'name': 'Material Consumption for Manufacture', 'purpose': 'Material Consumption for Manufacture'},
|
{'doctype': 'Stock Entry Type', 'name': 'Material Consumption for Manufacture', 'purpose': 'Material Consumption for Manufacture'},
|
||||||
{'doctype': 'Stock Entry Type', 'name': 'Send to Warehouse', 'purpose': 'Send to Warehouse'},
|
|
||||||
{'doctype': 'Stock Entry Type', 'name': 'Receive at Warehouse', 'purpose': 'Receive at Warehouse'},
|
|
||||||
|
|
||||||
# Designation
|
# Designation
|
||||||
{'doctype': 'Designation', 'designation_name': _('CEO')},
|
{'doctype': 'Designation', 'designation_name': _('CEO')},
|
||||||
@ -244,7 +242,10 @@ def install(country=None):
|
|||||||
{"doctype": "Sales Stage", "stage_name": _("Identifying Decision Makers")},
|
{"doctype": "Sales Stage", "stage_name": _("Identifying Decision Makers")},
|
||||||
{"doctype": "Sales Stage", "stage_name": _("Perception Analysis")},
|
{"doctype": "Sales Stage", "stage_name": _("Perception Analysis")},
|
||||||
{"doctype": "Sales Stage", "stage_name": _("Proposal/Price Quote")},
|
{"doctype": "Sales Stage", "stage_name": _("Proposal/Price Quote")},
|
||||||
{"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")}
|
{"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")},
|
||||||
|
|
||||||
|
# Warehouse Type
|
||||||
|
{'doctype': 'Warehouse Type', 'name': 'Transit'},
|
||||||
]
|
]
|
||||||
|
|
||||||
from erpnext.setup.setup_wizard.data.industry_type import get_industry_types
|
from erpnext.setup.setup_wizard.data.industry_type import get_industry_types
|
||||||
|
|||||||
@ -123,6 +123,7 @@
|
|||||||
"weightage",
|
"weightage",
|
||||||
"slideshow",
|
"slideshow",
|
||||||
"website_image",
|
"website_image",
|
||||||
|
"website_image_alt",
|
||||||
"thumbnail",
|
"thumbnail",
|
||||||
"cb72",
|
"cb72",
|
||||||
"website_warehouse",
|
"website_warehouse",
|
||||||
@ -1054,15 +1055,21 @@
|
|||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Default Manufacturer Part No",
|
"label": "Default Manufacturer Part No",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "website_image_alt",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Image Description"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 1,
|
"has_web_view": 1,
|
||||||
"icon": "fa fa-tag",
|
"icon": "fa fa-tag",
|
||||||
"idx": 2,
|
"idx": 2,
|
||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"max_attachments": 1,
|
"max_attachments": 1,
|
||||||
"modified": "2020-07-31 21:21:10.956453",
|
"modified": "2020-08-07 14:24:58.384992",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Item",
|
"name": "Item",
|
||||||
|
|||||||
@ -343,7 +343,7 @@ class Item(WebsiteGenerator):
|
|||||||
if variant:
|
if variant:
|
||||||
context.variant = frappe.get_doc("Item", variant)
|
context.variant = frappe.get_doc("Item", variant)
|
||||||
|
|
||||||
for fieldname in ("website_image", "web_long_description", "description",
|
for fieldname in ("website_image", "website_image_alt", "web_long_description", "description",
|
||||||
"website_specifications"):
|
"website_specifications"):
|
||||||
if context.variant.get(fieldname):
|
if context.variant.get(fieldname):
|
||||||
value = context.variant.get(fieldname)
|
value = context.variant.get(fieldname)
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
"naming_series",
|
"naming_series",
|
||||||
"title",
|
"title",
|
||||||
"material_request_type",
|
"material_request_type",
|
||||||
|
"transfer_status",
|
||||||
"customer",
|
"customer",
|
||||||
"column_break_2",
|
"column_break_2",
|
||||||
"schedule_date",
|
"schedule_date",
|
||||||
@ -303,13 +304,22 @@
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Set From Warehouse",
|
"label": "Set From Warehouse",
|
||||||
"options": "Warehouse"
|
"options": "Warehouse"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
|
"depends_on": "eval:doc.add_to_transit == 1",
|
||||||
|
"fieldname": "transfer_status",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Transfer Status",
|
||||||
|
"options": "\nNot Started\nIn Transit\nCompleted",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-ticket",
|
"icon": "fa fa-ticket",
|
||||||
"idx": 70,
|
"idx": 70,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-05-01 20:21:09.990867",
|
"modified": "2020-08-10 13:27:54.891058",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Material Request",
|
"name": "Material Request",
|
||||||
|
|||||||
@ -1,8 +1,16 @@
|
|||||||
frappe.listview_settings['Material Request'] = {
|
frappe.listview_settings['Material Request'] = {
|
||||||
add_fields: ["material_request_type", "status", "per_ordered", "per_received"],
|
add_fields: ["material_request_type", "status", "per_ordered", "per_received", "transfer_status"],
|
||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
if(doc.status=="Stopped") {
|
if(doc.status=="Stopped") {
|
||||||
return [__("Stopped"), "red", "status,=,Stopped"];
|
return [__("Stopped"), "red", "status,=,Stopped"];
|
||||||
|
} else if(doc.transfer_status && doc.docstatus != 2) {
|
||||||
|
if (doc.transfer_status == "Not Started") {
|
||||||
|
return [__("Not Started"), "orange"];
|
||||||
|
} else if (doc.transfer_status == "In Transit") {
|
||||||
|
return [__("In Transit"), "yellow"];
|
||||||
|
} else if (doc.transfer_status == "Completed") {
|
||||||
|
return [__("Completed"), "green"];
|
||||||
|
}
|
||||||
} else if(doc.docstatus==1 && flt(doc.per_ordered, 2) == 0) {
|
} else if(doc.docstatus==1 && flt(doc.per_ordered, 2) == 0) {
|
||||||
return [__("Pending"), "orange", "per_ordered,=,0"];
|
return [__("Pending"), "orange", "per_ordered,=,0"];
|
||||||
} else if(doc.docstatus==1 && flt(doc.per_ordered, 2) < 100) {
|
} else if(doc.docstatus==1 && flt(doc.per_ordered, 2) < 100) {
|
||||||
|
|||||||
@ -19,7 +19,6 @@ frappe.ui.form.on('Stock Entry', {
|
|||||||
filters: [
|
filters: [
|
||||||
['Stock Entry', 'docstatus', '=', 1],
|
['Stock Entry', 'docstatus', '=', 1],
|
||||||
['Stock Entry', 'per_transferred', '<','100'],
|
['Stock Entry', 'per_transferred', '<','100'],
|
||||||
['Stock Entry', 'purpose', '=', 'Send to Warehouse']
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -171,9 +170,9 @@ frappe.ui.form.on('Stock Entry', {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frm.doc.docstatus === 1 && frm.doc.purpose == 'Send to Warehouse') {
|
if (frm.doc.docstatus === 1) {
|
||||||
if (frm.doc.per_transferred < 100) {
|
if (frm.doc.add_to_transit && frm.doc.purpose=='Material Transfer' && frm.doc.per_transferred < 100) {
|
||||||
frm.add_custom_button(__('Receive at Warehouse Entry'), function() {
|
frm.add_custom_button('End Transit', function() {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.stock.doctype.stock_entry.stock_entry.make_stock_in_entry",
|
method: "erpnext.stock.doctype.stock_entry.stock_entry.make_stock_in_entry",
|
||||||
frm: frm
|
frm: frm
|
||||||
@ -266,6 +265,7 @@ frappe.ui.form.on('Stock Entry', {
|
|||||||
stock_entry_type: function(frm){
|
stock_entry_type: function(frm){
|
||||||
frm.remove_custom_button('Bill of Materials', "Get items from");
|
frm.remove_custom_button('Bill of Materials', "Get items from");
|
||||||
frm.events.show_bom_custom_button(frm);
|
frm.events.show_bom_custom_button(frm);
|
||||||
|
frm.trigger('add_to_transit');
|
||||||
},
|
},
|
||||||
|
|
||||||
purpose: function(frm) {
|
purpose: function(frm) {
|
||||||
@ -532,6 +532,26 @@ frappe.ui.form.on('Stock Entry', {
|
|||||||
|
|
||||||
target_warehouse_address: function(frm) {
|
target_warehouse_address: function(frm) {
|
||||||
erpnext.utils.get_address_display(frm, 'target_warehouse_address', 'target_address_display', false);
|
erpnext.utils.get_address_display(frm, 'target_warehouse_address', 'target_address_display', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
add_to_transit: function(frm) {
|
||||||
|
if(frm.doc.add_to_transit && frm.doc.purpose=='Material Transfer') {
|
||||||
|
frm.set_value('stock_entry_type', 'Material Transfer');
|
||||||
|
frm.fields_dict.to_warehouse.get_query = function() {
|
||||||
|
return {
|
||||||
|
filters:{
|
||||||
|
'warehouse_type' : 'Transit',
|
||||||
|
'is_group': 0,
|
||||||
|
'company': frm.doc.company
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
frappe.db.get_value('Company', frm.doc.company, 'default_in_transit_warehouse', (r) => {
|
||||||
|
if (r.default_in_transit_warehouse) {
|
||||||
|
frm.set_value('to_warehouse', r.default_in_transit_warehouse);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -754,6 +774,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
|||||||
}
|
}
|
||||||
erpnext.hide_company();
|
erpnext.hide_company();
|
||||||
erpnext.utils.add_item(this.frm);
|
erpnext.utils.add_item(this.frm);
|
||||||
|
this.frm.trigger('add_to_transit');
|
||||||
},
|
},
|
||||||
|
|
||||||
scan_barcode: function() {
|
scan_barcode: function() {
|
||||||
@ -919,8 +940,6 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
|||||||
doc.purpose!='Material Issue');
|
doc.purpose!='Material Issue');
|
||||||
|
|
||||||
this.frm.fields_dict["items"].grid.set_column_disp("additional_cost", doc.purpose!='Material Issue');
|
this.frm.fields_dict["items"].grid.set_column_disp("additional_cost", doc.purpose!='Material Issue');
|
||||||
this.frm.toggle_reqd("outgoing_stock_entry",
|
|
||||||
doc.purpose == 'Receive at Warehouse' ? 1: 0);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
supplier: function(doc) {
|
supplier: function(doc) {
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
"stock_entry_type",
|
"stock_entry_type",
|
||||||
"outgoing_stock_entry",
|
"outgoing_stock_entry",
|
||||||
"purpose",
|
"purpose",
|
||||||
|
"add_to_transit",
|
||||||
"work_order",
|
"work_order",
|
||||||
"purchase_order",
|
"purchase_order",
|
||||||
"delivery_note_no",
|
"delivery_note_no",
|
||||||
@ -116,11 +117,12 @@
|
|||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.purpose == 'Receive at Warehouse'",
|
"depends_on": "eval:doc.purpose == 'Material Transfer'",
|
||||||
"fieldname": "outgoing_stock_entry",
|
"fieldname": "outgoing_stock_entry",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Stock Entry (Outward GIT)",
|
"label": "Stock Entry (Outward GIT)",
|
||||||
"options": "Stock Entry"
|
"options": "Stock Entry",
|
||||||
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bold": 1,
|
"bold": 1,
|
||||||
@ -132,7 +134,7 @@
|
|||||||
"label": "Purpose",
|
"label": "Purpose",
|
||||||
"oldfieldname": "purpose",
|
"oldfieldname": "purpose",
|
||||||
"oldfieldtype": "Select",
|
"oldfieldtype": "Select",
|
||||||
"options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor\nSend to Warehouse\nReceive at Warehouse",
|
"options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -630,13 +632,21 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "print_settings_col_break",
|
"fieldname": "print_settings_col_break",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"depends_on": "eval: doc.purpose=='Material Transfer' && !doc.outgoing_stock_entry",
|
||||||
|
"fieldname": "add_to_transit",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Add to Transit",
|
||||||
|
"no_copy": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-23 12:56:52.881752",
|
"modified": "2020-08-11 19:10:07.954981",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock Entry",
|
"name": "Stock Entry",
|
||||||
|
|||||||
@ -97,6 +97,11 @@ class StockEntry(StockController):
|
|||||||
if self.work_order and self.purpose == "Manufacture":
|
if self.work_order and self.purpose == "Manufacture":
|
||||||
self.update_so_in_serial_number()
|
self.update_so_in_serial_number()
|
||||||
|
|
||||||
|
if self.purpose == 'Material Transfer' and self.add_to_transit:
|
||||||
|
self.set_material_request_transfer_status('In Transit')
|
||||||
|
if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
|
||||||
|
self.set_material_request_transfer_status('Completed')
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
|
|
||||||
if self.purchase_order and self.purpose == "Send to Subcontractor":
|
if self.purchase_order and self.purpose == "Send to Subcontractor":
|
||||||
@ -116,6 +121,11 @@ class StockEntry(StockController):
|
|||||||
self.update_quality_inspection()
|
self.update_quality_inspection()
|
||||||
self.delete_auto_created_batches()
|
self.delete_auto_created_batches()
|
||||||
|
|
||||||
|
if self.purpose == 'Material Transfer' and self.add_to_transit:
|
||||||
|
self.set_material_request_transfer_status('Not Started')
|
||||||
|
if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
|
||||||
|
self.set_material_request_transfer_status('In Transit')
|
||||||
|
|
||||||
def set_job_card_data(self):
|
def set_job_card_data(self):
|
||||||
if self.job_card and not self.work_order:
|
if self.job_card and not self.work_order:
|
||||||
data = frappe.db.get_value('Job Card',
|
data = frappe.db.get_value('Job Card',
|
||||||
@ -133,7 +143,7 @@ class StockEntry(StockController):
|
|||||||
def validate_purpose(self):
|
def validate_purpose(self):
|
||||||
valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer",
|
valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer",
|
||||||
"Material Transfer for Manufacture", "Manufacture", "Repack", "Send to Subcontractor",
|
"Material Transfer for Manufacture", "Manufacture", "Repack", "Send to Subcontractor",
|
||||||
"Material Consumption for Manufacture", "Send to Warehouse", "Receive at Warehouse"]
|
"Material Consumption for Manufacture"]
|
||||||
|
|
||||||
if self.purpose not in valid_purposes:
|
if self.purpose not in valid_purposes:
|
||||||
frappe.throw(_("Purpose must be one of {0}").format(comma_or(valid_purposes)))
|
frappe.throw(_("Purpose must be one of {0}").format(comma_or(valid_purposes)))
|
||||||
@ -199,7 +209,8 @@ class StockEntry(StockController):
|
|||||||
item.set(f, item_details.get(f))
|
item.set(f, item_details.get(f))
|
||||||
|
|
||||||
if not item.transfer_qty and item.qty:
|
if not item.transfer_qty and item.qty:
|
||||||
item.transfer_qty = item.qty * item.conversion_factor
|
item.transfer_qty = flt(flt(item.qty) * flt(item.conversion_factor),
|
||||||
|
self.precision("transfer_qty", item))
|
||||||
|
|
||||||
if (self.purpose in ("Material Transfer", "Material Transfer for Manufacture")
|
if (self.purpose in ("Material Transfer", "Material Transfer for Manufacture")
|
||||||
and not item.serial_no
|
and not item.serial_no
|
||||||
@ -258,10 +269,10 @@ class StockEntry(StockController):
|
|||||||
"""perform various (sometimes conditional) validations on warehouse"""
|
"""perform various (sometimes conditional) validations on warehouse"""
|
||||||
|
|
||||||
source_mandatory = ["Material Issue", "Material Transfer", "Send to Subcontractor", "Material Transfer for Manufacture",
|
source_mandatory = ["Material Issue", "Material Transfer", "Send to Subcontractor", "Material Transfer for Manufacture",
|
||||||
"Material Consumption for Manufacture", "Send to Warehouse", "Receive at Warehouse"]
|
"Material Consumption for Manufacture"]
|
||||||
|
|
||||||
target_mandatory = ["Material Receipt", "Material Transfer", "Send to Subcontractor",
|
target_mandatory = ["Material Receipt", "Material Transfer", "Send to Subcontractor",
|
||||||
"Material Transfer for Manufacture", "Send to Warehouse", "Receive at Warehouse"]
|
"Material Transfer for Manufacture"]
|
||||||
|
|
||||||
validate_for_manufacture = any([d.bom_no for d in self.get("items")])
|
validate_for_manufacture = any([d.bom_no for d in self.get("items")])
|
||||||
|
|
||||||
@ -809,7 +820,7 @@ class StockEntry(StockController):
|
|||||||
def set_items_for_stock_in(self):
|
def set_items_for_stock_in(self):
|
||||||
self.items = []
|
self.items = []
|
||||||
|
|
||||||
if self.outgoing_stock_entry and self.purpose == 'Receive at Warehouse':
|
if self.outgoing_stock_entry and self.purpose == 'Material Transfer':
|
||||||
doc = frappe.get_doc('Stock Entry', self.outgoing_stock_entry)
|
doc = frappe.get_doc('Stock Entry', self.outgoing_stock_entry)
|
||||||
|
|
||||||
if doc.per_transferred == 100:
|
if doc.per_transferred == 100:
|
||||||
@ -1210,13 +1221,25 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
def validate_with_material_request(self):
|
def validate_with_material_request(self):
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
if item.material_request:
|
material_request = item.material_request or None
|
||||||
|
material_request_item = item.material_request_item or None
|
||||||
|
if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
|
||||||
|
parent_se = frappe.get_value("Stock Entry Detail", item.ste_detail, ['material_request','material_request_item'],as_dict=True)
|
||||||
|
if parent_se:
|
||||||
|
material_request = parent_se.material_request
|
||||||
|
material_request_item = parent_se.material_request_item
|
||||||
|
|
||||||
|
if material_request:
|
||||||
mreq_item = frappe.db.get_value("Material Request Item",
|
mreq_item = frappe.db.get_value("Material Request Item",
|
||||||
{"name": item.material_request_item, "parent": item.material_request},
|
{"name": material_request_item, "parent": material_request},
|
||||||
["item_code", "warehouse", "idx"], as_dict=True)
|
["item_code", "warehouse", "idx"], as_dict=True)
|
||||||
if mreq_item.item_code != item.item_code or \
|
if mreq_item.item_code != item.item_code:
|
||||||
mreq_item.warehouse != (item.s_warehouse if self.purpose== "Material Issue" else item.t_warehouse):
|
frappe.throw(_("Item for row {0} does not match Material Request").format(item.idx),
|
||||||
frappe.throw(_("Item or Warehouse for row {0} does not match Material Request").format(item.idx),
|
frappe.MappingMismatchError)
|
||||||
|
elif self.purpose == "Material Transfer" and self.add_to_transit:
|
||||||
|
continue
|
||||||
|
elif mreq_item.warehouse != (item.s_warehouse if self.purpose == "Material Issue" else item.t_warehouse):
|
||||||
|
frappe.throw(_("Warehouse for row {0} does not match Material Request").format(item.idx),
|
||||||
frappe.MappingMismatchError)
|
frappe.MappingMismatchError)
|
||||||
|
|
||||||
def validate_batch(self):
|
def validate_batch(self):
|
||||||
@ -1284,7 +1307,7 @@ class StockEntry(StockController):
|
|||||||
to fullfill Sales Order {2}.").format(item.item_code, sr, sales_order))
|
to fullfill Sales Order {2}.").format(item.item_code, sr, sales_order))
|
||||||
|
|
||||||
def update_transferred_qty(self):
|
def update_transferred_qty(self):
|
||||||
if self.purpose == 'Receive at Warehouse':
|
if self.purpose == 'Material Transfer' and self.outgoing_stock_entry:
|
||||||
stock_entries = {}
|
stock_entries = {}
|
||||||
stock_entries_child_list = []
|
stock_entries_child_list = []
|
||||||
for d in self.items:
|
for d in self.items:
|
||||||
@ -1342,6 +1365,20 @@ class StockEntry(StockController):
|
|||||||
'reference_type': reference_type,
|
'reference_type': reference_type,
|
||||||
'reference_name': reference_name
|
'reference_name': reference_name
|
||||||
})
|
})
|
||||||
|
def set_material_request_transfer_status(self, status):
|
||||||
|
material_requests = []
|
||||||
|
if self.outgoing_stock_entry:
|
||||||
|
parent_se = frappe.get_value("Stock Entry", self.outgoing_stock_entry, 'add_to_transit')
|
||||||
|
|
||||||
|
for item in self.items:
|
||||||
|
material_request = item.material_request or None
|
||||||
|
if self.purpose == "Material Transfer" and material_request not in material_requests:
|
||||||
|
if self.outgoing_stock_entry and parent_se:
|
||||||
|
material_request = frappe.get_value("Stock Entry Detail", item.ste_detail, 'material_request')
|
||||||
|
|
||||||
|
if material_request and material_request not in material_requests:
|
||||||
|
material_requests.append(material_request)
|
||||||
|
frappe.db.set_value('Material Request', material_request, 'transfer_status', status)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def move_sample_to_retention_warehouse(company, items):
|
def move_sample_to_retention_warehouse(company, items):
|
||||||
@ -1381,12 +1418,19 @@ def move_sample_to_retention_warehouse(company, items):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_stock_in_entry(source_name, target_doc=None):
|
def make_stock_in_entry(source_name, target_doc=None):
|
||||||
|
|
||||||
def set_missing_values(source, target):
|
def set_missing_values(source, target):
|
||||||
target.purpose = 'Receive at Warehouse'
|
|
||||||
target.set_stock_entry_type()
|
target.set_stock_entry_type()
|
||||||
|
|
||||||
def update_item(source_doc, target_doc, source_parent):
|
def update_item(source_doc, target_doc, source_parent):
|
||||||
target_doc.t_warehouse = ''
|
target_doc.t_warehouse = ''
|
||||||
|
|
||||||
|
if source_doc.material_request_item and source_doc.material_request :
|
||||||
|
add_to_transit = frappe.db.get_value('Stock Entry', source_name, 'add_to_transit')
|
||||||
|
if add_to_transit:
|
||||||
|
warehouse = frappe.get_value('Material Request Item', source_doc.material_request_item, 'warehouse')
|
||||||
|
target_doc.t_warehouse = warehouse
|
||||||
|
|
||||||
target_doc.s_warehouse = source_doc.t_warehouse
|
target_doc.s_warehouse = source_doc.t_warehouse
|
||||||
target_doc.qty = source_doc.qty - source_doc.transferred_qty
|
target_doc.qty = source_doc.qty - source_doc.transferred_qty
|
||||||
|
|
||||||
|
|||||||
@ -737,34 +737,6 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
self.assertEqual(se.get("items")[0].allow_zero_valuation_rate, 1)
|
self.assertEqual(se.get("items")[0].allow_zero_valuation_rate, 1)
|
||||||
self.assertEqual(se.get("items")[0].amount, 0)
|
self.assertEqual(se.get("items")[0].amount, 0)
|
||||||
|
|
||||||
def test_goods_in_transit(self):
|
|
||||||
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
|
||||||
warehouse = "_Test Warehouse FG 1 - _TC"
|
|
||||||
|
|
||||||
if not frappe.db.exists('Warehouse', warehouse):
|
|
||||||
create_warehouse("_Test Warehouse FG 1")
|
|
||||||
|
|
||||||
outward_entry = make_stock_entry(item_code="_Test Item",
|
|
||||||
purpose="Send to Warehouse",
|
|
||||||
source="_Test Warehouse - _TC",
|
|
||||||
target="_Test Warehouse 1 - _TC", qty=50, basic_rate=100)
|
|
||||||
|
|
||||||
inward_entry1 = make_stock_in_entry(outward_entry.name)
|
|
||||||
inward_entry1.items[0].t_warehouse = warehouse
|
|
||||||
inward_entry1.items[0].qty = 25
|
|
||||||
inward_entry1.submit()
|
|
||||||
|
|
||||||
doc = frappe.get_doc('Stock Entry', outward_entry.name)
|
|
||||||
self.assertEqual(doc.per_transferred, 50)
|
|
||||||
|
|
||||||
inward_entry2 = make_stock_in_entry(outward_entry.name)
|
|
||||||
inward_entry2.items[0].t_warehouse = warehouse
|
|
||||||
inward_entry2.items[0].qty = 25
|
|
||||||
inward_entry2.submit()
|
|
||||||
|
|
||||||
doc = frappe.get_doc('Stock Entry', outward_entry.name)
|
|
||||||
self.assertEqual(doc.per_transferred, 100)
|
|
||||||
|
|
||||||
def test_gle_for_opening_stock_entry(self):
|
def test_gle_for_opening_stock_entry(self):
|
||||||
mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company="_Test Company with perpetual inventory",qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1", is_opening="Yes", do_not_save=True)
|
mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company="_Test Company with perpetual inventory",qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1", is_opening="Yes", do_not_save=True)
|
||||||
|
|
||||||
|
|||||||
@ -1,156 +1,83 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"autoname": "Prompt",
|
"autoname": "Prompt",
|
||||||
"beta": 0,
|
|
||||||
"creation": "2019-03-13 16:23:46.636769",
|
"creation": "2019-03-13 16:23:46.636769",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"purpose"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "Material Issue",
|
"default": "Material Issue",
|
||||||
"fetch_if_empty": 0,
|
|
||||||
"fieldname": "purpose",
|
"fieldname": "purpose",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Purpose",
|
"label": "Purpose",
|
||||||
"length": 0,
|
"options": "\nMaterial Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor",
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nMaterial Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor\nSend to Warehouse\nReceive at Warehouse",
|
|
||||||
"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,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"set_only_once": 1
|
||||||
"set_only_once": 1,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"links": [],
|
||||||
"hide_heading": 0,
|
"modified": "2020-08-10 23:24:37.160817",
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 0,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2019-03-26 12:02:42.144377",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock Entry Type",
|
"name": "Stock Entry Type",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Manufacturing Manager",
|
"role": "Manufacturing Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Stock Manager",
|
"role": "Stock Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Stock User",
|
"role": "Stock User",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
"track_changes": 1,
|
"track_changes": 1
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
||||||
@ -23,7 +23,7 @@
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ product_image(website_image or image or 'no-image.jpg') }}
|
{{ product_image(website_image or image or 'no-image.jpg', alt=website_image_alt or item_name) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Simple image preview -->
|
<!-- Simple image preview -->
|
||||||
|
|||||||
@ -7,9 +7,9 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro product_image(website_image, css_class="") %}
|
{% macro product_image(website_image, css_class="", alt="") %}
|
||||||
<div class="border text-center rounded h-100 {{ css_class }}" style="overflow: hidden;">
|
<div class="border text-center rounded h-100 {{ css_class }}" style="overflow: hidden;">
|
||||||
<img itemprop="image" class="website-image h-100 w-100" src="{{ frappe.utils.quoted(website_image or 'no-image.jpg') | abs_url }}">
|
<img itemprop="image" class="website-image h-100 w-100" alt="{{ alt }}" src="{{ frappe.utils.quoted(website_image or 'no-image.jpg') | abs_url }}">
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,33 @@
|
|||||||
<p class="hero-subtitle">{{ greeting_subtitle }}</p>
|
<p class="hero-subtitle">{{ greeting_subtitle }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="search-container">
|
||||||
|
<div class="website-search" id="search-container">
|
||||||
|
<div class="dropdown">
|
||||||
|
<div class="search-icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="feather feather-search">
|
||||||
|
<circle cx="11" cy="11" r="8"></circle>
|
||||||
|
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<input type="search" class="form-control" placeholder="Search the docs (Press ? to focus)" />
|
||||||
|
<div class="overflow-hidden shadow dropdown-menu w-100">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="navbar-toggler" type="button"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-target="#navbarSupportedContent"
|
||||||
|
aria-controls="navbarSupportedContent"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -54,5 +81,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{%- block script -%}
|
||||||
|
<script>
|
||||||
|
frappe.ready(() => {
|
||||||
|
frappe.setup_search('#search-container', 'kb');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{%- endblock -%}
|
||||||
|
|
||||||
|
{%- block style -%}
|
||||||
|
<style>
|
||||||
|
.search-container {
|
||||||
|
margin-top: 1.2rem;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{%- endblock -%}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user