Merge pull request #30443 from frappe/mergify/bp/develop/pr-30438
fix: Incorrect default amount to pay for POS invoices (backport #30438)
diff --git a/.github/workflows/server-tests-mariadb.yml b/.github/workflows/server-tests-mariadb.yml
index 69be765..8cc5826 100644
--- a/.github/workflows/server-tests-mariadb.yml
+++ b/.github/workflows/server-tests-mariadb.yml
@@ -119,9 +119,22 @@
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
- name: Upload coverage data
+ uses: actions/upload-artifact@v3
+ with:
+ name: coverage-${{ matrix.container }}
+ path: /home/runner/frappe-bench/sites/coverage.xml
+
+ coverage:
+ name: Coverage Wrap Up
+ needs: test
+ runs-on: ubuntu-latest
+ steps:
+ - name: Download artifacts
+ uses: actions/download-artifact@v3
+
+ - name: Upload coverage data
uses: codecov/codecov-action@v2
with:
name: MariaDB
fail_ci_if_error: true
- files: /home/runner/frappe-bench/sites/coverage.xml
verbose: true
diff --git a/codecov.yml b/codecov.yml
index 1fa602a..7d9c37d 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -21,7 +21,6 @@
comment:
layout: "diff, files"
require_changes: true
- after_n_builds: 3
ignore:
- "erpnext/demo"
diff --git a/erpnext/accounts/doctype/gst_account/gst_account.json b/erpnext/accounts/doctype/gst_account/gst_account.json
index b6ec884..be5124c 100644
--- a/erpnext/accounts/doctype/gst_account/gst_account.json
+++ b/erpnext/accounts/doctype/gst_account/gst_account.json
@@ -10,6 +10,7 @@
"sgst_account",
"igst_account",
"cess_account",
+ "utgst_account",
"is_reverse_charge_account"
],
"fields": [
@@ -64,12 +65,18 @@
"fieldtype": "Check",
"in_list_view": 1,
"label": "Is Reverse Charge Account"
+ },
+ {
+ "fieldname": "utgst_account",
+ "fieldtype": "Link",
+ "label": "UTGST Account",
+ "options": "Account"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2021-04-09 12:30:25.889993",
+ "modified": "2022-04-07 12:59:14.039768",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GST Account",
@@ -78,5 +85,6 @@
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
+ "states": [],
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py
index bdde3a1..bd4b59b 100644
--- a/erpnext/controllers/sales_and_purchase_return.py
+++ b/erpnext/controllers/sales_and_purchase_return.py
@@ -330,7 +330,6 @@
doc = frappe.get_doc(target)
doc.is_return = 1
doc.return_against = source.name
- doc.ignore_pricing_rule = 1
doc.set_warehouse = ""
if doctype == "Sales Invoice" or doctype == "POS Invoice":
doc.is_pos = source.is_pos
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index a3bf78b..6e5ffed 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -364,3 +364,4 @@
erpnext.patches.v13_0.set_return_against_in_pos_invoice_references
erpnext.patches.v13_0.remove_unknown_links_to_prod_plan_items # 24-03-2022
erpnext.patches.v13_0.update_expense_claim_status_for_paid_advances
+erpnext.patches.v13_0.create_gst_custom_fields_in_quotation
\ No newline at end of file
diff --git a/erpnext/patches/v13_0/create_gst_custom_fields_in_quotation.py b/erpnext/patches/v13_0/create_gst_custom_fields_in_quotation.py
new file mode 100644
index 0000000..3217eab
--- /dev/null
+++ b/erpnext/patches/v13_0/create_gst_custom_fields_in_quotation.py
@@ -0,0 +1,53 @@
+import frappe
+from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
+
+
+def execute():
+ company = frappe.get_all("Company", filters={"country": "India"}, fields=["name"])
+ if not company:
+ return
+
+ sales_invoice_gst_fields = [
+ dict(
+ fieldname="billing_address_gstin",
+ label="Billing Address GSTIN",
+ fieldtype="Data",
+ insert_after="customer_address",
+ read_only=1,
+ fetch_from="customer_address.gstin",
+ print_hide=1,
+ length=15,
+ ),
+ dict(
+ fieldname="customer_gstin",
+ label="Customer GSTIN",
+ fieldtype="Data",
+ insert_after="shipping_address_name",
+ fetch_from="shipping_address_name.gstin",
+ print_hide=1,
+ length=15,
+ ),
+ dict(
+ fieldname="place_of_supply",
+ label="Place of Supply",
+ fieldtype="Data",
+ insert_after="customer_gstin",
+ print_hide=1,
+ read_only=1,
+ length=50,
+ ),
+ dict(
+ fieldname="company_gstin",
+ label="Company GSTIN",
+ fieldtype="Data",
+ insert_after="company_address",
+ fetch_from="company_address.gstin",
+ print_hide=1,
+ read_only=1,
+ length=15,
+ ),
+ ]
+
+ custom_fields = {"Quotation": sales_invoice_gst_fields}
+
+ create_custom_fields(custom_fields, update=True)
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index 7031fcb..29f1ce4 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -326,21 +326,39 @@
def get_project_list(
doctype, txt, filters, limit_start, limit_page_length=20, order_by="modified"
):
- return frappe.db.sql(
- """select distinct project.*
- from tabProject project, `tabProject User` project_user
- where
- (project_user.user = %(user)s
- and project_user.parent = project.name)
- or project.owner = %(user)s
- order by project.modified desc
- limit {0}, {1}
- """.format(
- limit_start, limit_page_length
- ),
- {"user": frappe.session.user},
- as_dict=True,
- update={"doctype": "Project"},
+ meta = frappe.get_meta(doctype)
+ if not filters:
+ filters = []
+
+ fields = "distinct *"
+
+ or_filters = []
+
+ if txt:
+ if meta.search_fields:
+ for f in meta.get_search_fields():
+ if f == "name" or meta.get_field(f).fieldtype in (
+ "Data",
+ "Text",
+ "Small Text",
+ "Text Editor",
+ "select",
+ ):
+ or_filters.append([doctype, f, "like", "%" + txt + "%"])
+ else:
+ if isinstance(filters, dict):
+ filters["name"] = ("like", "%" + txt + "%")
+ else:
+ filters.append([doctype, "name", "like", "%" + txt + "%"])
+
+ return frappe.get_list(
+ doctype,
+ fields=fields,
+ filters=filters,
+ or_filters=or_filters,
+ limit_start=limit_start,
+ limit_page_length=limit_page_length,
+ order_by=order_by,
)
diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py
index 8fd9c1c..f317569 100644
--- a/erpnext/regional/india/e_invoice/utils.py
+++ b/erpnext/regional/india/e_invoice/utils.py
@@ -314,10 +314,14 @@
item.cess_rate += item_tax_rate
item.cess_amount += abs(item_tax_amount_after_discount)
- for tax_type in ["igst", "cgst", "sgst"]:
+ for tax_type in ["igst", "cgst", "sgst", "utgst"]:
if t.account_head in gst_accounts[f"{tax_type}_account"]:
item.tax_rate += item_tax_rate
- item[f"{tax_type}_amount"] += abs(item_tax_amount)
+ if tax_type == "utgst":
+ # utgst taxes are reported same as sgst tax
+ item["sgst_amount"] += abs(item_tax_amount)
+ else:
+ item[f"{tax_type}_amount"] += abs(item_tax_amount)
else:
# TODO: other charges per item
pass
@@ -359,11 +363,15 @@
# using after discount amt since item also uses after discount amt for cess calc
invoice_value_details.total_cess_amt += abs(t.base_tax_amount_after_discount_amount)
- for tax_type in ["igst", "cgst", "sgst"]:
+ for tax_type in ["igst", "cgst", "sgst", "utgst"]:
if t.account_head in gst_accounts[f"{tax_type}_account"]:
+ if tax_type == "utgst":
+ invoice_value_details["total_sgst_amt"] += abs(tax_amount)
+ else:
+ invoice_value_details[f"total_{tax_type}_amt"] += abs(tax_amount)
- invoice_value_details[f"total_{tax_type}_amt"] += abs(tax_amount)
update_other_charges(t, invoice_value_details, gst_accounts_list, invoice, considered_rows)
+
else:
invoice_value_details.total_other_charges += abs(tax_amount)
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index 40fa6cd..446faaa 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -930,6 +930,7 @@
"Journal Entry": journal_entry_fields,
"Sales Order": sales_invoice_gst_fields,
"Tax Category": inter_state_gst_field,
+ "Quotation": sales_invoice_gst_fields,
"Item": [
dict(
fieldname="gst_hsn_code",
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 249c1b7..0b6fcc6 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -225,7 +225,7 @@
if not frappe.get_meta("Address").has_field("gst_state"):
return
- if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"):
+ if doctype in ("Sales Invoice", "Delivery Note", "Sales Order", "Quotation"):
address_name = party_details.customer_address or party_details.shipping_address_name
elif doctype in ("Purchase Invoice", "Purchase Order", "Purchase Receipt"):
address_name = party_details.shipping_address or party_details.supplier_address
@@ -254,7 +254,7 @@
party_details.taxes = []
return party_details
- if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"):
+ if doctype in ("Sales Invoice", "Delivery Note", "Sales Order", "Quotation"):
master_doctype = "Sales Taxes and Charges Template"
tax_template_by_category = get_tax_template_based_on_category(
master_doctype, company, party_details
@@ -311,7 +311,7 @@
def is_internal_transfer(party_details, doctype):
- if doctype in ("Sales Invoice", "Delivery Note", "Sales Order"):
+ if doctype in ("Sales Invoice", "Delivery Note", "Sales Order", "Quotation"):
destination_gstin = party_details.company_gstin
elif doctype in ("Purchase Invoice", "Purchase Order", "Purchase Receipt"):
destination_gstin = party_details.supplier_gstin
@@ -824,7 +824,7 @@
gst_settings_accounts = frappe.get_all(
"GST Account",
filters=filters,
- fields=["cgst_account", "sgst_account", "igst_account", "cess_account"],
+ fields=["cgst_account", "sgst_account", "igst_account", "cess_account", "utgst_account"],
)
if not gst_settings_accounts and not frappe.flags.in_test and not frappe.flags.in_migrate:
diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json
index 0318b70..75443ab 100644
--- a/erpnext/selling/doctype/quotation/quotation.json
+++ b/erpnext/selling/doctype/quotation/quotation.json
@@ -31,6 +31,8 @@
"col_break98",
"shipping_address_name",
"shipping_address",
+ "company_address",
+ "company_address_display",
"customer_group",
"territory",
"currency_and_price_list",
@@ -955,7 +957,18 @@
"fieldname": "competitors",
"fieldtype": "Table MultiSelect",
"label": "Competitors",
- "options": "Competitor Detail",
+ "options": "Competitor Detail"
+ },
+ {
+ "fieldname": "company_address",
+ "fieldtype": "Link",
+ "label": "Company Address Name",
+ "options": "Address"
+ },
+ {
+ "fieldname": "company_address_display",
+ "fieldtype": "Small Text",
+ "label": "Company Address",
"read_only": 1
},
{
diff --git a/erpnext/selling/doctype/quotation/regional/india.js b/erpnext/selling/doctype/quotation/regional/india.js
new file mode 100644
index 0000000..9550835
--- /dev/null
+++ b/erpnext/selling/doctype/quotation/regional/india.js
@@ -0,0 +1,3 @@
+{% include "erpnext/regional/india/taxes.js" %}
+
+erpnext.setup_auto_gst_taxation('Quotation');
diff --git a/erpnext/stock/doctype/pick_list/test_pick_list.py b/erpnext/stock/doctype/pick_list/test_pick_list.py
index ec5011b..27b06d2 100644
--- a/erpnext/stock/doctype/pick_list/test_pick_list.py
+++ b/erpnext/stock/doctype/pick_list/test_pick_list.py
@@ -8,7 +8,7 @@
from frappe.tests.utils import FrappeTestCase
-from erpnext.stock.doctype.item.test_item import create_item
+from erpnext.stock.doctype.item.test_item import create_item, make_item
from erpnext.stock.doctype.pick_list.pick_list import create_delivery_note
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import (
@@ -18,6 +18,7 @@
class TestPickList(FrappeTestCase):
def test_pick_list_picks_warehouse_for_each_item(self):
+ item_code = make_item().name
try:
frappe.get_doc(
{
@@ -27,7 +28,7 @@
"expense_account": "Temporary Opening - _TC",
"items": [
{
- "item_code": "_Test Item",
+ "item_code": item_code,
"warehouse": "_Test Warehouse - _TC",
"valuation_rate": 100,
"qty": 5,
@@ -47,7 +48,7 @@
"purpose": "Delivery",
"locations": [
{
- "item_code": "_Test Item",
+ "item_code": item_code,
"qty": 5,
"stock_qty": 5,
"conversion_factor": 1,
@@ -59,7 +60,7 @@
)
pick_list.set_item_locations()
- self.assertEqual(pick_list.locations[0].item_code, "_Test Item")
+ self.assertEqual(pick_list.locations[0].item_code, item_code)
self.assertEqual(pick_list.locations[0].warehouse, "_Test Warehouse - _TC")
self.assertEqual(pick_list.locations[0].qty, 5)
@@ -270,6 +271,8 @@
pr2.cancel()
def test_pick_list_for_items_from_multiple_sales_orders(self):
+
+ item_code = make_item().name
try:
frappe.get_doc(
{
@@ -279,7 +282,7 @@
"expense_account": "Temporary Opening - _TC",
"items": [
{
- "item_code": "_Test Item",
+ "item_code": item_code,
"warehouse": "_Test Warehouse - _TC",
"valuation_rate": 100,
"qty": 10,
@@ -295,7 +298,14 @@
"doctype": "Sales Order",
"customer": "_Test Customer",
"company": "_Test Company",
- "items": [{"item_code": "_Test Item", "qty": 10, "delivery_date": frappe.utils.today()}],
+ "items": [
+ {
+ "item_code": item_code,
+ "qty": 10,
+ "delivery_date": frappe.utils.today(),
+ "warehouse": "_Test Warehouse - _TC",
+ }
+ ],
}
)
sales_order.submit()
@@ -309,7 +319,7 @@
"purpose": "Delivery",
"locations": [
{
- "item_code": "_Test Item",
+ "item_code": item_code,
"qty": 5,
"stock_qty": 5,
"conversion_factor": 1,
@@ -317,7 +327,7 @@
"sales_order_item": "_T-Sales Order-1_item",
},
{
- "item_code": "_Test Item",
+ "item_code": item_code,
"qty": 5,
"stock_qty": 5,
"conversion_factor": 1,
@@ -329,18 +339,19 @@
)
pick_list.set_item_locations()
- self.assertEqual(pick_list.locations[0].item_code, "_Test Item")
+ self.assertEqual(pick_list.locations[0].item_code, item_code)
self.assertEqual(pick_list.locations[0].warehouse, "_Test Warehouse - _TC")
self.assertEqual(pick_list.locations[0].qty, 5)
self.assertEqual(pick_list.locations[0].sales_order_item, "_T-Sales Order-1_item")
- self.assertEqual(pick_list.locations[1].item_code, "_Test Item")
+ self.assertEqual(pick_list.locations[1].item_code, item_code)
self.assertEqual(pick_list.locations[1].warehouse, "_Test Warehouse - _TC")
self.assertEqual(pick_list.locations[1].qty, 5)
self.assertEqual(pick_list.locations[1].sales_order_item, sales_order.items[0].name)
def test_pick_list_for_items_with_multiple_UOM(self):
- purchase_receipt = make_purchase_receipt(item_code="_Test Item", qty=10)
+ item_code = make_item().name
+ purchase_receipt = make_purchase_receipt(item_code=item_code, qty=10)
purchase_receipt.submit()
sales_order = frappe.get_doc(
@@ -350,17 +361,19 @@
"company": "_Test Company",
"items": [
{
- "item_code": "_Test Item",
+ "item_code": item_code,
"qty": 1,
"conversion_factor": 5,
"stock_qty": 5,
"delivery_date": frappe.utils.today(),
+ "warehouse": "_Test Warehouse - _TC",
},
{
- "item_code": "_Test Item",
+ "item_code": item_code,
"qty": 1,
"conversion_factor": 1,
"delivery_date": frappe.utils.today(),
+ "warehouse": "_Test Warehouse - _TC",
},
],
}
@@ -376,7 +389,7 @@
"purpose": "Delivery",
"locations": [
{
- "item_code": "_Test Item",
+ "item_code": item_code,
"qty": 2,
"stock_qty": 1,
"conversion_factor": 0.5,
@@ -384,7 +397,7 @@
"sales_order_item": sales_order.items[0].name,
},
{
- "item_code": "_Test Item",
+ "item_code": item_code,
"qty": 1,
"stock_qty": 1,
"conversion_factor": 1,