mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-04 20:59:11 +00:00
Merge pull request #31352 from frappe/version-12-hotfix
chore: version-12 release
This commit is contained in:
@@ -16,11 +16,11 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- name: "Python 2.7 Server Side Test"
|
- name: "Python 2.7 Server Side Test"
|
||||||
python: 2.7
|
python: 2.7
|
||||||
script: bench --site test_site run-tests --app erpnext --coverage
|
script: bench --site test_site run-tests --app erpnext
|
||||||
|
|
||||||
- name: "Python 3.6 Server Side Test"
|
- name: "Python 3.6 Server Side Test"
|
||||||
python: 3.6
|
python: 3.6
|
||||||
script: bench --site test_site run-tests --app erpnext --coverage
|
script: bench --site test_site run-tests --app erpnext
|
||||||
|
|
||||||
- name: "Python 2.7 Patch Test"
|
- name: "Python 2.7 Patch Test"
|
||||||
python: 2.7
|
python: 2.7
|
||||||
@@ -74,8 +74,3 @@ install:
|
|||||||
- bench get-app erpnext $TRAVIS_BUILD_DIR
|
- bench get-app erpnext $TRAVIS_BUILD_DIR
|
||||||
- bench start &
|
- bench start &
|
||||||
- bench --site test_site reinstall --yes
|
- bench --site test_site reinstall --yes
|
||||||
|
|
||||||
after_script:
|
|
||||||
- pip install coverage==4.5.4
|
|
||||||
- pip install python-coveralls
|
|
||||||
- coveralls -b apps/erpnext -d ../../sites/.coverage
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
{%- from "templates/print_formats/standard_macros.html" import add_header, render_field, print_value -%}
|
{%- from "templates/print_formats/standard_macros.html" import add_header, render_field, print_value -%}
|
||||||
{%- set einvoice = json.loads(doc.signed_einvoice) -%}
|
|
||||||
|
|
||||||
<div class="page-break">
|
<div class="page-break">
|
||||||
|
{% if doc.signed_einvoice %}
|
||||||
|
{%- set einvoice = json.loads(doc.signed_einvoice) -%}
|
||||||
<div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}>
|
<div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}>
|
||||||
{% if letter_head and not no_letterhead %}
|
{% if letter_head and not no_letterhead %}
|
||||||
<div class="letter-head">{{ letter_head }}</div>
|
<div class="letter-head">{{ letter_head }}</div>
|
||||||
@@ -163,4 +164,10 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="text-center" style="color: #98A1A9; font-size: 14px;">
|
||||||
|
You must generate IRN before you can preview GST E-Invoice.
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ def update_employee(employee, details, date=None, cancel=False):
|
|||||||
new_data = getdate(new_data)
|
new_data = getdate(new_data)
|
||||||
elif fieldtype =="Datetime" and new_data:
|
elif fieldtype =="Datetime" and new_data:
|
||||||
new_data = get_datetime(new_data)
|
new_data = get_datetime(new_data)
|
||||||
|
elif fieldtype in ["Currency", "Float"] and new_data:
|
||||||
|
new_data = flt(new_data)
|
||||||
setattr(employee, item.fieldname, new_data)
|
setattr(employee, item.fieldname, new_data)
|
||||||
if item.fieldname in ["department", "designation", "branch"]:
|
if item.fieldname in ["department", "designation", "branch"]:
|
||||||
internal_work_history[item.fieldname] = item.new
|
internal_work_history[item.fieldname] = item.new
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ def validate_eligibility(doc):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
invalid_company = not frappe.db.get_value('E Invoice User', { 'company': doc.get('company') })
|
invalid_company = not frappe.db.get_value('E Invoice User', { 'company': doc.get('company') })
|
||||||
|
invalid_company_gstin = not frappe.db.get_value('E Invoice User', {'gstin': doc.get('company_gstin')})
|
||||||
invalid_supply_type = doc.get('gst_category') not in ['Registered Regular', 'SEZ', 'Overseas', 'Deemed Export']
|
invalid_supply_type = doc.get('gst_category') not in ['Registered Regular', 'SEZ', 'Overseas', 'Deemed Export']
|
||||||
company_transaction = doc.get('billing_address_gstin') == doc.get('company_gstin')
|
company_transaction = doc.get('billing_address_gstin') == doc.get('company_gstin')
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ def validate_eligibility(doc):
|
|||||||
no_taxes_applied = not doc.get('taxes') and not doc.get('gst_category') == 'Overseas'
|
no_taxes_applied = not doc.get('taxes') and not doc.get('gst_category') == 'Overseas'
|
||||||
has_non_gst_item = any(d for d in doc.get('items', []) if d.get('is_non_gst'))
|
has_non_gst_item = any(d for d in doc.get('items', []) if d.get('is_non_gst'))
|
||||||
|
|
||||||
if invalid_company or invalid_supply_type or company_transaction or no_taxes_applied or has_non_gst_item:
|
if invalid_company or invalid_company_gstin or invalid_supply_type or company_transaction or no_taxes_applied or has_non_gst_item:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
@@ -306,7 +307,7 @@ def update_other_charges(tax_row, invoice_value_details, gst_accounts_list, invo
|
|||||||
|
|
||||||
def get_payment_details(invoice):
|
def get_payment_details(invoice):
|
||||||
payee_name = invoice.company
|
payee_name = invoice.company
|
||||||
mode_of_payment = ', '.join([d.mode_of_payment for d in invoice.payments])
|
mode_of_payment = ""
|
||||||
paid_amount = invoice.base_paid_amount
|
paid_amount = invoice.base_paid_amount
|
||||||
outstanding_amount = invoice.outstanding_amount
|
outstanding_amount = invoice.outstanding_amount
|
||||||
|
|
||||||
@@ -457,6 +458,8 @@ def make_einvoice(invoice):
|
|||||||
try:
|
try:
|
||||||
einvoice = safe_json_load(einvoice)
|
einvoice = safe_json_load(einvoice)
|
||||||
einvoice = santize_einvoice_fields(einvoice)
|
einvoice = santize_einvoice_fields(einvoice)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
raise
|
||||||
except Exception:
|
except Exception:
|
||||||
show_link_to_error_log(invoice, einvoice)
|
show_link_to_error_log(invoice, einvoice)
|
||||||
|
|
||||||
@@ -536,7 +539,14 @@ def safe_json_load(json_string):
|
|||||||
pos = e.pos
|
pos = e.pos
|
||||||
start, end = max(0, pos-20), min(len(json_string)-1, pos+20)
|
start, end = max(0, pos-20), min(len(json_string)-1, pos+20)
|
||||||
snippet = json_string[start:end]
|
snippet = json_string[start:end]
|
||||||
frappe.throw(_("Error in input data. Please check for any special characters near following input: <br> {}").format(snippet))
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Error in input data. Please check for any special characters near following input: <br> {}"
|
||||||
|
).format(snippet),
|
||||||
|
title=_("Invalid JSON"),
|
||||||
|
exc=e,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def throw_error_list(errors, title):
|
def throw_error_list(errors, title):
|
||||||
if len(errors) > 1:
|
if len(errors) > 1:
|
||||||
@@ -766,12 +776,13 @@ class GSPConnector():
|
|||||||
|
|
||||||
headers = self.get_headers()
|
headers = self.get_headers()
|
||||||
eway_bill_details = get_eway_bill_details(args)
|
eway_bill_details = get_eway_bill_details(args)
|
||||||
|
|
||||||
data = json.dumps({
|
data = json.dumps({
|
||||||
'Irn': args.irn,
|
'Irn': args.irn,
|
||||||
'Distance': cint(eway_bill_details.distance),
|
'Distance': cint(eway_bill_details.distance),
|
||||||
'TransMode': eway_bill_details.mode_of_transport,
|
'TransMode': eway_bill_details.mode_of_transport,
|
||||||
'TransId': eway_bill_details.gstin,
|
'TransId': eway_bill_details.gstin,
|
||||||
'TransName': eway_bill_details.transporter,
|
'TransName': eway_bill_details.name,
|
||||||
'TrnDocDt': eway_bill_details.document_date,
|
'TrnDocDt': eway_bill_details.document_date,
|
||||||
'TrnDocNo': eway_bill_details.document_name,
|
'TrnDocNo': eway_bill_details.document_name,
|
||||||
'VehNo': eway_bill_details.vehicle_no,
|
'VehNo': eway_bill_details.vehicle_no,
|
||||||
|
|||||||
@@ -32,6 +32,15 @@ class TestWarehouse(unittest.TestCase):
|
|||||||
self.assertEqual(p_warehouse.name, child_warehouse.parent_warehouse)
|
self.assertEqual(p_warehouse.name, child_warehouse.parent_warehouse)
|
||||||
self.assertEqual(child_warehouse.is_group, 0)
|
self.assertEqual(child_warehouse.is_group, 0)
|
||||||
|
|
||||||
|
def test_naming(self):
|
||||||
|
company = "Wind Power LLC"
|
||||||
|
warehouse_name = "Named Warehouse - WP"
|
||||||
|
wh = frappe.get_doc(doctype="Warehouse", warehouse_name=warehouse_name, company=company).insert()
|
||||||
|
self.assertEqual(wh.name, warehouse_name)
|
||||||
|
|
||||||
|
warehouse_name = "Unnamed Warehouse"
|
||||||
|
wh = frappe.get_doc(doctype="Warehouse", warehouse_name=warehouse_name, company=company).insert()
|
||||||
|
self.assertIn(warehouse_name, wh.name)
|
||||||
|
|
||||||
def create_warehouse(warehouse_name, properties=None, company=None):
|
def create_warehouse(warehouse_name, properties=None, company=None):
|
||||||
if not company:
|
if not company:
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ class Warehouse(NestedSet):
|
|||||||
suffix = " - " + frappe.get_cached_value('Company', self.company, "abbr")
|
suffix = " - " + frappe.get_cached_value('Company', self.company, "abbr")
|
||||||
if not self.warehouse_name.endswith(suffix):
|
if not self.warehouse_name.endswith(suffix):
|
||||||
self.name = self.warehouse_name + suffix
|
self.name = self.warehouse_name + suffix
|
||||||
else:
|
return
|
||||||
|
|
||||||
self.name = self.warehouse_name
|
self.name = self.warehouse_name
|
||||||
|
|
||||||
def onload(self):
|
def onload(self):
|
||||||
|
|||||||
@@ -368,7 +368,7 @@ class update_entries_after(object):
|
|||||||
batch = self.stock_queue[index]
|
batch = self.stock_queue[index]
|
||||||
if qty_to_pop >= batch[0]:
|
if qty_to_pop >= batch[0]:
|
||||||
# consume current batch
|
# consume current batch
|
||||||
qty_to_pop = qty_to_pop - batch[0]
|
qty_to_pop = _round_off_if_near_zero(qty_to_pop - batch[0])
|
||||||
self.stock_queue.pop(index)
|
self.stock_queue.pop(index)
|
||||||
if not self.stock_queue and qty_to_pop:
|
if not self.stock_queue and qty_to_pop:
|
||||||
# stock finished, qty still remains to be withdrawn
|
# stock finished, qty still remains to be withdrawn
|
||||||
@@ -382,8 +382,8 @@ class update_entries_after(object):
|
|||||||
batch[0] = batch[0] - qty_to_pop
|
batch[0] = batch[0] - qty_to_pop
|
||||||
qty_to_pop = 0
|
qty_to_pop = 0
|
||||||
|
|
||||||
stock_value = sum((flt(batch[0]) * flt(batch[1]) for batch in self.stock_queue))
|
stock_value = _round_off_if_near_zero(sum((flt(batch[0]) * flt(batch[1]) for batch in self.stock_queue)))
|
||||||
stock_qty = sum((flt(batch[0]) for batch in self.stock_queue))
|
stock_qty = _round_off_if_near_zero(sum((flt(batch[0]) for batch in self.stock_queue)))
|
||||||
|
|
||||||
if stock_qty:
|
if stock_qty:
|
||||||
self.valuation_rate = stock_value / flt(stock_qty)
|
self.valuation_rate = stock_value / flt(stock_qty)
|
||||||
@@ -549,3 +549,12 @@ def get_valuation_rate(item_code, warehouse, voucher_type, voucher_no,
|
|||||||
frappe.throw(msg=msg, title=_("Valuation Rate Missing"))
|
frappe.throw(msg=msg, title=_("Valuation Rate Missing"))
|
||||||
|
|
||||||
return valuation_rate
|
return valuation_rate
|
||||||
|
|
||||||
|
def _round_off_if_near_zero(number, precision = 7):
|
||||||
|
"""Rounds off the number to zero only if number is close to zero for decimal
|
||||||
|
specified in precision. Precision defaults to 7.
|
||||||
|
"""
|
||||||
|
if abs(0.0 - flt(number)) < (1.0 / (10**precision)):
|
||||||
|
return 0.0
|
||||||
|
|
||||||
|
return flt(number)
|
||||||
|
|||||||
Reference in New Issue
Block a user