Merge branch 'develop' into fix_create_item_tax_with_salespurchasetax

This commit is contained in:
Deepesh Garg 2021-02-26 10:43:15 +05:30 committed by GitHub
commit 28ca4ec79d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 196 additions and 85 deletions

View File

@ -61,8 +61,10 @@ class AccountingDimension(Document):
def on_update(self):
frappe.flags.accounting_dimensions = None
def make_dimension_in_accounting_doctypes(doc):
doclist = get_doctypes_with_dimensions()
def make_dimension_in_accounting_doctypes(doc, doclist=None):
if not doclist:
doclist = get_doctypes_with_dimensions()
doc_count = len(get_accounting_dimensions())
count = 0
@ -82,13 +84,13 @@ def make_dimension_in_accounting_doctypes(doc):
"owner": "Administrator"
}
if doctype == "Budget":
add_dimension_to_budget_doctype(df, doc)
else:
meta = frappe.get_meta(doctype, cached=False)
fieldnames = [d.fieldname for d in meta.get("fields")]
meta = frappe.get_meta(doctype, cached=False)
fieldnames = [d.fieldname for d in meta.get("fields")]
if df['fieldname'] not in fieldnames:
if df['fieldname'] not in fieldnames:
if doctype == "Budget":
add_dimension_to_budget_doctype(df.copy(), doc)
else:
create_custom_field(doctype, df)
count += 1
@ -178,15 +180,7 @@ def toggle_disabling(doc):
frappe.clear_cache(doctype=doctype)
def get_doctypes_with_dimensions():
doclist = ["GL Entry", "Sales Invoice", "POS Invoice", "Purchase Invoice", "Payment Entry", "Asset",
"Expense Claim", "Expense Claim Detail", "Expense Taxes and Charges", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note",
"Sales Invoice Item", "POS Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item",
"Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule",
"Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation",
"Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item", "Subscription",
"Subscription Plan"]
return doclist
return frappe.get_hooks("accounting_dimension_doctypes")
def get_accounting_dimensions(as_list=True):
if frappe.flags.accounting_dimensions is None:

View File

@ -136,7 +136,7 @@ class PricingRule(Document):
for d in self.items:
max_discount = frappe.get_cached_value("Item", d.item_code, "max_discount")
if max_discount and flt(self.discount_percentage) > flt(max_discount):
throw(_("Max discount allowed for item: {0} is {1}%").format(self.item_code, max_discount))
throw(_("Max discount allowed for item: {0} is {1}%").format(d.item_code, max_discount))
def validate_price_list_with_currency(self):
if self.currency and self.for_price_list:

View File

@ -10,6 +10,14 @@ frappe.ui.form.on('Subscription', {
}
}
});
frm.set_query('cost_center', function() {
return {
filters: {
company: frm.doc.company
}
};
});
},
refresh: function(frm) {

View File

@ -7,9 +7,10 @@
"engine": "InnoDB",
"field_order": [
"party_type",
"status",
"cb_1",
"party",
"cb_1",
"company",
"status",
"subscription_period",
"start_date",
"end_date",
@ -44,80 +45,107 @@
{
"allow_on_submit": 1,
"fieldname": "cb_1",
"fieldtype": "Column Break"
"fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "status",
"fieldtype": "Select",
"label": "Status",
"no_copy": 1,
"options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid\nCompleted",
"read_only": 1
"read_only": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "subscription_period",
"fieldtype": "Section Break",
"label": "Subscription Period"
"label": "Subscription Period",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "cancelation_date",
"fieldtype": "Date",
"label": "Cancelation Date",
"read_only": 1
"read_only": 1,
"show_days": 1,
"show_seconds": 1
},
{
"allow_on_submit": 1,
"fieldname": "trial_period_start",
"fieldtype": "Date",
"label": "Trial Period Start Date",
"set_only_once": 1
"set_only_once": 1,
"show_days": 1,
"show_seconds": 1
},
{
"depends_on": "eval:doc.trial_period_start",
"fieldname": "trial_period_end",
"fieldtype": "Date",
"label": "Trial Period End Date",
"set_only_once": 1
"set_only_once": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "column_break_11",
"fieldtype": "Column Break"
"fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "current_invoice_start",
"fieldtype": "Date",
"label": "Current Invoice Start Date",
"read_only": 1
"read_only": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "current_invoice_end",
"fieldtype": "Date",
"label": "Current Invoice End Date",
"read_only": 1
"read_only": 1,
"show_days": 1,
"show_seconds": 1
},
{
"default": "0",
"description": "Number of days that the subscriber has to pay invoices generated by this subscription",
"fieldname": "days_until_due",
"fieldtype": "Int",
"label": "Days Until Due"
"label": "Days Until Due",
"show_days": 1,
"show_seconds": 1
},
{
"default": "0",
"fieldname": "cancel_at_period_end",
"fieldtype": "Check",
"label": "Cancel At End Of Period"
"label": "Cancel At End Of Period",
"show_days": 1,
"show_seconds": 1
},
{
"default": "0",
"fieldname": "generate_invoice_at_period_start",
"fieldtype": "Check",
"label": "Generate Invoice At Beginning Of Period"
"label": "Generate Invoice At Beginning Of Period",
"show_days": 1,
"show_seconds": 1
},
{
"allow_on_submit": 1,
"fieldname": "sb_4",
"fieldtype": "Section Break",
"label": "Plans"
"label": "Plans",
"show_days": 1,
"show_seconds": 1
},
{
"allow_on_submit": 1,
@ -125,62 +153,84 @@
"fieldtype": "Table",
"label": "Plans",
"options": "Subscription Plan Detail",
"reqd": 1
"reqd": 1,
"show_days": 1,
"show_seconds": 1
},
{
"depends_on": "eval:['Customer', 'Supplier'].includes(doc.party_type)",
"fieldname": "sb_1",
"fieldtype": "Section Break",
"label": "Taxes"
"label": "Taxes",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "sb_2",
"fieldtype": "Section Break",
"label": "Discounts"
"label": "Discounts",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "apply_additional_discount",
"fieldtype": "Select",
"label": "Apply Additional Discount On",
"options": "\nGrand Total\nNet Total"
"options": "\nGrand Total\nNet Total",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "cb_2",
"fieldtype": "Column Break"
"fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "additional_discount_percentage",
"fieldtype": "Percent",
"label": "Additional DIscount Percentage"
"label": "Additional DIscount Percentage",
"show_days": 1,
"show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "additional_discount_amount",
"fieldtype": "Currency",
"label": "Additional DIscount Amount"
"label": "Additional DIscount Amount",
"show_days": 1,
"show_seconds": 1
},
{
"depends_on": "eval:doc.invoices",
"fieldname": "sb_3",
"fieldtype": "Section Break",
"label": "Invoices"
"label": "Invoices",
"show_days": 1,
"show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "invoices",
"fieldtype": "Table",
"label": "Invoices",
"options": "Subscription Invoice"
"options": "Subscription Invoice",
"show_days": 1,
"show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
"label": "Accounting Dimensions"
"label": "Accounting Dimensions",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
"fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "party_type",
@ -188,7 +238,9 @@
"label": "Party Type",
"options": "DocType",
"reqd": 1,
"set_only_once": 1
"set_only_once": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "party",
@ -197,21 +249,27 @@
"label": "Party",
"options": "party_type",
"reqd": 1,
"set_only_once": 1
"set_only_once": 1,
"show_days": 1,
"show_seconds": 1
},
{
"depends_on": "eval:doc.party_type === 'Customer'",
"fieldname": "sales_tax_template",
"fieldtype": "Link",
"label": "Sales Taxes and Charges Template",
"options": "Sales Taxes and Charges Template"
"options": "Sales Taxes and Charges Template",
"show_days": 1,
"show_seconds": 1
},
{
"depends_on": "eval:doc.party_type === 'Supplier'",
"fieldname": "purchase_tax_template",
"fieldtype": "Link",
"label": "Purchase Taxes and Charges Template",
"options": "Purchase Taxes and Charges Template"
"options": "Purchase Taxes and Charges Template",
"show_days": 1,
"show_seconds": 1
},
{
"default": "0",
@ -219,36 +277,55 @@
"fieldname": "follow_calendar_months",
"fieldtype": "Check",
"label": "Follow Calendar Months",
"set_only_once": 1
"set_only_once": 1,
"show_days": 1,
"show_seconds": 1
},
{
"default": "0",
"description": "New invoices will be generated as per schedule even if current invoices are unpaid or past due date",
"fieldname": "generate_new_invoices_past_due_date",
"fieldtype": "Check",
"label": "Generate New Invoices Past Due Date"
"label": "Generate New Invoices Past Due Date",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "end_date",
"fieldtype": "Date",
"label": "Subscription End Date",
"set_only_once": 1
"set_only_once": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "start_date",
"fieldtype": "Date",
"label": "Subscription Start Date",
"set_only_once": 1
"set_only_once": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
"options": "Cost Center"
"options": "Cost Center",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"show_days": 1,
"show_seconds": 1
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2020-06-25 10:52:52.265105",
"modified": "2021-02-09 15:44:20.024789",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Subscription",

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
@ -5,12 +6,13 @@
from __future__ import unicode_literals
import frappe
import erpnext
from frappe import _
from frappe.model.document import Document
from frappe.utils.data import nowdate, getdate, cstr, cint, add_days, date_diff, get_last_day, add_to_date, flt
from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_plan_rate
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
from erpnext import get_default_company
class Subscription(Document):
def before_insert(self):
@ -243,6 +245,7 @@ class Subscription(Document):
self.validate_plans_billing_cycle(self.get_billing_cycle_and_interval())
self.validate_end_date()
self.validate_to_follow_calendar_months()
self.cost_center = erpnext.get_default_cost_center(self.get('company'))
def validate_trial_period(self):
"""
@ -304,6 +307,14 @@ class Subscription(Document):
doctype = 'Sales Invoice' if self.party_type == 'Customer' else 'Purchase Invoice'
invoice = frappe.new_doc(doctype)
# For backward compatibility
# Earlier subscription didn't had any company field
company = self.get('company') or get_default_company()
if not company:
frappe.throw(_("Company is mandatory was generating invoice. Please set default company in Global Defaults"))
invoice.company = company
invoice.set_posting_time = 1
invoice.posting_date = self.current_invoice_start if self.generate_invoice_at_period_start \
else self.current_invoice_end
@ -330,6 +341,7 @@ class Subscription(Document):
# for that reason
items_list = self.get_items_from_plans(self.plans, prorate)
for item in items_list:
item['cost_center'] = self.cost_center
invoice.append('items', item)
# Taxes
@ -380,7 +392,8 @@ class Subscription(Document):
Returns the `Item`s linked to `Subscription Plan`
"""
if prorate:
prorate_factor = get_prorata_factor(self.current_invoice_end, self.current_invoice_start)
prorate_factor = get_prorata_factor(self.current_invoice_end, self.current_invoice_start,
self.generate_invoice_at_period_start)
items = []
party = self.party
@ -583,10 +596,13 @@ def get_calendar_months(billing_interval):
return calendar_months
def get_prorata_factor(period_end, period_start):
diff = flt(date_diff(nowdate(), period_start) + 1)
plan_days = flt(date_diff(period_end, period_start) + 1)
prorate_factor = diff / plan_days
def get_prorata_factor(period_end, period_start, is_prepaid):
if is_prepaid:
prorate_factor = 1
else:
diff = flt(date_diff(nowdate(), period_start) + 1)
plan_days = flt(date_diff(period_end, period_start) + 1)
prorate_factor = diff / plan_days
return prorate_factor

View File

@ -321,7 +321,8 @@ class TestSubscription(unittest.TestCase):
self.assertEqual(
flt(
get_prorata_factor(subscription.current_invoice_end, subscription.current_invoice_start),
get_prorata_factor(subscription.current_invoice_end, subscription.current_invoice_start,
subscription.generate_invoice_at_period_start),
2),
flt(prorate_factor, 2)
)
@ -561,9 +562,7 @@ class TestSubscription(unittest.TestCase):
current_inv = subscription.get_current_invoice()
self.assertEqual(current_inv.status, "Unpaid")
diff = flt(date_diff(nowdate(), subscription.current_invoice_start) + 1)
plan_days = flt(date_diff(subscription.current_invoice_end, subscription.current_invoice_start) + 1)
prorate_factor = flt(diff / plan_days)
prorate_factor = 1
self.assertEqual(flt(current_inv.grand_total, 2), flt(prorate_factor * 900, 2))

View File

@ -13,21 +13,28 @@
"fieldname": "document_type",
"fieldtype": "Link",
"label": "Document Type ",
"no_copy": 1,
"options": "DocType",
"read_only": 1
"read_only": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "invoice",
"fieldtype": "Dynamic Link",
"in_list_view": 1,
"label": "Invoice",
"no_copy": 1,
"options": "document_type",
"read_only": 1
"read_only": 1,
"show_days": 1,
"show_seconds": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-06-01 22:23:54.462718",
"modified": "2021-02-09 15:43:32.026233",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Subscription Invoice",

View File

@ -196,7 +196,7 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
if not round_off_gle:
for k in ["voucher_type", "voucher_no", "company",
"posting_date", "remarks", "is_opening"]:
"posting_date", "remarks"]:
round_off_gle[k] = gl_map[0][k]
round_off_gle.update({
@ -208,6 +208,7 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
"cost_center": round_off_cost_center,
"party_type": None,
"party": None,
"is_opening": "No",
"against_voucher_type": None,
"against_voucher": None
})

View File

@ -117,7 +117,7 @@ def call_mws_method(mws_method, *args, **kwargs):
return response
except Exception as e:
delay = math.pow(4, x) * 125
frappe.log_error(message=e, title=str(mws_method))
frappe.log_error(message=e, title=f'Method "{mws_method.__name__}" failed')
time.sleep(delay)
continue

View File

@ -393,6 +393,15 @@ payment_gateway_enabled = "erpnext.accounts.utils.create_payment_gateway_account
communication_doctypes = ["Customer", "Supplier"]
accounting_dimension_doctypes = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset",
"Expense Claim", "Expense Claim Detail", "Expense Taxes and Charges", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note",
"Sales Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item",
"Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule",
"Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation",
"Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item", "Subscription",
"Subscription Plan"
]
regional_overrides = {
'France': {
'erpnext.tests.test_regional.test_method': 'erpnext.regional.france.utils.test_method'

View File

@ -138,7 +138,7 @@
"idx": 1,
"issingle": 1,
"links": [],
"modified": "2020-08-27 14:30:28.995324",
"modified": "2021-02-25 12:31:14.947865",
"modified_by": "Administrator",
"module": "HR",
"name": "HR Settings",
@ -155,5 +155,6 @@
}
],
"sort_field": "modified",
"sort_order": "ASC"
}
"sort_order": "ASC",
"track_changes": 1
}

View File

@ -3,7 +3,7 @@
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"allow_rename": 1,
"autoname": "field:skill_name",
"beta": 0,
"creation": "2019-04-16 09:54:39.486915",
@ -56,7 +56,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-04-16 09:55:00.536328",
"modified": "2021-02-24 09:55:00.536328",
"modified_by": "Administrator",
"module": "HR",
"name": "Skill",
@ -110,4 +110,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -20,6 +20,7 @@
},
{
"columns": 6,
"fetch_from": "task.subject",
"fieldname": "subject",
"fieldtype": "Read Only",
"in_list_view": 1,
@ -28,7 +29,7 @@
],
"istable": 1,
"links": [],
"modified": "2021-01-07 15:13:40.995071",
"modified": "2021-02-24 15:18:49.095071",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project Template Task",

View File

@ -212,8 +212,7 @@
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Represents Company",
"options": "Company",
"unique": 1
"options": "Company"
},
{
"depends_on": "represents_company",
@ -500,7 +499,7 @@
"image_field": "image",
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-01-27 12:54:57.258959",
"modified": "2021-01-28 12:54:57.258959",
"modified_by": "Administrator",
"module": "Selling",
"name": "Customer",

View File

@ -521,8 +521,7 @@
"fieldname": "has_variants",
"fieldtype": "Check",
"in_standard_filter": 1,
"label": "Has Variants",
"no_copy": 1
"label": "Has Variants"
},
{
"default": "Item Attribute",
@ -538,7 +537,6 @@
"fieldtype": "Table",
"hidden": 1,
"label": "Attributes",
"no_copy": 1,
"options": "Item Variant Attribute"
},
{
@ -1068,7 +1066,7 @@
"index_web_pages_for_search": 1,
"links": [],
"max_attachments": 1,
"modified": "2021-01-25 20:49:50.222976",
"modified": "2021-02-18 14:00:19.668049",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",

View File

@ -276,9 +276,10 @@ class StockEntry(StockController):
item_wise_qty.setdefault(d.item_code, []).append(d.qty)
for item_code, qty_list in iteritems(item_wise_qty):
if self.fg_completed_qty != sum(qty_list):
total = flt(sum(qty_list), frappe.get_precision("Stock Entry Detail", "qty"))
if self.fg_completed_qty != total:
frappe.throw(_("The finished product {0} quantity {1} and For Quantity {2} cannot be different")
.format(frappe.bold(item_code), frappe.bold(sum(qty_list)), frappe.bold(self.fg_completed_qty)))
.format(frappe.bold(item_code), frappe.bold(total), frappe.bold(self.fg_completed_qty)))
def validate_difference_account(self):
if not cint(erpnext.is_perpetual_inventory_enabled(self.company)):