Merge branch 'version-13-hotfix' into mergify/bp/version-13-hotfix/pr-31579
This commit is contained in:
@@ -305,7 +305,7 @@ class PaymentEntry(AccountsController):
|
|||||||
|
|
||||||
def validate_reference_documents(self):
|
def validate_reference_documents(self):
|
||||||
if self.party_type == "Student":
|
if self.party_type == "Student":
|
||||||
valid_reference_doctypes = "Fees"
|
valid_reference_doctypes = ("Fees", "Journal Entry")
|
||||||
elif self.party_type == "Customer":
|
elif self.party_type == "Customer":
|
||||||
valid_reference_doctypes = ("Sales Order", "Sales Invoice", "Journal Entry", "Dunning")
|
valid_reference_doctypes = ("Sales Order", "Sales Invoice", "Journal Entry", "Dunning")
|
||||||
elif self.party_type == "Supplier":
|
elif self.party_type == "Supplier":
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from frappe import _
|
|||||||
from frappe.core.page.background_jobs.background_jobs import get_info
|
from frappe.core.page.background_jobs.background_jobs import get_info
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.model.mapper import map_child_doc, map_doc
|
from frappe.model.mapper import map_child_doc, map_doc
|
||||||
from frappe.utils import flt, getdate, nowdate
|
from frappe.utils import cint, flt, getdate, nowdate
|
||||||
from frappe.utils.background_jobs import enqueue
|
from frappe.utils.background_jobs import enqueue
|
||||||
from frappe.utils.scheduler import is_scheduler_inactive
|
from frappe.utils.scheduler import is_scheduler_inactive
|
||||||
|
|
||||||
@@ -219,6 +219,9 @@ class POSInvoiceMergeLog(Document):
|
|||||||
invoice.taxes_and_charges = None
|
invoice.taxes_and_charges = None
|
||||||
invoice.ignore_pricing_rule = 1
|
invoice.ignore_pricing_rule = 1
|
||||||
invoice.customer = self.customer
|
invoice.customer = self.customer
|
||||||
|
invoice.disable_rounded_total = cint(
|
||||||
|
frappe.db.get_value("POS Profile", invoice.pos_profile, "disable_rounded_total")
|
||||||
|
)
|
||||||
|
|
||||||
if self.merge_invoices_based_on == "Customer Group":
|
if self.merge_invoices_based_on == "Customer Group":
|
||||||
invoice.flags.ignore_pos_profile = True
|
invoice.flags.ignore_pos_profile = True
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
"write_off_account",
|
"write_off_account",
|
||||||
"write_off_cost_center",
|
"write_off_cost_center",
|
||||||
"account_for_change_amount",
|
"account_for_change_amount",
|
||||||
|
"disable_rounded_total",
|
||||||
"column_break_23",
|
"column_break_23",
|
||||||
"income_account",
|
"income_account",
|
||||||
"expense_account",
|
"expense_account",
|
||||||
@@ -358,6 +359,13 @@
|
|||||||
"fieldname": "validate_stock_on_save",
|
"fieldname": "validate_stock_on_save",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Validate Stock on Save"
|
"label": "Validate Stock on Save"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "If enabled, the consolidated invoices will have rounded total disabled",
|
||||||
|
"fieldname": "disable_rounded_total",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Disable Rounded Total"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "icon-cog",
|
"icon": "icon-cog",
|
||||||
@@ -385,7 +393,7 @@
|
|||||||
"link_fieldname": "pos_profile"
|
"link_fieldname": "pos_profile"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2022-03-21 13:29:28.480533",
|
"modified": "2022-07-21 11:16:46.911173",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "POS Profile",
|
"name": "POS Profile",
|
||||||
|
|||||||
@@ -2712,6 +2712,19 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
self.assertEqual(einvoice["ItemList"][2]["UnitPrice"], 20)
|
self.assertEqual(einvoice["ItemList"][2]["UnitPrice"], 20)
|
||||||
self.assertEqual(einvoice["ItemList"][3]["UnitPrice"], 10)
|
self.assertEqual(einvoice["ItemList"][3]["UnitPrice"], 10)
|
||||||
|
|
||||||
|
si = get_sales_invoice_for_e_invoice()
|
||||||
|
si.apply_discount_on = ""
|
||||||
|
si.items[1].price_list_rate = 15
|
||||||
|
si.items[1].discount_amount = -5
|
||||||
|
si.items[1].rate = 20
|
||||||
|
si.save()
|
||||||
|
|
||||||
|
einvoice = make_einvoice(si)
|
||||||
|
validate_totals(einvoice)
|
||||||
|
|
||||||
|
self.assertEqual(einvoice["ItemList"][1]["Discount"], 0)
|
||||||
|
self.assertEqual(einvoice["ItemList"][1]["UnitPrice"], 20)
|
||||||
|
|
||||||
def test_einvoice_without_discounts(self):
|
def test_einvoice_without_discounts(self):
|
||||||
from erpnext.regional.india.e_invoice.utils import make_einvoice, validate_totals
|
from erpnext.regional.india.e_invoice.utils import make_einvoice, validate_totals
|
||||||
|
|
||||||
@@ -2804,6 +2817,19 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
self.assertEqual(einvoice["ItemList"][2]["UnitPrice"], 18)
|
self.assertEqual(einvoice["ItemList"][2]["UnitPrice"], 18)
|
||||||
self.assertEqual(einvoice["ItemList"][3]["UnitPrice"], 5)
|
self.assertEqual(einvoice["ItemList"][3]["UnitPrice"], 5)
|
||||||
|
|
||||||
|
si = get_sales_invoice_for_e_invoice()
|
||||||
|
si.apply_discount_on = ""
|
||||||
|
si.items[1].price_list_rate = 15
|
||||||
|
si.items[1].discount_amount = -5
|
||||||
|
si.items[1].rate = 20
|
||||||
|
si.save()
|
||||||
|
|
||||||
|
einvoice = make_einvoice(si)
|
||||||
|
validate_totals(einvoice)
|
||||||
|
|
||||||
|
self.assertEqual(einvoice["ItemList"][1]["Discount"], 0)
|
||||||
|
self.assertEqual(einvoice["ItemList"][1]["UnitPrice"], 20)
|
||||||
|
|
||||||
def test_item_tax_net_range(self):
|
def test_item_tax_net_range(self):
|
||||||
item = create_item("T Shirt")
|
item = create_item("T Shirt")
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fetch_from": "website_item.image",
|
"fetch_from": "website_item.website_image",
|
||||||
"fieldname": "website_item_image",
|
"fieldname": "website_item_image",
|
||||||
"fieldtype": "Attach",
|
"fieldtype": "Attach",
|
||||||
"label": "Website Item Image",
|
"label": "Website Item Image",
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-07-13 21:02:19.031652",
|
"modified": "2022-06-28 16:44:24.718728",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "E-commerce",
|
"module": "E-commerce",
|
||||||
"name": "Recommended Items",
|
"name": "Recommended Items",
|
||||||
@@ -83,5 +83,6 @@
|
|||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -30,10 +30,6 @@ frappe.ui.form.on('Website Item', {
|
|||||||
}, __("View"));
|
}, __("View"));
|
||||||
},
|
},
|
||||||
|
|
||||||
image: () => {
|
|
||||||
refresh_field("image_view");
|
|
||||||
},
|
|
||||||
|
|
||||||
copy_from_item_group: (frm) => {
|
copy_from_item_group: (frm) => {
|
||||||
return frm.call({
|
return frm.call({
|
||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
"column_break_11",
|
"column_break_11",
|
||||||
"description",
|
"description",
|
||||||
"brand",
|
"brand",
|
||||||
"image",
|
|
||||||
"display_section",
|
"display_section",
|
||||||
"website_image",
|
"website_image",
|
||||||
"website_image_alt",
|
"website_image_alt",
|
||||||
@@ -113,8 +112,11 @@
|
|||||||
{
|
{
|
||||||
"description": "Item Image (if not slideshow)",
|
"description": "Item Image (if not slideshow)",
|
||||||
"fieldname": "website_image",
|
"fieldname": "website_image",
|
||||||
"fieldtype": "Attach",
|
"fieldtype": "Attach Image",
|
||||||
"label": "Website Image"
|
"hidden": 1,
|
||||||
|
"in_preview": 1,
|
||||||
|
"label": "Website Image",
|
||||||
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Image Alternative Text",
|
"description": "Image Alternative Text",
|
||||||
@@ -188,14 +190,6 @@
|
|||||||
"options": "Item Group",
|
"options": "Item Group",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "image",
|
|
||||||
"fieldtype": "Attach Image",
|
|
||||||
"hidden": 1,
|
|
||||||
"in_preview": 1,
|
|
||||||
"label": "Image",
|
|
||||||
"print_hide": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"default": "1",
|
"default": "1",
|
||||||
"fieldname": "published",
|
"fieldname": "published",
|
||||||
@@ -348,13 +342,14 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 1,
|
"has_web_view": 1,
|
||||||
"image_field": "image",
|
"image_field": "website_image",
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-09-02 13:08:41.942726",
|
"modified": "2022-06-28 17:10:30.613251",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "E-commerce",
|
"module": "E-commerce",
|
||||||
"name": "Website Item",
|
"name": "Website Item",
|
||||||
|
"naming_rule": "Expression (old style)",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@@ -410,6 +405,7 @@
|
|||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"title_field": "web_item_name",
|
"title_field": "web_item_name",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
|
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
from typing import TYPE_CHECKING, List, Union
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from erpnext.stock.doctype.item.item import Item
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
@@ -116,11 +120,6 @@ class WebsiteItem(WebsiteGenerator):
|
|||||||
if frappe.flags.in_import:
|
if frappe.flags.in_import:
|
||||||
return
|
return
|
||||||
|
|
||||||
auto_set_website_image = False
|
|
||||||
if not self.website_image and self.image:
|
|
||||||
auto_set_website_image = True
|
|
||||||
self.website_image = self.image
|
|
||||||
|
|
||||||
if not self.website_image:
|
if not self.website_image:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -137,7 +136,6 @@ class WebsiteItem(WebsiteGenerator):
|
|||||||
file_doc = file_doc[0]
|
file_doc = file_doc[0]
|
||||||
|
|
||||||
if not file_doc:
|
if not file_doc:
|
||||||
if not auto_set_website_image:
|
|
||||||
frappe.msgprint(
|
frappe.msgprint(
|
||||||
_("Website Image {0} attached to Item {1} cannot be found").format(
|
_("Website Image {0} attached to Item {1} cannot be found").format(
|
||||||
self.website_image, self.name
|
self.website_image, self.name
|
||||||
@@ -147,7 +145,6 @@ class WebsiteItem(WebsiteGenerator):
|
|||||||
self.website_image = None
|
self.website_image = None
|
||||||
|
|
||||||
elif file_doc.is_private:
|
elif file_doc.is_private:
|
||||||
if not auto_set_website_image:
|
|
||||||
frappe.msgprint(_("Website Image should be a public file or website URL"))
|
frappe.msgprint(_("Website Image should be a public file or website URL"))
|
||||||
|
|
||||||
self.website_image = None
|
self.website_image = None
|
||||||
@@ -159,9 +156,8 @@ class WebsiteItem(WebsiteGenerator):
|
|||||||
|
|
||||||
import requests.exceptions
|
import requests.exceptions
|
||||||
|
|
||||||
if not self.is_new() and self.website_image != frappe.db.get_value(
|
db_website_image = frappe.db.get_value(self.doctype, self.name, "website_image")
|
||||||
self.doctype, self.name, "website_image"
|
if not self.is_new() and self.website_image != db_website_image:
|
||||||
):
|
|
||||||
self.thumbnail = None
|
self.thumbnail = None
|
||||||
|
|
||||||
if self.website_image and not self.thumbnail:
|
if self.website_image and not self.thumbnail:
|
||||||
@@ -437,7 +433,9 @@ def check_if_user_is_customer(user=None):
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_website_item(doc, save=True):
|
def make_website_item(doc: "Item", save: bool = True) -> Union["WebsiteItem", List[str]]:
|
||||||
|
"Make Website Item from Item. Used via Form UI or patch."
|
||||||
|
|
||||||
if not doc:
|
if not doc:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -457,7 +455,6 @@ def make_website_item(doc, save=True):
|
|||||||
"item_group",
|
"item_group",
|
||||||
"stock_uom",
|
"stock_uom",
|
||||||
"brand",
|
"brand",
|
||||||
"image",
|
|
||||||
"has_variants",
|
"has_variants",
|
||||||
"variant_of",
|
"variant_of",
|
||||||
"description",
|
"description",
|
||||||
@@ -465,6 +462,10 @@ def make_website_item(doc, save=True):
|
|||||||
for field in fields_to_map:
|
for field in fields_to_map:
|
||||||
website_item.update({field: doc.get(field)})
|
website_item.update({field: doc.get(field)})
|
||||||
|
|
||||||
|
# Needed for publishing/mapping via Form UI only
|
||||||
|
if not frappe.flags.in_migrate and (doc.get("image") and not website_item.website_image):
|
||||||
|
website_item.website_image = doc.get("image")
|
||||||
|
|
||||||
if not save:
|
if not save:
|
||||||
return website_item
|
return website_item
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
frappe.listview_settings['Website Item'] = {
|
frappe.listview_settings['Website Item'] = {
|
||||||
add_fields: ["item_name", "web_item_name", "published", "image", "has_variants", "variant_of"],
|
add_fields: ["item_name", "web_item_name", "published", "website_image", "has_variants", "variant_of"],
|
||||||
filters: [["published", "=", "1"]],
|
filters: [["published", "=", "1"]],
|
||||||
|
|
||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
|
|||||||
@@ -20,7 +20,15 @@ def add_to_wishlist(item_code):
|
|||||||
web_item_data = frappe.db.get_value(
|
web_item_data = frappe.db.get_value(
|
||||||
"Website Item",
|
"Website Item",
|
||||||
{"item_code": item_code},
|
{"item_code": item_code},
|
||||||
["image", "website_warehouse", "name", "web_item_name", "item_name", "item_group", "route"],
|
[
|
||||||
|
"website_image",
|
||||||
|
"website_warehouse",
|
||||||
|
"name",
|
||||||
|
"web_item_name",
|
||||||
|
"item_name",
|
||||||
|
"item_group",
|
||||||
|
"route",
|
||||||
|
],
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,7 +38,7 @@ def add_to_wishlist(item_code):
|
|||||||
"item_group": web_item_data.get("item_group"),
|
"item_group": web_item_data.get("item_group"),
|
||||||
"website_item": web_item_data.get("name"),
|
"website_item": web_item_data.get("name"),
|
||||||
"web_item_name": web_item_data.get("web_item_name"),
|
"web_item_name": web_item_data.get("web_item_name"),
|
||||||
"image": web_item_data.get("image"),
|
"image": web_item_data.get("website_image"),
|
||||||
"warehouse": web_item_data.get("website_warehouse"),
|
"warehouse": web_item_data.get("website_warehouse"),
|
||||||
"route": web_item_data.get("route"),
|
"route": web_item_data.get("route"),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ class ProductQuery:
|
|||||||
"variant_of",
|
"variant_of",
|
||||||
"has_variants",
|
"has_variants",
|
||||||
"item_group",
|
"item_group",
|
||||||
"image",
|
|
||||||
"web_long_description",
|
"web_long_description",
|
||||||
"short_description",
|
"short_description",
|
||||||
"route",
|
"route",
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ erpnext.ProductGrid = class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_image_html(item, title) {
|
get_image_html(item, title) {
|
||||||
let image = item.website_image || item.image;
|
let image = item.website_image;
|
||||||
|
|
||||||
if (image) {
|
if (image) {
|
||||||
return `
|
return `
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ erpnext.ProductList = class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_image_html(item, title, settings) {
|
get_image_html(item, title, settings) {
|
||||||
let image = item.website_image || item.image;
|
let image = item.website_image;
|
||||||
let wishlist_enabled = !item.has_variants && settings.enable_wishlist;
|
let wishlist_enabled = !item.has_variants && settings.enable_wishlist;
|
||||||
let image_html = ``;
|
let image_html = ``;
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ def execute():
|
|||||||
"item_group",
|
"item_group",
|
||||||
"stock_uom",
|
"stock_uom",
|
||||||
"brand",
|
"brand",
|
||||||
"image",
|
|
||||||
"has_variants",
|
"has_variants",
|
||||||
"variant_of",
|
"variant_of",
|
||||||
"description",
|
"description",
|
||||||
@@ -30,6 +29,7 @@ def execute():
|
|||||||
"website_warehouse",
|
"website_warehouse",
|
||||||
"web_long_description",
|
"web_long_description",
|
||||||
"website_content",
|
"website_content",
|
||||||
|
"website_image",
|
||||||
"thumbnail",
|
"thumbnail",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -623,9 +623,20 @@ class SalarySlip(TransactionBase):
|
|||||||
|
|
||||||
def add_structure_components(self, component_type):
|
def add_structure_components(self, component_type):
|
||||||
data = self.get_data_for_eval()
|
data = self.get_data_for_eval()
|
||||||
|
timesheet_component = frappe.db.get_value(
|
||||||
|
"Salary Structure", self.salary_structure, "salary_component"
|
||||||
|
)
|
||||||
|
|
||||||
for struct_row in self._salary_structure_doc.get(component_type):
|
for struct_row in self._salary_structure_doc.get(component_type):
|
||||||
|
if self.salary_slip_based_on_timesheet and struct_row.salary_component == timesheet_component:
|
||||||
|
continue
|
||||||
|
|
||||||
amount = self.eval_condition_and_formula(struct_row, data)
|
amount = self.eval_condition_and_formula(struct_row, data)
|
||||||
if amount is not None and struct_row.statistical_component == 0:
|
if (
|
||||||
|
amount
|
||||||
|
or (struct_row.amount_based_on_formula and amount is not None)
|
||||||
|
and struct_row.statistical_component == 0
|
||||||
|
):
|
||||||
self.update_component_row(struct_row, amount, component_type, data=data)
|
self.update_component_row(struct_row, amount, component_type, data=data)
|
||||||
|
|
||||||
def get_data_for_eval(self):
|
def get_data_for_eval(self):
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class SalaryStructure(Document):
|
|||||||
self.validate_max_benefits_with_flexi()
|
self.validate_max_benefits_with_flexi()
|
||||||
self.validate_component_based_on_tax_slab()
|
self.validate_component_based_on_tax_slab()
|
||||||
self.validate_payment_days_based_dependent_component()
|
self.validate_payment_days_based_dependent_component()
|
||||||
|
self.validate_timesheet_component()
|
||||||
|
|
||||||
def set_missing_values(self):
|
def set_missing_values(self):
|
||||||
overwritten_fields = [
|
overwritten_fields = [
|
||||||
@@ -89,6 +90,21 @@ class SalaryStructure(Document):
|
|||||||
|
|
||||||
return abbr
|
return abbr
|
||||||
|
|
||||||
|
def validate_timesheet_component(self):
|
||||||
|
if not self.salary_slip_based_on_timesheet:
|
||||||
|
return
|
||||||
|
|
||||||
|
for component in self.earnings:
|
||||||
|
if component.salary_component == self.salary_component:
|
||||||
|
frappe.msgprint(
|
||||||
|
_(
|
||||||
|
"Row #{0}: Timesheet amount will overwrite the Earning component amount for the Salary Component {1}"
|
||||||
|
).format(self.idx, frappe.bold(self.salary_component)),
|
||||||
|
title=_("Warning"),
|
||||||
|
indicator="orange",
|
||||||
|
)
|
||||||
|
break
|
||||||
|
|
||||||
def strip_condition_and_formula_fields(self):
|
def strip_condition_and_formula_fields(self):
|
||||||
# remove whitespaces from condition and formula fields
|
# remove whitespaces from condition and formula fields
|
||||||
for row in self.earnings:
|
for row in self.earnings:
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class Homepage(Document):
|
|||||||
def setup_items(self):
|
def setup_items(self):
|
||||||
for d in frappe.get_all(
|
for d in frappe.get_all(
|
||||||
"Website Item",
|
"Website Item",
|
||||||
fields=["name", "item_name", "description", "image", "route"],
|
fields=["name", "item_name", "description", "website_image", "route"],
|
||||||
filters={"published": 1},
|
filters={"published": 1},
|
||||||
limit=3,
|
limit=3,
|
||||||
):
|
):
|
||||||
@@ -31,7 +31,7 @@ class Homepage(Document):
|
|||||||
item_code=d.name,
|
item_code=d.name,
|
||||||
item_name=d.item_name,
|
item_name=d.item_name,
|
||||||
description=d.description,
|
description=d.description,
|
||||||
image=d.image,
|
image=d.website_image,
|
||||||
route=d.route,
|
route=d.route,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -265,6 +265,10 @@ def get_overseas_address_details(address_name):
|
|||||||
def get_item_list(invoice):
|
def get_item_list(invoice):
|
||||||
item_list = []
|
item_list = []
|
||||||
|
|
||||||
|
hide_discount_in_einvoice = cint(
|
||||||
|
frappe.db.get_single_value("E Invoice Settings", "dont_show_discounts_in_e_invoice")
|
||||||
|
)
|
||||||
|
|
||||||
for d in invoice.items:
|
for d in invoice.items:
|
||||||
einvoice_item_schema = read_json("einv_item_template")
|
einvoice_item_schema = read_json("einv_item_template")
|
||||||
item = frappe._dict({})
|
item = frappe._dict({})
|
||||||
@@ -276,17 +280,12 @@ def get_item_list(invoice):
|
|||||||
item.qty = abs(item.qty)
|
item.qty = abs(item.qty)
|
||||||
item_qty = item.qty
|
item_qty = item.qty
|
||||||
|
|
||||||
item.discount_amount = abs(item.discount_amount)
|
|
||||||
item.taxable_value = abs(item.taxable_value)
|
item.taxable_value = abs(item.taxable_value)
|
||||||
|
|
||||||
if invoice.get("is_return") or invoice.get("is_debit_note"):
|
if invoice.get("is_return") or invoice.get("is_debit_note"):
|
||||||
item_qty = item_qty or 1
|
item_qty = item_qty or 1
|
||||||
|
|
||||||
hide_discount_in_einvoice = cint(
|
if hide_discount_in_einvoice or invoice.is_internal_customer or item.discount_amount < 0:
|
||||||
frappe.db.get_single_value("E Invoice Settings", "dont_show_discounts_in_e_invoice")
|
|
||||||
)
|
|
||||||
|
|
||||||
if hide_discount_in_einvoice:
|
|
||||||
item.unit_rate = item.taxable_value / item_qty
|
item.unit_rate = item.taxable_value / item_qty
|
||||||
item.gross_amount = item.taxable_value
|
item.gross_amount = item.taxable_value
|
||||||
item.discount_amount = 0
|
item.discount_amount = 0
|
||||||
|
|||||||
@@ -580,7 +580,7 @@ def get_ewb_data(dt, dn):
|
|||||||
|
|
||||||
if dt == "Delivery Note":
|
if dt == "Delivery Note":
|
||||||
data.subSupplyType = 1
|
data.subSupplyType = 1
|
||||||
elif doc.gst_category in ["Registered Regular", "SEZ"]:
|
elif doc.gst_category in ["Unregistered", "Registered Regular", "SEZ"]:
|
||||||
data.subSupplyType = 1
|
data.subSupplyType = 1
|
||||||
elif doc.gst_category in ["Overseas", "Deemed Export"]:
|
elif doc.gst_category in ["Overseas", "Deemed Export"]:
|
||||||
data.subSupplyType = 3
|
data.subSupplyType = 3
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ def _execute(filters=None):
|
|||||||
added_item = []
|
added_item = []
|
||||||
for d in item_list:
|
for d in item_list:
|
||||||
if (d.parent, d.item_code) not in added_item:
|
if (d.parent, d.item_code) not in added_item:
|
||||||
row = [d.gst_hsn_code, d.description, d.stock_uom, d.stock_qty, d.tax_rate]
|
row = [d.gst_hsn_code, d.description, d.stock_uom, d.stock_qty, d.tax_rate or 0]
|
||||||
total_tax = 0
|
total_tax = 0
|
||||||
for tax in tax_columns:
|
for tax in tax_columns:
|
||||||
item_tax = itemised_tax.get((d.parent, d.item_code), {}).get(tax, {})
|
item_tax = itemised_tax.get((d.parent, d.item_code), {}).get(tax, {})
|
||||||
@@ -100,31 +100,51 @@ def get_items(filters):
|
|||||||
|
|
||||||
items = frappe.db.sql(
|
items = frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
select
|
SELECT
|
||||||
`tabSales Invoice Item`.gst_hsn_code,
|
`tabSales Invoice Item`.gst_hsn_code,
|
||||||
`tabSales Invoice Item`.stock_uom,
|
`tabSales Invoice Item`.stock_uom,
|
||||||
sum(`tabSales Invoice Item`.stock_qty) as stock_qty,
|
sum(
|
||||||
sum(`tabSales Invoice Item`.base_net_amount) as base_net_amount,
|
`tabSales Invoice Item`.stock_qty
|
||||||
sum(`tabSales Invoice Item`.base_price_list_rate) as base_price_list_rate,
|
) as stock_qty,
|
||||||
|
sum(
|
||||||
|
`tabSales Invoice Item`.base_net_amount
|
||||||
|
) as base_net_amount,
|
||||||
|
sum(
|
||||||
|
`tabSales Invoice Item`.base_price_list_rate
|
||||||
|
) as base_price_list_rate,
|
||||||
|
|
||||||
`tabSales Invoice Item`.parent,
|
`tabSales Invoice Item`.parent,
|
||||||
`tabSales Invoice Item`.item_code,
|
`tabSales Invoice Item`.item_code,
|
||||||
`tabGST HSN Code`.description,
|
`tabGST HSN Code`.description,
|
||||||
json_extract(`tabSales Taxes and Charges`.item_wise_tax_detail,
|
json_extract(
|
||||||
concat('$."' , `tabSales Invoice Item`.item_code, '"[0]')) * count(distinct `tabSales Taxes and Charges`.name) as tax_rate
|
`tabSales Taxes and Charges`.item_wise_tax_detail,
|
||||||
from
|
concat(
|
||||||
`tabSales Invoice`,
|
'$."', `tabSales Invoice Item`.item_code,
|
||||||
`tabSales Invoice Item`,
|
'"[0]'
|
||||||
`tabGST HSN Code`,
|
)
|
||||||
`tabSales Taxes and Charges`
|
) * count(
|
||||||
where
|
distinct `tabSales Taxes and Charges`.name
|
||||||
`tabSales Invoice`.name = `tabSales Invoice Item`.parent
|
) as tax_rate
|
||||||
and `tabSales Taxes and Charges`.parent = `tabSales Invoice`.name
|
FROM
|
||||||
and `tabSales Invoice`.docstatus = 1
|
`tabSales Invoice`
|
||||||
and `tabSales Invoice Item`.gst_hsn_code is not NULL
|
INNER JOIN
|
||||||
and `tabSales Invoice Item`.gst_hsn_code = `tabGST HSN Code`.name %s %s
|
`tabSales Invoice Item` ON `tabSales Invoice`.name = `tabSales Invoice Item`.parent
|
||||||
group by
|
INNER JOIN
|
||||||
|
`tabGST HSN Code` ON `tabSales Invoice Item`.gst_hsn_code = `tabGST HSN Code`.name % s % s
|
||||||
|
LEFT JOIN
|
||||||
|
`tabSales Taxes and Charges` ON `tabSales Taxes and Charges`.parent = `tabSales Invoice`.name
|
||||||
|
WHERE
|
||||||
|
`tabSales Invoice`.docstatus = 1
|
||||||
|
AND
|
||||||
|
`tabSales Invoice Item`.gst_hsn_code is not NULL
|
||||||
|
GROUP BY
|
||||||
`tabSales Invoice Item`.parent,
|
`tabSales Invoice Item`.parent,
|
||||||
`tabSales Invoice Item`.item_code
|
`tabSales Invoice Item`.item_code,
|
||||||
|
`tabSales Invoice Item`.gst_hsn_code,
|
||||||
|
`tabSales Invoice Item`.uom
|
||||||
|
ORDER BY
|
||||||
|
`tabSales Invoice Item`.gst_hsn_code,
|
||||||
|
`tabSales Invoice Item`.uom
|
||||||
"""
|
"""
|
||||||
% (conditions, match_conditions),
|
% (conditions, match_conditions),
|
||||||
filters,
|
filters,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ product_image(doc.website_image or doc.image, alt=doc.website_image_alt or doc.item_name) }}
|
{{ product_image(doc.website_image, alt=doc.website_image_alt or doc.item_name) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Simple image preview -->
|
<!-- Simple image preview -->
|
||||||
|
|||||||
@@ -74,7 +74,7 @@
|
|||||||
{%- set col_size = 3 if is_full_width else 4 -%}
|
{%- set col_size = 3 if is_full_width else 4 -%}
|
||||||
{%- set title = item.web_item_name or item.item_name or item.item_code -%}
|
{%- set title = item.web_item_name or item.item_name or item.item_code -%}
|
||||||
{%- set title = title[:50] + "..." if title|len > 50 else title -%}
|
{%- set title = title[:50] + "..." if title|len > 50 else title -%}
|
||||||
{%- set image = item.website_image or item.image -%}
|
{%- set image = item.website_image -%}
|
||||||
{%- set description = item.website_description or item.description-%}
|
{%- set description = item.website_description or item.description-%}
|
||||||
|
|
||||||
{% if is_featured %}
|
{% if is_featured %}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/* csslint ignore:start */
|
/* csslint ignore:start */
|
||||||
{% if homepage.hero_image %}
|
{% if homepage.hero_image %}
|
||||||
.hero-image {
|
.hero-image {
|
||||||
background-image: url("{{ homepage.hero_image }}");
|
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
padding: 10rem 0;
|
padding: 10rem 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,11 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<main>
|
<main>
|
||||||
{% if homepage.hero_section_based_on == 'Default' %}
|
{% if homepage.hero_section_based_on == 'Default' %}
|
||||||
<section class="hero-section border-bottom {%if homepage.hero_image%}hero-image{%endif%}">
|
<section class="hero-section border-bottom {%if homepage.hero_image%}hero-image{%endif%}"
|
||||||
|
{% if homepage.hero_image %}
|
||||||
|
style="background-image: url('{{ homepage.hero_image }}');"
|
||||||
|
{%- endif %}
|
||||||
|
>
|
||||||
<div class="container py-5">
|
<div class="container py-5">
|
||||||
<h1 class="d-none d-sm-block display-4">{{ homepage.tag_line }}</h1>
|
<h1 class="d-none d-sm-block display-4">{{ homepage.tag_line }}</h1>
|
||||||
<h1 class="d-block d-sm-none">{{ homepage.tag_line }}</h1>
|
<h1 class="d-block d-sm-none">{{ homepage.tag_line }}</h1>
|
||||||
|
|||||||
Reference in New Issue
Block a user