Merge branch 'develop' into serial-no-space
This commit is contained in:
commit
f6ea00e029
@ -10,6 +10,7 @@
|
||||
"accounts_transactions_settings_section",
|
||||
"over_billing_allowance",
|
||||
"role_allowed_to_over_bill",
|
||||
"credit_controller",
|
||||
"make_payment_via_journal_entry",
|
||||
"column_break_11",
|
||||
"check_supplier_invoice_uniqueness",
|
||||
@ -27,7 +28,6 @@
|
||||
"acc_frozen_upto",
|
||||
"frozen_accounts_modifier",
|
||||
"column_break_4",
|
||||
"credit_controller",
|
||||
"deferred_accounting_settings_section",
|
||||
"book_deferred_entries_based_on",
|
||||
"column_break_18",
|
||||
@ -73,11 +73,10 @@
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"description": "This role is allowed to submit transactions that exceed credit limits",
|
||||
"fieldname": "credit_controller",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Credit Controller",
|
||||
"label": "Role allowed to bypass Credit Limit",
|
||||
"options": "Role"
|
||||
},
|
||||
{
|
||||
@ -268,7 +267,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2021-06-17 20:26:03.721202",
|
||||
"modified": "2021-08-09 13:08:01.335416",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
|
@ -558,7 +558,8 @@
|
||||
"description": "Simple Python Expression, Example: territory != 'All Territories'",
|
||||
"fieldname": "condition",
|
||||
"fieldtype": "Code",
|
||||
"label": "Condition"
|
||||
"label": "Condition",
|
||||
"options": "PythonExpression"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_42",
|
||||
@ -575,7 +576,7 @@
|
||||
"icon": "fa fa-gift",
|
||||
"idx": 1,
|
||||
"links": [],
|
||||
"modified": "2021-03-06 22:01:24.840422",
|
||||
"modified": "2021-08-06 15:10:04.219321",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Pricing Rule",
|
||||
|
@ -78,7 +78,7 @@
|
||||
"label": "Cost"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.price_determination==\"Based on price list\"",
|
||||
"depends_on": "eval:doc.price_determination==\"Based On Price List\"",
|
||||
"fieldname": "price_list",
|
||||
"fieldtype": "Link",
|
||||
"label": "Price List",
|
||||
@ -147,7 +147,7 @@
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-06-25 10:53:44.205774",
|
||||
"modified": "2021-08-09 10:53:44.205774",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Subscription Plan",
|
||||
|
@ -1507,7 +1507,7 @@ def set_child_tax_template_and_map(item, child_item, parent_doc):
|
||||
if child_item.get("item_tax_template"):
|
||||
child_item.item_tax_rate = get_item_tax_map(parent_doc.get('company'), child_item.item_tax_template, as_json=True)
|
||||
|
||||
def add_taxes_from_tax_template(child_item, parent_doc):
|
||||
def add_taxes_from_tax_template(child_item, parent_doc, db_insert=True):
|
||||
add_taxes_from_item_tax_template = frappe.db.get_single_value("Accounts Settings", "add_taxes_from_item_tax_template")
|
||||
|
||||
if child_item.get("item_tax_rate") and add_taxes_from_item_tax_template:
|
||||
@ -1530,7 +1530,8 @@ def add_taxes_from_tax_template(child_item, parent_doc):
|
||||
"category" : "Total",
|
||||
"add_deduct_tax" : "Add"
|
||||
})
|
||||
tax_row.db_insert()
|
||||
if db_insert:
|
||||
tax_row.db_insert()
|
||||
|
||||
def set_order_defaults(parent_doctype, parent_doctype_name, child_doctype, child_docname, trans_item):
|
||||
"""
|
||||
|
@ -9,7 +9,7 @@ import datetime
|
||||
|
||||
|
||||
def create_test_lead():
|
||||
test_lead = frappe.db.exists({'doctype': 'Lead', 'lead_name': 'Test Lead'})
|
||||
test_lead = frappe.db.exists({'doctype': 'Lead', 'email_id':'test@example.com'})
|
||||
if test_lead:
|
||||
return frappe.get_doc('Lead', test_lead[0][0])
|
||||
test_lead = frappe.get_doc({
|
||||
|
@ -12,7 +12,8 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller
|
||||
'Opportunity': this.make_opportunity
|
||||
};
|
||||
|
||||
this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead);
|
||||
// For avoiding integration issues.
|
||||
this.frm.set_df_property('first_name', 'reqd', true);
|
||||
}
|
||||
|
||||
onload () {
|
||||
@ -42,6 +43,7 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller
|
||||
|
||||
if (!this.frm.is_new()) {
|
||||
frappe.contacts.render_address_and_contact(this.frm);
|
||||
cur_frm.trigger('render_contact_day_html');
|
||||
} else {
|
||||
frappe.contacts.clear_address_and_contact(this.frm);
|
||||
}
|
||||
@ -68,13 +70,8 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller
|
||||
})
|
||||
}
|
||||
|
||||
organization_lead () {
|
||||
this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead);
|
||||
this.frm.toggle_reqd("company_name", this.frm.doc.organization_lead);
|
||||
}
|
||||
|
||||
company_name () {
|
||||
if (this.frm.doc.organization_lead && !this.frm.doc.lead_name) {
|
||||
if (!this.frm.doc.lead_name) {
|
||||
this.frm.set_value("lead_name", this.frm.doc.company_name);
|
||||
}
|
||||
}
|
||||
@ -86,6 +83,19 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller
|
||||
this.frm.set_value("ends_on", d.format(frappe.defaultDatetimeFormat));
|
||||
}
|
||||
}
|
||||
|
||||
render_contact_day_html() {
|
||||
if (cur_frm.doc.contact_date) {
|
||||
let contact_date = frappe.datetime.obj_to_str(cur_frm.doc.contact_date);
|
||||
let diff_days = frappe.datetime.get_day_diff(contact_date, frappe.datetime.get_today());
|
||||
let color = diff_days > 0 ? "orange" : "green";
|
||||
let message = diff_days > 0 ? __("Next Contact Date") : __("Last Contact Date");
|
||||
let html = `<div class="col-xs-12">
|
||||
<span class="indicator whitespace-nowrap ${color}"><span> ${message} : ${frappe.datetime.global_date_format(contact_date)}</span></span>
|
||||
</div>` ;
|
||||
cur_frm.dashboard.set_headline_alert(html);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extend_cscript(cur_frm.cscript, new erpnext.LeadController({ frm: cur_frm }));
|
||||
|
@ -9,71 +9,70 @@
|
||||
"email_append_to": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"organization_lead",
|
||||
"lead_details",
|
||||
"naming_series",
|
||||
"lead_name",
|
||||
"company_name",
|
||||
"email_id",
|
||||
"col_break123",
|
||||
"lead_owner",
|
||||
"status",
|
||||
"salutation",
|
||||
"first_name",
|
||||
"middle_name",
|
||||
"last_name",
|
||||
"lead_name",
|
||||
"col_break123",
|
||||
"status",
|
||||
"company_name",
|
||||
"designation",
|
||||
"gender",
|
||||
"source",
|
||||
"customer",
|
||||
"campaign_name",
|
||||
"image",
|
||||
"section_break_12",
|
||||
"contact_by",
|
||||
"column_break_14",
|
||||
"contact_date",
|
||||
"ends_on",
|
||||
"notes_section",
|
||||
"notes",
|
||||
"address_info",
|
||||
"contact_details_section",
|
||||
"email_id",
|
||||
"mobile_no",
|
||||
"whatsapp_no",
|
||||
"column_break_16",
|
||||
"phone",
|
||||
"phone_ext",
|
||||
"additional_information_section",
|
||||
"no_of_employees",
|
||||
"industry",
|
||||
"market_segment",
|
||||
"column_break_22",
|
||||
"fax",
|
||||
"website",
|
||||
"type",
|
||||
"request_type",
|
||||
"address_section",
|
||||
"address_html",
|
||||
"address_type",
|
||||
"address_title",
|
||||
"address_line1",
|
||||
"address_line2",
|
||||
"city",
|
||||
"pincode",
|
||||
"county",
|
||||
"column_break2",
|
||||
"contact_html",
|
||||
"state",
|
||||
"country",
|
||||
"pincode",
|
||||
"contact_section",
|
||||
"phone",
|
||||
"mobile_no",
|
||||
"fax",
|
||||
"website",
|
||||
"more_info",
|
||||
"type",
|
||||
"market_segment",
|
||||
"industry",
|
||||
"request_type",
|
||||
"column_break3",
|
||||
"section_break_12",
|
||||
"lead_owner",
|
||||
"ends_on",
|
||||
"column_break_14",
|
||||
"contact_by",
|
||||
"contact_date",
|
||||
"lead_source_details_section",
|
||||
"company",
|
||||
"territory",
|
||||
"language",
|
||||
"column_break_50",
|
||||
"source",
|
||||
"campaign_name",
|
||||
"unsubscribed",
|
||||
"blog_subscriber",
|
||||
"notes_section",
|
||||
"notes",
|
||||
"other_information_section",
|
||||
"customer",
|
||||
"image",
|
||||
"title"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "organization_lead",
|
||||
"fieldtype": "Check",
|
||||
"label": "Lead is an Organization",
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "lead_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Lead Details",
|
||||
"options": "fa fa-user"
|
||||
},
|
||||
{
|
||||
@ -90,16 +89,19 @@
|
||||
"fieldname": "lead_name",
|
||||
"fieldtype": "Data",
|
||||
"in_global_search": 1,
|
||||
"label": "Person Name",
|
||||
"label": "Full Name",
|
||||
"oldfieldname": "lead_name",
|
||||
"oldfieldtype": "Data",
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "company_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Organization Name",
|
||||
"mandatory_depends_on": "eval: !(doc.first_name)",
|
||||
"oldfieldname": "company_name",
|
||||
"oldfieldtype": "Data"
|
||||
},
|
||||
@ -121,7 +123,6 @@
|
||||
"default": "__user",
|
||||
"fieldname": "lead_owner",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Lead Owner",
|
||||
"oldfieldname": "lead_owner",
|
||||
"oldfieldtype": "Link",
|
||||
@ -143,7 +144,6 @@
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "salutation",
|
||||
"fieldtype": "Link",
|
||||
"label": "Salutation",
|
||||
@ -241,46 +241,22 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"description": "Home, Work, etc.",
|
||||
"fieldname": "address_title",
|
||||
"fieldtype": "Data",
|
||||
"label": "Address Title"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "address_line1",
|
||||
"fieldtype": "Data",
|
||||
"label": "Address Line 1",
|
||||
"mandatory_depends_on": "eval: doc.address_title && doc.address_type"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "address_line2",
|
||||
"fieldtype": "Data",
|
||||
"label": "Address Line 2"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "city",
|
||||
"fieldtype": "Data",
|
||||
"label": "City/Town",
|
||||
"mandatory_depends_on": "eval: doc.address_title && doc.address_type"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "county",
|
||||
"fieldtype": "Data",
|
||||
"label": "County"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "state",
|
||||
"fieldtype": "Data",
|
||||
"label": "State"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "country",
|
||||
"fieldtype": "Link",
|
||||
"label": "Country",
|
||||
@ -288,7 +264,6 @@
|
||||
"options": "Country"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "pincode",
|
||||
"fieldtype": "Data",
|
||||
"label": "Postal Code"
|
||||
@ -304,7 +279,6 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "phone",
|
||||
"fieldtype": "Data",
|
||||
"label": "Phone",
|
||||
@ -313,7 +287,6 @@
|
||||
"options": "Phone"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "mobile_no",
|
||||
"fieldtype": "Data",
|
||||
"label": "Mobile No.",
|
||||
@ -322,21 +295,12 @@
|
||||
"options": "Phone"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "fax",
|
||||
"fieldtype": "Data",
|
||||
"label": "Fax",
|
||||
"oldfieldname": "fax",
|
||||
"oldfieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "more_info",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "More Information",
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "fa fa-file-text"
|
||||
},
|
||||
{
|
||||
"fieldname": "type",
|
||||
"fieldtype": "Select",
|
||||
@ -369,12 +333,6 @@
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nProduct Enquiry\nRequest for Information\nSuggestions\nOther"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break3",
|
||||
"fieldtype": "Column Break",
|
||||
"oldfieldtype": "Column Break",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
@ -389,11 +347,14 @@
|
||||
"fieldtype": "Data",
|
||||
"label": "Website",
|
||||
"oldfieldname": "website",
|
||||
"oldfieldtype": "Data"
|
||||
"oldfieldtype": "Data",
|
||||
"options": "URL"
|
||||
},
|
||||
{
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Territory",
|
||||
"oldfieldname": "territory",
|
||||
"oldfieldtype": "Link",
|
||||
@ -422,45 +383,95 @@
|
||||
{
|
||||
"fieldname": "designation",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Designation",
|
||||
"options": "Designation"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "address_info",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Address & Contact",
|
||||
"oldfieldtype": "Column Break",
|
||||
"options": "fa fa-map-marker"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "contact_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Contact"
|
||||
},
|
||||
{
|
||||
"default": "Billing",
|
||||
"depends_on": "eval: doc.__islocal",
|
||||
"fieldname": "address_type",
|
||||
"fieldtype": "Select",
|
||||
"label": "Address Type",
|
||||
"options": "Billing\nShipping\nOffice\nPersonal\nPlant\nPostal\nShop\nSubsidiary\nWarehouse\nCurrent\nPermanent\nOther"
|
||||
},
|
||||
{
|
||||
"fieldname": "language",
|
||||
"fieldtype": "Link",
|
||||
"label": "Print Language",
|
||||
"options": "Language"
|
||||
},
|
||||
{
|
||||
"fieldname": "first_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "First Name",
|
||||
"mandatory_depends_on": "eval: !(doc.company_name)"
|
||||
},
|
||||
{
|
||||
"fieldname": "middle_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Middle Name"
|
||||
},
|
||||
{
|
||||
"fieldname": "last_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Last Name"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "additional_information_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Additional Information"
|
||||
},
|
||||
{
|
||||
"fieldname": "no_of_employees",
|
||||
"fieldtype": "Int",
|
||||
"label": "No. of Employees"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_22",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "whatsapp_no",
|
||||
"fieldtype": "Data",
|
||||
"label": "WhatsApp No.",
|
||||
"options": "Phone"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"depends_on": "eval: !doc.__islocal",
|
||||
"fieldname": "address_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Address"
|
||||
},
|
||||
{
|
||||
"fieldname": "lead_source_details_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Lead Source Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_50",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "other_information_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Other Information"
|
||||
},
|
||||
{
|
||||
"fieldname": "contact_details_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Contact Details"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_16",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "phone_ext",
|
||||
"fieldtype": "Data",
|
||||
"label": "Phone Ext."
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-user",
|
||||
"idx": 5,
|
||||
"image_field": "image",
|
||||
"links": [],
|
||||
"modified": "2021-01-06 19:39:58.748978",
|
||||
"modified": "2021-08-04 00:24:57.208590",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Lead",
|
||||
|
@ -21,26 +21,24 @@ class Lead(SellingController):
|
||||
self.get("__onload").is_customer = customer
|
||||
load_address_and_contact(self)
|
||||
|
||||
def before_insert(self):
|
||||
if self.address_title and self.address_type:
|
||||
self.address_doc = self.create_address()
|
||||
self.contact_doc = self.create_contact()
|
||||
|
||||
def after_insert(self):
|
||||
self.update_links()
|
||||
|
||||
def validate(self):
|
||||
self.set_full_name()
|
||||
self.set_lead_name()
|
||||
self.set_title()
|
||||
self.set_status()
|
||||
self.check_email_id_is_unique()
|
||||
self.validate_email_id()
|
||||
self.validate_contact_date()
|
||||
self._prev = frappe._dict({
|
||||
"contact_date": frappe.db.get_value("Lead", self.name, "contact_date") if (not cint(self.is_new())) else None,
|
||||
"ends_on": frappe.db.get_value("Lead", self.name, "ends_on") if (not cint(self.is_new())) else None,
|
||||
"contact_by": frappe.db.get_value("Lead", self.name, "contact_by") if (not cint(self.is_new())) else None,
|
||||
})
|
||||
|
||||
def set_full_name(self):
|
||||
self.lead_name = " ".join(filter(None, [self.first_name, self.middle_name, self.last_name]))
|
||||
|
||||
self.set_status()
|
||||
self.check_email_id_is_unique()
|
||||
|
||||
def validate_email_id(self):
|
||||
if self.email_id:
|
||||
if not self.flags.ignore_email_validation:
|
||||
validate_email_address(self.email_id, throw=True)
|
||||
@ -54,6 +52,7 @@ class Lead(SellingController):
|
||||
if self.is_new() or not self.image:
|
||||
self.image = has_gravatar(self.email_id)
|
||||
|
||||
def validate_contact_date(self):
|
||||
if self.contact_date and getdate(self.contact_date) < getdate(nowdate()):
|
||||
frappe.throw(_("Next Contact Date cannot be in the past"))
|
||||
|
||||
@ -64,6 +63,22 @@ class Lead(SellingController):
|
||||
def on_update(self):
|
||||
self.add_calendar_event()
|
||||
|
||||
def before_insert(self):
|
||||
self.contact_doc = self.create_contact()
|
||||
|
||||
def after_insert(self):
|
||||
self.update_links()
|
||||
|
||||
def update_links(self):
|
||||
# update contact links
|
||||
if self.contact_doc:
|
||||
self.contact_doc.append("links", {
|
||||
"link_doctype": "Lead",
|
||||
"link_name": self.name,
|
||||
"link_title": self.lead_name
|
||||
})
|
||||
self.contact_doc.save()
|
||||
|
||||
def add_calendar_event(self, opts=None, force=False):
|
||||
super(Lead, self).add_calendar_event({
|
||||
"owner": self.lead_owner,
|
||||
@ -86,8 +101,26 @@ class Lead(SellingController):
|
||||
def on_trash(self):
|
||||
frappe.db.sql("""update `tabIssue` set lead='' where lead=%s""", self.name)
|
||||
|
||||
self.unlink_dynamic_links()
|
||||
self.delete_events()
|
||||
|
||||
def unlink_dynamic_links(self):
|
||||
links = frappe.get_all('Dynamic Link', filters={'link_doctype': self.doctype, 'link_name': self.name}, fields=['parent', 'parenttype'])
|
||||
|
||||
for link in links:
|
||||
linked_doc = frappe.get_doc(link['parenttype'], link['parent'])
|
||||
|
||||
if len(linked_doc.get('links')) == 1:
|
||||
linked_doc.delete(ignore_permissions=True)
|
||||
else:
|
||||
to_remove = None
|
||||
for d in linked_doc.get('links'):
|
||||
if d.link_doctype == self.doctype and d.link_name == self.name:
|
||||
to_remove = d
|
||||
if to_remove:
|
||||
linked_doc.remove(to_remove)
|
||||
linked_doc.save(ignore_permissions=True)
|
||||
|
||||
def has_customer(self):
|
||||
return frappe.db.get_value("Customer", {"lead_name": self.name})
|
||||
|
||||
@ -99,7 +132,6 @@ class Lead(SellingController):
|
||||
"party_name": self.name,
|
||||
"docstatus": 1,
|
||||
"status": ["!=", "Lost"]
|
||||
|
||||
})
|
||||
|
||||
def has_lost_quotation(self):
|
||||
@ -120,40 +152,17 @@ class Lead(SellingController):
|
||||
self.lead_name = self.email_id.split("@")[0]
|
||||
|
||||
def set_title(self):
|
||||
if self.organization_lead:
|
||||
self.title = self.company_name
|
||||
else:
|
||||
self.title = self.lead_name
|
||||
|
||||
def create_address(self):
|
||||
address_fields = ["address_type", "address_title", "address_line1", "address_line2",
|
||||
"city", "county", "state", "country", "pincode"]
|
||||
info_fields = ["email_id", "phone", "fax"]
|
||||
|
||||
# do not create an address if no fields are available,
|
||||
# skipping country since the system auto-sets it from system defaults
|
||||
address = frappe.new_doc("Address")
|
||||
|
||||
address.update({addr_field: self.get(addr_field) for addr_field in address_fields})
|
||||
address.update({info_field: self.get(info_field) for info_field in info_fields})
|
||||
address.insert()
|
||||
|
||||
return address
|
||||
self.title = self.company_name or self.lead_name
|
||||
|
||||
def create_contact(self):
|
||||
if not self.lead_name:
|
||||
self.set_full_name()
|
||||
self.set_lead_name()
|
||||
|
||||
names = self.lead_name.strip().split(" ")
|
||||
if len(names) > 1:
|
||||
first_name, last_name = names[0], " ".join(names[1:])
|
||||
else:
|
||||
first_name, last_name = self.lead_name, None
|
||||
|
||||
contact = frappe.new_doc("Contact")
|
||||
contact.update({
|
||||
"first_name": first_name,
|
||||
"last_name": last_name,
|
||||
"first_name": self.first_name or self.lead_name,
|
||||
"last_name": self.last_name,
|
||||
"salutation": self.salutation,
|
||||
"gender": self.gender,
|
||||
"designation": self.designation,
|
||||
@ -181,25 +190,6 @@ class Lead(SellingController):
|
||||
|
||||
return contact
|
||||
|
||||
def update_links(self):
|
||||
# update address links
|
||||
if hasattr(self, 'address_doc'):
|
||||
self.address_doc.append("links", {
|
||||
"link_doctype": "Lead",
|
||||
"link_name": self.name,
|
||||
"link_title": self.lead_name
|
||||
})
|
||||
self.address_doc.save()
|
||||
|
||||
# update contact links
|
||||
if self.contact_doc:
|
||||
self.contact_doc.append("links", {
|
||||
"link_doctype": "Lead",
|
||||
"link_name": self.name,
|
||||
"link_title": self.lead_name
|
||||
})
|
||||
self.contact_doc.save()
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_customer(source_name, target_doc=None):
|
||||
return _make_customer(source_name, target_doc)
|
||||
|
@ -4,6 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
from frappe.utils import random_string
|
||||
import unittest
|
||||
|
||||
test_records = frappe.get_test_records('Lead')
|
||||
@ -32,3 +33,53 @@ class TestLead(unittest.TestCase):
|
||||
customer.company = "_Test Company"
|
||||
customer.customer_group = "_Test Customer Group"
|
||||
customer.insert()
|
||||
|
||||
def test_create_lead_and_unlinking_dynamic_links(self):
|
||||
lead_doc = make_lead(first_name = "Lorem", last_name="Ipsum", email_id="lorem_ipsum@example.com")
|
||||
lead_doc_1 = make_lead()
|
||||
frappe.get_doc({
|
||||
"doctype": "Address",
|
||||
"address_type": "Billing",
|
||||
"city": "Mumbai",
|
||||
"address_line1": "Vidya Vihar West",
|
||||
"country": "India",
|
||||
"links": [{
|
||||
"link_doctype": "Lead",
|
||||
"link_name": lead_doc.name
|
||||
}]
|
||||
}).insert()
|
||||
|
||||
address_1 = frappe.get_doc({
|
||||
"doctype": "Address",
|
||||
"address_type": "Billing",
|
||||
"address_line1": "Baner",
|
||||
"city": "Pune",
|
||||
"country": "India",
|
||||
"links": [
|
||||
{
|
||||
"link_doctype": "Lead",
|
||||
"link_name": lead_doc.name
|
||||
},
|
||||
{
|
||||
"link_doctype": "Lead",
|
||||
"link_name": lead_doc_1.name
|
||||
}
|
||||
]
|
||||
}).insert()
|
||||
|
||||
lead_doc.delete()
|
||||
address_1.reload()
|
||||
self.assertEqual(frappe.db.exists("Lead",lead_doc.name), None)
|
||||
self.assertEqual(len(address_1.get('links')), 1)
|
||||
|
||||
def make_lead(**args):
|
||||
args = frappe._dict(args)
|
||||
|
||||
lead_doc = frappe.get_doc({
|
||||
"doctype": "Lead",
|
||||
"first_name": args.first_name or "_Test",
|
||||
"last_name": args.last_name or "Lead",
|
||||
"email_id": args.email_id or "new_lead_{}@example.com".format(random_string(5)),
|
||||
}).insert()
|
||||
|
||||
return lead_doc
|
@ -27,7 +27,6 @@
|
||||
{
|
||||
"doctype": "Lead",
|
||||
"email_id": "test_lead4@example.com",
|
||||
"organization_lead": 1,
|
||||
"lead_name": "_Test Lead 4",
|
||||
"company_name": "_Test Lead 4",
|
||||
"status": "Open"
|
||||
|
@ -9,7 +9,6 @@ QUnit.test("test: lead", function (assert) {
|
||||
() => frappe.set_route("List", "Lead"),
|
||||
() => frappe.new_doc("Lead"),
|
||||
() => frappe.timeout(1),
|
||||
() => cur_frm.set_value("organization_lead", "1"),
|
||||
() => cur_frm.set_value("company_name", lead_name),
|
||||
() => cur_frm.save(),
|
||||
() => frappe.timeout(1),
|
||||
|
@ -294,7 +294,8 @@ erpnext.patches.v13_0.update_level_in_bom #1234sswef
|
||||
erpnext.patches.v13_0.add_missing_fg_item_for_stock_entry
|
||||
erpnext.patches.v13_0.update_subscription_status_in_memberships
|
||||
erpnext.patches.v13_0.update_amt_in_work_order_required_items
|
||||
erpnext.patches.v13_0.delete_orphaned_tables
|
||||
erpnext.patches.v13_0.update_export_type_for_gst
|
||||
erpnext.patches.v13_0.update_tds_check_field #3
|
||||
erpnext.patches.v13_0.add_custom_field_for_south_africa
|
||||
erpnext.patches.v13_0.add_custom_field_for_south_africa #2
|
||||
erpnext.patches.v13_0.shopify_deprecation_warning
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from erpnext.regional.south_africa.setup import make_custom_fields
|
||||
from erpnext.regional.south_africa.setup import make_custom_fields, add_permissions
|
||||
|
||||
def execute():
|
||||
company = frappe.get_all('Company', filters = {'country': 'South Africa'})
|
||||
@ -11,3 +11,4 @@ def execute():
|
||||
return
|
||||
|
||||
make_custom_fields()
|
||||
add_permissions()
|
||||
|
69
erpnext/patches/v13_0/delete_orphaned_tables.py
Normal file
69
erpnext/patches/v13_0/delete_orphaned_tables.py
Normal file
@ -0,0 +1,69 @@
|
||||
# Copyright (c) 2019, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
from frappe.utils import getdate
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('setup', 'doctype', 'transaction_deletion_record')
|
||||
|
||||
if has_deleted_company_transactions():
|
||||
child_doctypes = get_child_doctypes_whose_parent_doctypes_were_affected()
|
||||
|
||||
for doctype in child_doctypes:
|
||||
docs = frappe.get_all(doctype, fields=['name', 'parent', 'parenttype', 'creation'])
|
||||
|
||||
for doc in docs:
|
||||
if not frappe.db.exists(doc['parenttype'], doc['parent']):
|
||||
frappe.db.delete(doctype, {'name': doc['name']})
|
||||
|
||||
elif check_for_new_doc_with_same_name_as_deleted_parent(doc):
|
||||
frappe.db.delete(doctype, {'name': doc['name']})
|
||||
|
||||
def has_deleted_company_transactions():
|
||||
return frappe.get_all('Transaction Deletion Record')
|
||||
|
||||
def get_child_doctypes_whose_parent_doctypes_were_affected():
|
||||
parent_doctypes = get_affected_doctypes()
|
||||
child_doctypes = frappe.get_all(
|
||||
'DocField',
|
||||
filters={
|
||||
'fieldtype': 'Table',
|
||||
'parent':['in', parent_doctypes]
|
||||
}, pluck='options')
|
||||
|
||||
return child_doctypes
|
||||
|
||||
def get_affected_doctypes():
|
||||
affected_doctypes = []
|
||||
tdr_docs = frappe.get_all('Transaction Deletion Record', pluck="name")
|
||||
|
||||
for tdr in tdr_docs:
|
||||
tdr_doc = frappe.get_doc("Transaction Deletion Record", tdr)
|
||||
|
||||
for doctype in tdr_doc.doctypes:
|
||||
if is_not_child_table(doctype.doctype_name):
|
||||
affected_doctypes.append(doctype.doctype_name)
|
||||
|
||||
affected_doctypes = remove_duplicate_items(affected_doctypes)
|
||||
return affected_doctypes
|
||||
|
||||
def is_not_child_table(doctype):
|
||||
return not bool(frappe.get_value('DocType', doctype, 'istable'))
|
||||
|
||||
def remove_duplicate_items(affected_doctypes):
|
||||
return list(set(affected_doctypes))
|
||||
|
||||
def check_for_new_doc_with_same_name_as_deleted_parent(doc):
|
||||
"""
|
||||
Compares creation times of parent and child docs.
|
||||
Since Transaction Deletion Record resets the naming series after deletion,
|
||||
it allows the creation of new docs with the same names as the deleted ones.
|
||||
"""
|
||||
|
||||
parent_creation_time = frappe.db.get_value(doc['parenttype'], doc['parent'], 'creation')
|
||||
child_creation_time = doc['creation']
|
||||
|
||||
return getdate(parent_creation_time) > getdate(child_creation_time)
|
@ -928,7 +928,7 @@ class GSPConnector():
|
||||
|
||||
def set_einvoice_data(self, res):
|
||||
enc_signed_invoice = res.get('SignedInvoice')
|
||||
dec_signed_invoice = jwt.decode(enc_signed_invoice, verify=False)['data']
|
||||
dec_signed_invoice = jwt.decode(enc_signed_invoice, options={"verify_signature": False})['data']
|
||||
|
||||
self.invoice.irn = res.get('Irn')
|
||||
self.invoice.ewaybill = res.get('EwbNo')
|
||||
@ -1126,4 +1126,4 @@ def check_scheduler_status():
|
||||
def job_already_enqueued(job_name):
|
||||
enqueued_jobs = [d.get("job_name") for d in get_info()]
|
||||
if job_name in enqueued_jobs:
|
||||
return True
|
||||
return True
|
||||
|
@ -18,15 +18,5 @@
|
||||
"ref_doctype": "GL Entry",
|
||||
"report_name": "VAT Audit Report",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Accounts User"
|
||||
},
|
||||
{
|
||||
"role": "Accounts Manager"
|
||||
},
|
||||
{
|
||||
"role": "Auditor"
|
||||
}
|
||||
]
|
||||
"roles": []
|
||||
}
|
@ -189,6 +189,8 @@ class VATAuditReport(object):
|
||||
row["posting_date"] = formatdate(inv_data.get("posting_date"), "dd-mm-yyyy")
|
||||
row["voucher_type"] = doctype
|
||||
row["voucher_no"] = inv
|
||||
row["party_type"] = "Customer" if doctype == "Sales Invoice" else "Supplier"
|
||||
row["party"] = inv_data.get("party")
|
||||
row["remarks"] = inv_data.get("remarks")
|
||||
row["gross_amount"]= item_details[0].get("gross_amount")
|
||||
row["tax_amount"]= item_details[0].get("tax_amount")
|
||||
@ -226,6 +228,20 @@ class VATAuditReport(object):
|
||||
"options": "voucher_type",
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"fieldname": "party_type",
|
||||
"label": "Party Type",
|
||||
"fieldtype": "Data",
|
||||
"width": 140,
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "party",
|
||||
"label": "Party",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"options": "party_type",
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"fieldname": "remarks",
|
||||
"label": "Details",
|
||||
@ -236,18 +252,18 @@ class VATAuditReport(object):
|
||||
"fieldname": "net_amount",
|
||||
"label": "Net Amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 150
|
||||
"width": 130
|
||||
},
|
||||
{
|
||||
"fieldname": "tax_amount",
|
||||
"label": "Tax Amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 150
|
||||
"width": 130
|
||||
},
|
||||
{
|
||||
"fieldname": "gross_amount",
|
||||
"label": "Gross Amount",
|
||||
"fieldtype": "Currency",
|
||||
"width": 150
|
||||
"width": 130
|
||||
},
|
||||
]
|
||||
|
@ -3,11 +3,12 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe, os, json
|
||||
import frappe
|
||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
||||
from frappe.permissions import add_permission, update_permission_property
|
||||
|
||||
def setup(company=None, patch=True):
|
||||
make_custom_fields()
|
||||
add_permissions()
|
||||
|
||||
def make_custom_fields(update=True):
|
||||
@ -27,10 +28,23 @@ def make_custom_fields(update=True):
|
||||
create_custom_fields(custom_fields, update=update)
|
||||
|
||||
def add_permissions():
|
||||
"""Add Permissions for South Africa VAT Settings and South Africa VAT Account"""
|
||||
"""Add Permissions for South Africa VAT Settings and South Africa VAT Account
|
||||
and VAT Audit Report"""
|
||||
for doctype in ('South Africa VAT Settings', 'South Africa VAT Account'):
|
||||
add_permission(doctype, 'All', 0)
|
||||
for role in ('Accounts Manager', 'Accounts User', 'System Manager'):
|
||||
add_permission(doctype, role, 0)
|
||||
update_permission_property(doctype, role, 0, 'write', 1)
|
||||
update_permission_property(doctype, role, 0, 'create', 1)
|
||||
update_permission_property(doctype, role, 0, 'create', 1)
|
||||
|
||||
|
||||
if not frappe.db.get_value('Custom Role', dict(report="VAT Audit Report")):
|
||||
frappe.get_doc(dict(
|
||||
doctype='Custom Role',
|
||||
report="VAT Audit Report",
|
||||
roles= [
|
||||
dict(role='Accounts User'),
|
||||
dict(role='Accounts Manager'),
|
||||
dict(role='Auditor')
|
||||
]
|
||||
)).insert()
|
@ -157,9 +157,7 @@ class Customer(TransactionBase):
|
||||
'''If Customer created from Lead, update lead status to "Converted"
|
||||
update Customer link in Quotation, Opportunity'''
|
||||
if self.lead_name:
|
||||
lead = frappe.get_doc('Lead', self.lead_name)
|
||||
lead.status = 'Converted'
|
||||
lead.save()
|
||||
frappe.db.set_value("Lead", self.lead_name, "status", "Converted")
|
||||
|
||||
def create_lead_address_contact(self):
|
||||
if self.lead_name:
|
||||
@ -176,12 +174,12 @@ class Customer(TransactionBase):
|
||||
address.append('links', dict(link_doctype='Customer', link_name=self.name))
|
||||
address.save(ignore_permissions=self.flags.ignore_permissions)
|
||||
|
||||
lead = frappe.db.get_value("Lead", self.lead_name, ["organization_lead", "lead_name", "email_id", "phone", "mobile_no", "gender", "salutation"], as_dict=True)
|
||||
lead = frappe.db.get_value("Lead", self.lead_name, ["company_name", "lead_name", "email_id", "phone", "mobile_no", "gender", "salutation"], as_dict=True)
|
||||
|
||||
if not lead.lead_name:
|
||||
frappe.throw(_("Please mention the Lead Name in Lead {0}").format(self.lead_name))
|
||||
|
||||
if lead.organization_lead:
|
||||
if lead.company_name:
|
||||
contact_names = frappe.get_all('Dynamic Link', filters={
|
||||
"parenttype":"Contact",
|
||||
"link_doctype":"Lead",
|
||||
|
@ -6,24 +6,31 @@
|
||||
"document_type": "Other",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"customer_defaults_section",
|
||||
"cust_master_name",
|
||||
"campaign_naming_by",
|
||||
"customer_group",
|
||||
"column_break_4",
|
||||
"territory",
|
||||
"selling_price_list",
|
||||
"close_opportunity_after_days",
|
||||
"crm_settings_section",
|
||||
"campaign_naming_by",
|
||||
"default_valid_till",
|
||||
"column_break_5",
|
||||
"column_break_9",
|
||||
"close_opportunity_after_days",
|
||||
"item_price_settings_section",
|
||||
"selling_price_list",
|
||||
"column_break_15",
|
||||
"maintain_same_sales_rate",
|
||||
"maintain_same_rate_action",
|
||||
"editable_price_list_rate",
|
||||
"validate_selling_price",
|
||||
"sales_transactions_settings_section",
|
||||
"so_required",
|
||||
"dn_required",
|
||||
"sales_update_frequency",
|
||||
"maintain_same_sales_rate",
|
||||
"maintain_same_rate_action",
|
||||
"column_break_5",
|
||||
"role_to_override_stop_action",
|
||||
"editable_price_list_rate",
|
||||
"allow_multiple_items",
|
||||
"allow_against_multiple_purchase_orders",
|
||||
"validate_selling_price",
|
||||
"hide_tax_id"
|
||||
],
|
||||
"fields": [
|
||||
@ -116,7 +123,7 @@
|
||||
"default": "0",
|
||||
"fieldname": "allow_multiple_items",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow Item to Be Added Multiple Times in a Transaction"
|
||||
"label": "Allow Item to be Added Multiple Times in a Transaction"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
@ -142,7 +149,7 @@
|
||||
"description": "Configure the action to stop the transaction or just warn if the same rate is not maintained.",
|
||||
"fieldname": "maintain_same_rate_action",
|
||||
"fieldtype": "Select",
|
||||
"label": "Action If Same Rate is Not Maintained",
|
||||
"label": "Action if Same Rate is Not Maintained",
|
||||
"mandatory_depends_on": "maintain_same_sales_rate",
|
||||
"options": "Stop\nWarn"
|
||||
},
|
||||
@ -152,6 +159,38 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Role Allowed to Override Stop Action",
|
||||
"options": "Role"
|
||||
},
|
||||
{
|
||||
"fieldname": "customer_defaults_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Customer Defaults"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "crm_settings_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "CRM Settings"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "item_price_settings_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Item Price Settings"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_15",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "sales_transactions_settings_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Transaction Settings"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-cog",
|
||||
@ -159,7 +198,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2021-04-04 20:18:12.814624",
|
||||
"modified": "2021-08-06 22:25:50.119458",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Selling Settings",
|
||||
|
@ -47,7 +47,8 @@
|
||||
"description": "Simple Python formula applied on Reading fields.<br> Numeric eg. 1: <b>reading_1 > 0.2 and reading_1 < 0.5</b><br>\nNumeric eg. 2: <b>mean > 3.5</b> (mean of populated fields)<br>\nValue based eg.: <b>reading_value in (\"A\", \"B\", \"C\")</b>",
|
||||
"fieldname": "acceptance_formula",
|
||||
"fieldtype": "Code",
|
||||
"label": "Acceptance Criteria Formula"
|
||||
"label": "Acceptance Criteria Formula",
|
||||
"options": "PythonExpression"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
@ -89,7 +90,7 @@
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-02-04 18:50:02.056173",
|
||||
"modified": "2021-08-06 15:08:20.911338",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Item Quality Inspection Parameter",
|
||||
|
@ -11,6 +11,7 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \
|
||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
||||
from erpnext.accounts.doctype.account.test_account import create_account
|
||||
from erpnext.assets.doctype.asset.test_asset import create_asset_category, create_fixed_asset_item
|
||||
|
||||
class TestLandedCostVoucher(unittest.TestCase):
|
||||
def test_landed_cost_voucher(self):
|
||||
@ -250,6 +251,38 @@ class TestLandedCostVoucher(unittest.TestCase):
|
||||
self.assertEqual(entry.credit, amounts[0])
|
||||
self.assertEqual(entry.credit_in_account_currency, amounts[1])
|
||||
|
||||
def test_asset_lcv(self):
|
||||
"Check if LCV for an Asset updates the Assets Gross Purchase Amount correctly."
|
||||
if not frappe.db.exists("Asset Category", "Computers"):
|
||||
create_asset_category()
|
||||
|
||||
if not frappe.db.exists("Item", "Macbook Pro"):
|
||||
create_fixed_asset_item()
|
||||
|
||||
pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=50000)
|
||||
|
||||
# check if draft asset was created
|
||||
assets = frappe.db.get_all('Asset', filters={'purchase_receipt': pr.name})
|
||||
self.assertEqual(len(assets), 1)
|
||||
|
||||
frappe.db.set_value("Company", pr.company, "capital_work_in_progress_account", "CWIP Account - _TC")
|
||||
lcv = make_landed_cost_voucher(
|
||||
company = pr.company,
|
||||
receipt_document_type = "Purchase Receipt",
|
||||
receipt_document=pr.name,
|
||||
charges=80,
|
||||
expense_account="Expenses Included In Valuation - _TC")
|
||||
|
||||
lcv.save()
|
||||
lcv.submit()
|
||||
|
||||
# lcv updates amount in draft asset
|
||||
self.assertEqual(frappe.db.get_value("Asset", assets[0].name, "gross_purchase_amount"), 50080)
|
||||
|
||||
# tear down
|
||||
lcv.cancel()
|
||||
pr.cancel()
|
||||
|
||||
def make_landed_cost_voucher(** args):
|
||||
args = frappe._dict(args)
|
||||
ref_doc = frappe.get_doc(args.receipt_document_type, args.receipt_document)
|
||||
@ -268,7 +301,7 @@ def make_landed_cost_voucher(** args):
|
||||
|
||||
lcv.set("taxes", [{
|
||||
"description": "Shipping Charges",
|
||||
"expense_account": "Expenses Included In Valuation - TCP1",
|
||||
"expense_account": args.expense_account or "Expenses Included In Valuation - TCP1",
|
||||
"amount": args.charges
|
||||
}])
|
||||
|
||||
|
@ -290,8 +290,16 @@ class PurchaseReceipt(BuyingController):
|
||||
and warehouse_account_name == supplier_warehouse_account:
|
||||
continue
|
||||
|
||||
self.add_gl_entry(gl_entries, warehouse_account_name, d.cost_center, stock_value_diff, 0.0, remarks,
|
||||
stock_rbnb, account_currency=warehouse_account_currency, item=d)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=warehouse_account_name,
|
||||
cost_center=d.cost_center,
|
||||
debit=stock_value_diff,
|
||||
credit=0.0,
|
||||
remarks=remarks,
|
||||
against_account=stock_rbnb,
|
||||
account_currency=warehouse_account_currency,
|
||||
item=d)
|
||||
|
||||
# GL Entry for from warehouse or Stock Received but not billed
|
||||
# Intentionally passed negative debit amount to avoid incorrect GL Entry validation
|
||||
@ -304,9 +312,17 @@ class PurchaseReceipt(BuyingController):
|
||||
account = warehouse_account[d.from_warehouse]['account'] \
|
||||
if d.from_warehouse else stock_rbnb
|
||||
|
||||
self.add_gl_entry(gl_entries, account, d.cost_center,
|
||||
-1 * flt(d.base_net_amount, d.precision("base_net_amount")), 0.0, remarks, warehouse_account_name,
|
||||
debit_in_account_currency=-1 * credit_amount, account_currency=credit_currency, item=d)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=account,
|
||||
cost_center=d.cost_center,
|
||||
debit=-1 * flt(d.base_net_amount, d.precision("base_net_amount")),
|
||||
credit=0.0,
|
||||
remarks=remarks,
|
||||
against_account=warehouse_account_name,
|
||||
debit_in_account_currency=-1 * credit_amount,
|
||||
account_currency=credit_currency,
|
||||
item=d)
|
||||
|
||||
# check if the exchange rate has changed
|
||||
if d.get('purchase_invoice'):
|
||||
@ -317,13 +333,29 @@ class PurchaseReceipt(BuyingController):
|
||||
discrepancy_caused_by_exchange_rate_difference = (d.qty * d.net_rate) * \
|
||||
(exchange_rate_map[d.purchase_invoice] - self.conversion_rate)
|
||||
|
||||
self.add_gl_entry(gl_entries, account, d.cost_center, 0.0, discrepancy_caused_by_exchange_rate_difference,
|
||||
remarks, self.supplier, debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference,
|
||||
account_currency=credit_currency, item=d)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=account,
|
||||
cost_center=d.cost_center,
|
||||
debit=0.0,
|
||||
credit=discrepancy_caused_by_exchange_rate_difference,
|
||||
remarks=remarks,
|
||||
against_account=self.supplier,
|
||||
debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference,
|
||||
account_currency=credit_currency,
|
||||
item=d)
|
||||
|
||||
self.add_gl_entry(gl_entries, self.get_company_default("exchange_gain_loss_account"), d.cost_center, discrepancy_caused_by_exchange_rate_difference, 0.0,
|
||||
remarks, self.supplier, debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference,
|
||||
account_currency=credit_currency, item=d)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=self.get_company_default("exchange_gain_loss_account"),
|
||||
cost_center=d.cost_center,
|
||||
debit=discrepancy_caused_by_exchange_rate_difference,
|
||||
credit=0.0,
|
||||
remarks=remarks,
|
||||
against_account=self.supplier,
|
||||
debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference,
|
||||
account_currency=credit_currency,
|
||||
item=d)
|
||||
|
||||
# Amount added through landed-cos-voucher
|
||||
if d.landed_cost_voucher_amount and landed_cost_entries:
|
||||
@ -332,14 +364,31 @@ class PurchaseReceipt(BuyingController):
|
||||
credit_amount = (flt(amount["base_amount"]) if (amount["base_amount"] or
|
||||
account_currency!=self.company_currency) else flt(amount["amount"]))
|
||||
|
||||
self.add_gl_entry(gl_entries, account, d.cost_center, 0.0, credit_amount, remarks,
|
||||
warehouse_account_name, credit_in_account_currency=flt(amount["amount"]),
|
||||
account_currency=account_currency, project=d.project, item=d)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=account,
|
||||
cost_center=d.cost_center,
|
||||
debit=0.0,
|
||||
credit=credit_amount,
|
||||
remarks=remarks,
|
||||
against_account=warehouse_account_name,
|
||||
credit_in_account_currency=flt(amount["amount"]),
|
||||
account_currency=account_currency,
|
||||
project=d.project,
|
||||
item=d)
|
||||
|
||||
# sub-contracting warehouse
|
||||
if flt(d.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse):
|
||||
self.add_gl_entry(gl_entries, supplier_warehouse_account, d.cost_center, 0.0, flt(d.rm_supp_cost),
|
||||
remarks, warehouse_account_name, account_currency=supplier_warehouse_account_currency, item=d)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=supplier_warehouse_account,
|
||||
cost_center=d.cost_center,
|
||||
debit=0.0,
|
||||
credit=flt(d.rm_supp_cost),
|
||||
remarks=remarks,
|
||||
against_account=warehouse_account_name,
|
||||
account_currency=supplier_warehouse_account_currency,
|
||||
item=d)
|
||||
|
||||
# divisional loss adjustment
|
||||
valuation_amount_as_per_doc = flt(d.base_net_amount, d.precision("base_net_amount")) + \
|
||||
@ -356,8 +405,17 @@ class PurchaseReceipt(BuyingController):
|
||||
|
||||
cost_center = d.cost_center or frappe.get_cached_value("Company", self.company, "cost_center")
|
||||
|
||||
self.add_gl_entry(gl_entries, loss_account, cost_center, divisional_loss, 0.0, remarks,
|
||||
warehouse_account_name, account_currency=credit_currency, project=d.project, item=d)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=loss_account,
|
||||
cost_center=cost_center,
|
||||
debit=divisional_loss,
|
||||
credit=0.0,
|
||||
remarks=remarks,
|
||||
against_account=warehouse_account_name,
|
||||
account_currency=credit_currency,
|
||||
project=d.project,
|
||||
item=d)
|
||||
|
||||
elif d.warehouse not in warehouse_with_no_account or \
|
||||
d.rejected_warehouse not in warehouse_with_no_account:
|
||||
@ -368,12 +426,30 @@ class PurchaseReceipt(BuyingController):
|
||||
debit_currency = get_account_currency(d.expense_account)
|
||||
remarks = self.get("remarks") or _("Accounting Entry for Service")
|
||||
|
||||
self.add_gl_entry(gl_entries, service_received_but_not_billed_account, d.cost_center, 0.0, d.amount,
|
||||
remarks, d.expense_account, account_currency=credit_currency, project=d.project,
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=service_received_but_not_billed_account,
|
||||
cost_center=d.cost_center,
|
||||
debit=0.0,
|
||||
credit=d.amount,
|
||||
remarks=remarks,
|
||||
against_account=d.expense_account,
|
||||
account_currency=credit_currency,
|
||||
project=d.project,
|
||||
voucher_detail_no=d.name, item=d)
|
||||
|
||||
self.add_gl_entry(gl_entries, d.expense_account, d.cost_center, d.amount, 0.0, remarks, service_received_but_not_billed_account,
|
||||
account_currency = debit_currency, project=d.project, voucher_detail_no=d.name, item=d)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=d.expense_account,
|
||||
cost_center=d.cost_center,
|
||||
debit=d.amount,
|
||||
credit=0.0,
|
||||
remarks=remarks,
|
||||
against_account=service_received_but_not_billed_account,
|
||||
account_currency = debit_currency,
|
||||
project=d.project,
|
||||
voucher_detail_no=d.name,
|
||||
item=d)
|
||||
|
||||
if warehouse_with_no_account:
|
||||
frappe.msgprint(_("No accounting entries for the following warehouses") + ": \n" +
|
||||
@ -423,8 +499,15 @@ class PurchaseReceipt(BuyingController):
|
||||
applicable_amount = negative_expense_to_be_booked * (valuation_tax[tax.name] / total_valuation_amount)
|
||||
amount_including_divisional_loss -= applicable_amount
|
||||
|
||||
self.add_gl_entry(gl_entries, account, tax.cost_center, 0.0, applicable_amount, self.remarks or _("Accounting Entry for Stock"),
|
||||
against_account, item=tax)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=account,
|
||||
cost_center=tax.cost_center,
|
||||
debit=0.0,
|
||||
credit=applicable_amount,
|
||||
remarks=self.remarks or _("Accounting Entry for Stock"),
|
||||
against_account=against_account,
|
||||
item=tax)
|
||||
|
||||
i += 1
|
||||
|
||||
@ -477,15 +560,31 @@ class PurchaseReceipt(BuyingController):
|
||||
# debit cwip account
|
||||
debit_in_account_currency = (base_asset_amount
|
||||
if cwip_account_currency == self.company_currency else asset_amount)
|
||||
self.add_gl_entry(gl_entries, cwip_account, item.cost_center, base_asset_amount, 0.0, remarks,
|
||||
arbnb_account, debit_in_account_currency=debit_in_account_currency, item=item)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=cwip_account,
|
||||
cost_center=item.cost_center,
|
||||
debit=base_asset_amount,
|
||||
credit=0.0,
|
||||
remarks=remarks,
|
||||
against_account=arbnb_account,
|
||||
debit_in_account_currency=debit_in_account_currency,
|
||||
item=item)
|
||||
|
||||
asset_rbnb_currency = get_account_currency(arbnb_account)
|
||||
# credit arbnb account
|
||||
credit_in_account_currency = (base_asset_amount
|
||||
if asset_rbnb_currency == self.company_currency else asset_amount)
|
||||
self.add_gl_entry(gl_entries, arbnb_account, item.cost_center, 0.0, base_asset_amount, remarks,
|
||||
cwip_account, credit_in_account_currency=credit_in_account_currency, item=item)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=arbnb_account,
|
||||
cost_center=item.cost_center,
|
||||
debit=0.0,
|
||||
credit=base_asset_amount,
|
||||
remarks=remarks,
|
||||
against_account=cwip_account,
|
||||
credit_in_account_currency=credit_in_account_currency,
|
||||
item=item)
|
||||
|
||||
def add_lcv_gl_entries(self, item, gl_entries):
|
||||
expenses_included_in_asset_valuation = self.get_company_default("expenses_included_in_asset_valuation")
|
||||
@ -498,11 +597,27 @@ class PurchaseReceipt(BuyingController):
|
||||
|
||||
remarks = self.get("remarks") or _("Accounting Entry for Stock")
|
||||
|
||||
self.add_gl_entry(gl_entries, expenses_included_in_asset_valuation, item.cost_center, 0.0, flt(item.landed_cost_voucher_amount),
|
||||
remarks, asset_account, project=item.project, item=item)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=expenses_included_in_asset_valuation,
|
||||
cost_center=item.cost_center,
|
||||
debit=0.0,
|
||||
credit=flt(item.landed_cost_voucher_amount),
|
||||
remarks=remarks,
|
||||
against_account=asset_account,
|
||||
project=item.project,
|
||||
item=item)
|
||||
|
||||
self.add_gl_entry(gl_entries, asset_account, item.cost_center, 0.0, flt(item.landed_cost_voucher_amount),
|
||||
remarks, expenses_included_in_asset_valuation, project=item.project, item=item)
|
||||
self.add_gl_entry(
|
||||
gl_entries=gl_entries,
|
||||
account=asset_account,
|
||||
cost_center=item.cost_center,
|
||||
debit=flt(item.landed_cost_voucher_amount),
|
||||
credit=0.0,
|
||||
remarks=remarks,
|
||||
against_account=expenses_included_in_asset_valuation,
|
||||
project=item.project,
|
||||
item=item)
|
||||
|
||||
def update_assets(self, item, valuation_rate):
|
||||
assets = frappe.db.get_all('Asset',
|
||||
|
@ -324,21 +324,8 @@ class TestPurchaseReceipt(unittest.TestCase):
|
||||
|
||||
pr1.submit()
|
||||
self.assertRaises(frappe.ValidationError, pr2.submit)
|
||||
frappe.db.rollback()
|
||||
|
||||
pr1.cancel()
|
||||
se.cancel()
|
||||
se1.cancel()
|
||||
se2.cancel()
|
||||
se3.cancel()
|
||||
po.reload()
|
||||
pr2.load_from_db()
|
||||
|
||||
if pr2.docstatus == 1 and frappe.db.get_value('Stock Ledger Entry',
|
||||
{'voucher_no': pr2.name, 'is_cancelled': 0}, 'name'):
|
||||
pr2.cancel()
|
||||
|
||||
po.load_from_db()
|
||||
po.cancel()
|
||||
|
||||
def test_serial_no_supplier(self):
|
||||
pr = make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1)
|
||||
|
@ -116,6 +116,10 @@ class Issue(Document):
|
||||
}).insert(ignore_permissions=True)
|
||||
|
||||
return replicated_issue.name
|
||||
|
||||
def reset_issue_metrics(self):
|
||||
self.db_set("resolution_time", None)
|
||||
self.db_set("user_resolution_time", None)
|
||||
|
||||
def get_list_context(context=None):
|
||||
return {
|
||||
|
@ -281,15 +281,18 @@ def get_repeated(values):
|
||||
|
||||
|
||||
def get_documents_with_active_service_level_agreement():
|
||||
if not frappe.cache().hget("service_level_agreement", "active"):
|
||||
set_documents_with_active_service_level_agreement()
|
||||
sla_doctypes = frappe.cache().hget("service_level_agreement", "active")
|
||||
|
||||
return frappe.cache().hget("service_level_agreement", "active")
|
||||
if sla_doctypes is None:
|
||||
return set_documents_with_active_service_level_agreement()
|
||||
|
||||
return sla_doctypes
|
||||
|
||||
|
||||
def set_documents_with_active_service_level_agreement():
|
||||
active = [sla.document_type for sla in frappe.get_all("Service Level Agreement", fields=["document_type"])]
|
||||
frappe.cache().hset("service_level_agreement", "active", active)
|
||||
return active
|
||||
|
||||
|
||||
def apply(doc, method=None):
|
||||
|
Loading…
x
Reference in New Issue
Block a user