mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-17 22:05:10 +00:00
Merge branch 'v12-pre-release' into version-12
This commit is contained in:
14
.github/workflows/docker-release.yml
vendored
Normal file
14
.github/workflows/docker-release.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: Trigger Docker build on release
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
jobs:
|
||||
curl:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: alpine:latest
|
||||
steps:
|
||||
- name: curl
|
||||
run: |
|
||||
apk add curl bash
|
||||
curl -s -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Travis-API-Version: 3" -H "Authorization: token ${{ secrets.TRAVIS_CI_TOKEN }}" -d '{"request":{"branch":"master"}}' https://api.travis-ci.com/repo/frappe%2Ffrappe_docker/requests
|
||||
@@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '12.10.1'
|
||||
__version__ = '12.11.0'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
||||
@@ -244,6 +244,8 @@ class Account(NestedSet):
|
||||
|
||||
super(Account, self).on_trash(True)
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql("""select name from tabAccount
|
||||
where is_group = 1 and docstatus != 2 and company = %s
|
||||
|
||||
@@ -225,7 +225,7 @@ def build_tree_from_json(chart_template, chart_data=None):
|
||||
|
||||
account['parent_account'] = parent
|
||||
account['expandable'] = True if identify_is_group(child) else False
|
||||
account['value'] = (child.get('account_number') + ' - ' + account_name) \
|
||||
account['value'] = (cstr(child.get('account_number')).strip() + ' - ' + account_name) \
|
||||
if child.get('account_number') else account_name
|
||||
accounts.append(account)
|
||||
_import_accounts(child, account['value'])
|
||||
|
||||
@@ -1,210 +1,210 @@
|
||||
{
|
||||
"creation": "2013-06-24 15:49:57",
|
||||
"description": "Settings for Accounts",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Other",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"auto_accounting_for_stock",
|
||||
"acc_frozen_upto",
|
||||
"frozen_accounts_modifier",
|
||||
"determine_address_tax_category_from",
|
||||
"over_billing_allowance",
|
||||
"column_break_4",
|
||||
"credit_controller",
|
||||
"check_supplier_invoice_uniqueness",
|
||||
"make_payment_via_journal_entry",
|
||||
"unlink_payment_on_cancellation_of_invoice",
|
||||
"unlink_advance_payment_on_cancelation_of_order",
|
||||
"book_asset_depreciation_entry_automatically",
|
||||
"allow_cost_center_in_entry_of_bs_account",
|
||||
"add_taxes_from_item_tax_template",
|
||||
"automatically_fetch_payment_terms",
|
||||
"print_settings",
|
||||
"show_inclusive_tax_in_print",
|
||||
"column_break_12",
|
||||
"show_payment_schedule_in_print",
|
||||
"currency_exchange_section",
|
||||
"allow_stale",
|
||||
"stale_days",
|
||||
"report_settings_sb",
|
||||
"use_custom_cash_flow"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"default": "1",
|
||||
"description": "If enabled, the system will post accounting entries for inventory automatically.",
|
||||
"fieldname": "auto_accounting_for_stock",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Make Accounting Entry For Every Stock Movement"
|
||||
},
|
||||
{
|
||||
"description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",
|
||||
"fieldname": "acc_frozen_upto",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Accounts Frozen Upto"
|
||||
},
|
||||
{
|
||||
"description": "Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts",
|
||||
"fieldname": "frozen_accounts_modifier",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
|
||||
"options": "Role"
|
||||
},
|
||||
{
|
||||
"default": "Billing Address",
|
||||
"description": "Address used to determine Tax Category in transactions.",
|
||||
"fieldname": "determine_address_tax_category_from",
|
||||
"fieldtype": "Select",
|
||||
"label": "Determine Address Tax Category From",
|
||||
"options": "Billing Address\nShipping Address"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"description": "Role that is allowed to submit transactions that exceed credit limits set.",
|
||||
"fieldname": "credit_controller",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Credit Controller",
|
||||
"options": "Role"
|
||||
},
|
||||
{
|
||||
"fieldname": "check_supplier_invoice_uniqueness",
|
||||
"fieldtype": "Check",
|
||||
"label": "Check Supplier Invoice Number Uniqueness"
|
||||
},
|
||||
{
|
||||
"fieldname": "make_payment_via_journal_entry",
|
||||
"fieldtype": "Check",
|
||||
"label": "Make Payment via Journal Entry"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "unlink_payment_on_cancellation_of_invoice",
|
||||
"fieldtype": "Check",
|
||||
"label": "Unlink Payment on Cancellation of Invoice"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "unlink_advance_payment_on_cancelation_of_order",
|
||||
"fieldtype": "Check",
|
||||
"label": "Unlink Advance Payment on Cancelation of Order"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "book_asset_depreciation_entry_automatically",
|
||||
"fieldtype": "Check",
|
||||
"label": "Book Asset Depreciation Entry Automatically"
|
||||
},
|
||||
{
|
||||
"fieldname": "allow_cost_center_in_entry_of_bs_account",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow Cost Center In Entry of Balance Sheet Account"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "add_taxes_from_item_tax_template",
|
||||
"fieldtype": "Check",
|
||||
"label": "Automatically Add Taxes and Charges from Item Tax Template"
|
||||
},
|
||||
{
|
||||
"fieldname": "print_settings",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Print Settings"
|
||||
},
|
||||
{
|
||||
"fieldname": "show_inclusive_tax_in_print",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Inclusive Tax In Print"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_12",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "show_payment_schedule_in_print",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Payment Schedule in Print"
|
||||
},
|
||||
{
|
||||
"fieldname": "currency_exchange_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Currency Exchange Settings"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "allow_stale",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Allow Stale Exchange Rates"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "eval:doc.allow_stale==0",
|
||||
"fieldname": "stale_days",
|
||||
"fieldtype": "Int",
|
||||
"label": "Stale Days"
|
||||
},
|
||||
{
|
||||
"fieldname": "report_settings_sb",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Report Settings"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Only select if you have setup Cash Flow Mapper documents",
|
||||
"fieldname": "use_custom_cash_flow",
|
||||
"fieldtype": "Check",
|
||||
"label": "Use Custom Cash Flow Format"
|
||||
},
|
||||
{
|
||||
"fieldname": "automatically_fetch_payment_terms",
|
||||
"fieldtype": "Check",
|
||||
"label": "Automatically Fetch Payment Terms"
|
||||
},
|
||||
{
|
||||
"description": "Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.",
|
||||
"fieldname": "over_billing_allowance",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Over Billing Allowance (%)"
|
||||
}
|
||||
],
|
||||
"icon": "icon-cog",
|
||||
"idx": 1,
|
||||
"issingle": 1,
|
||||
"modified": "2019-07-04 18:20:55.789946",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"role": "Accounts Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Sales User"
|
||||
},
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Purchase User"
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_order": "ASC",
|
||||
"track_changes": 1
|
||||
"creation": "2013-06-24 15:49:57",
|
||||
"description": "Settings for Accounts",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Other",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"auto_accounting_for_stock",
|
||||
"acc_frozen_upto",
|
||||
"frozen_accounts_modifier",
|
||||
"determine_address_tax_category_from",
|
||||
"over_billing_allowance",
|
||||
"column_break_4",
|
||||
"credit_controller",
|
||||
"check_supplier_invoice_uniqueness",
|
||||
"make_payment_via_journal_entry",
|
||||
"unlink_payment_on_cancellation_of_invoice",
|
||||
"unlink_advance_payment_on_cancelation_of_order",
|
||||
"book_asset_depreciation_entry_automatically",
|
||||
"add_taxes_from_item_tax_template",
|
||||
"automatically_fetch_payment_terms",
|
||||
"print_settings",
|
||||
"show_inclusive_tax_in_print",
|
||||
"column_break_12",
|
||||
"show_payment_schedule_in_print",
|
||||
"currency_exchange_section",
|
||||
"allow_stale",
|
||||
"stale_days",
|
||||
"report_settings_sb",
|
||||
"use_custom_cash_flow"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"default": "1",
|
||||
"description": "If enabled, the system will post accounting entries for inventory automatically.",
|
||||
"fieldname": "auto_accounting_for_stock",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Make Accounting Entry For Every Stock Movement"
|
||||
},
|
||||
{
|
||||
"description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",
|
||||
"fieldname": "acc_frozen_upto",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Accounts Frozen Upto"
|
||||
},
|
||||
{
|
||||
"description": "Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts",
|
||||
"fieldname": "frozen_accounts_modifier",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
|
||||
"options": "Role"
|
||||
},
|
||||
{
|
||||
"default": "Billing Address",
|
||||
"description": "Address used to determine Tax Category in transactions.",
|
||||
"fieldname": "determine_address_tax_category_from",
|
||||
"fieldtype": "Select",
|
||||
"label": "Determine Address Tax Category From",
|
||||
"options": "Billing Address\nShipping Address"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"description": "Role that is allowed to submit transactions that exceed credit limits set.",
|
||||
"fieldname": "credit_controller",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Credit Controller",
|
||||
"options": "Role"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "check_supplier_invoice_uniqueness",
|
||||
"fieldtype": "Check",
|
||||
"label": "Check Supplier Invoice Number Uniqueness"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "make_payment_via_journal_entry",
|
||||
"fieldtype": "Check",
|
||||
"label": "Make Payment via Journal Entry"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "unlink_payment_on_cancellation_of_invoice",
|
||||
"fieldtype": "Check",
|
||||
"label": "Unlink Payment on Cancellation of Invoice"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "unlink_advance_payment_on_cancelation_of_order",
|
||||
"fieldtype": "Check",
|
||||
"label": "Unlink Advance Payment on Cancelation of Order"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "book_asset_depreciation_entry_automatically",
|
||||
"fieldtype": "Check",
|
||||
"label": "Book Asset Depreciation Entry Automatically"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "add_taxes_from_item_tax_template",
|
||||
"fieldtype": "Check",
|
||||
"label": "Automatically Add Taxes and Charges from Item Tax Template"
|
||||
},
|
||||
{
|
||||
"fieldname": "print_settings",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Print Settings"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "show_inclusive_tax_in_print",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Inclusive Tax In Print"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_12",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "show_payment_schedule_in_print",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Payment Schedule in Print"
|
||||
},
|
||||
{
|
||||
"fieldname": "currency_exchange_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Currency Exchange Settings"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "allow_stale",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Allow Stale Exchange Rates"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"depends_on": "eval:doc.allow_stale==0",
|
||||
"fieldname": "stale_days",
|
||||
"fieldtype": "Int",
|
||||
"label": "Stale Days"
|
||||
},
|
||||
{
|
||||
"fieldname": "report_settings_sb",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Report Settings"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Only select if you have setup Cash Flow Mapper documents",
|
||||
"fieldname": "use_custom_cash_flow",
|
||||
"fieldtype": "Check",
|
||||
"label": "Use Custom Cash Flow Format"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "automatically_fetch_payment_terms",
|
||||
"fieldtype": "Check",
|
||||
"label": "Automatically Fetch Payment Terms"
|
||||
},
|
||||
{
|
||||
"description": "Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.",
|
||||
"fieldname": "over_billing_allowance",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Over Billing Allowance (%)"
|
||||
}
|
||||
],
|
||||
"icon": "icon-cog",
|
||||
"idx": 1,
|
||||
"issingle": 1,
|
||||
"modified": "2020-03-11 13:09:26.235848",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"role": "Accounts Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Sales User"
|
||||
},
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Purchase User"
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "ASC",
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -20,7 +20,6 @@ class AccountsSettings(Document):
|
||||
|
||||
self.validate_stale_days()
|
||||
self.enable_payment_schedule_in_print()
|
||||
self.enable_fields_for_cost_center_settings()
|
||||
|
||||
def validate_stale_days(self):
|
||||
if not self.allow_stale and cint(self.stale_days) <= 0:
|
||||
@@ -33,8 +32,3 @@ class AccountsSettings(Document):
|
||||
for doctype in ("Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"):
|
||||
make_property_setter(doctype, "due_date", "print_hide", show_in_print, "Check")
|
||||
make_property_setter(doctype, "payment_schedule", "print_hide", 0 if show_in_print else 1, "Check")
|
||||
|
||||
def enable_fields_for_cost_center_settings(self):
|
||||
show_field = 0 if cint(self.allow_cost_center_in_entry_of_bs_account) else 1
|
||||
for doctype in ("Sales Invoice", "Purchase Invoice", "Payment Entry"):
|
||||
make_property_setter(doctype, "cost_center", "hidden", show_field, "Check")
|
||||
|
||||
@@ -60,12 +60,13 @@ class BankReconciliation(Document):
|
||||
""".format(condition=condition), {"account": self.account, "from":self.from_date,
|
||||
"to": self.to_date, "bank_account": self.bank_account}, as_dict=1)
|
||||
|
||||
pos_entries = []
|
||||
|
||||
pos_sales_invoices, pos_purchase_invoices = [], []
|
||||
if self.include_pos_transactions:
|
||||
pos_entries = frappe.db.sql("""
|
||||
pos_sales_invoices = frappe.db.sql("""
|
||||
select
|
||||
"Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit,
|
||||
si.posting_date, si.debit_to as against_account, sip.clearance_date,
|
||||
si.posting_date, si.customer as against_account, sip.clearance_date,
|
||||
account.account_currency, 0 as credit
|
||||
from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account
|
||||
where
|
||||
@@ -75,7 +76,20 @@ class BankReconciliation(Document):
|
||||
si.posting_date ASC, si.name DESC
|
||||
""", {"account":self.account, "from":self.from_date, "to":self.to_date}, as_dict=1)
|
||||
|
||||
entries = sorted(list(payment_entries)+list(journal_entries+list(pos_entries)),
|
||||
pos_purchase_invoices = frappe.db.sql("""
|
||||
select
|
||||
"Purchase Invoice" as payment_document, pi.name as payment_entry, pi.paid_amount as credit,
|
||||
pi.posting_date, pi.supplier as against_account, pi.clearance_date,
|
||||
account.account_currency, 0 as debit
|
||||
from `tabPurchase Invoice` pi, `tabAccount` account
|
||||
where
|
||||
pi.cash_bank_account=%(account)s and pi.docstatus=1 and account.name = pi.cash_bank_account
|
||||
and pi.posting_date >= %(from)s and pi.posting_date <= %(to)s
|
||||
order by
|
||||
pi.posting_date ASC, pi.name DESC
|
||||
""", {"account": self.account, "from": self.from_date, "to": self.to_date}, as_dict=1)
|
||||
|
||||
entries = sorted(list(payment_entries) + list(journal_entries + list(pos_sales_invoices) + list(pos_purchase_invoices)),
|
||||
key=lambda k: k['posting_date'] or getdate(nowdate()))
|
||||
|
||||
self.set('payment_entries', [])
|
||||
|
||||
@@ -60,8 +60,13 @@ frappe.ui.form.on('Cost Center', {
|
||||
"label": "Cost Center Number",
|
||||
"fieldname": "cost_center_number",
|
||||
"fieldtype": "Data",
|
||||
"reqd": 1,
|
||||
"default": frm.doc.cost_center_number
|
||||
},
|
||||
{
|
||||
"label": __("Merge with existing"),
|
||||
"fieldname": "merge",
|
||||
"fieldtype": "Check",
|
||||
"default": 0
|
||||
}
|
||||
],
|
||||
primary_action: function() {
|
||||
@@ -76,8 +81,9 @@ frappe.ui.form.on('Cost Center', {
|
||||
args: {
|
||||
docname: frm.doc.name,
|
||||
cost_center_name: data.cost_center_name,
|
||||
cost_center_number: data.cost_center_number,
|
||||
company: frm.doc.company
|
||||
cost_center_number: cstr(data.cost_center_number),
|
||||
company: frm.doc.company,
|
||||
merge: data.merge
|
||||
},
|
||||
callback: function(r) {
|
||||
frappe.dom.unfreeze();
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
"idx": 1,
|
||||
"is_tree": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-29 16:09:30.025214",
|
||||
"modified": "2020-06-12 16:09:30.025214",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Cost Center",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
from frappe import _
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||
from frappe.utils import flt, fmt_money, getdate, formatdate, cint
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.naming import set_name_from_naming_options
|
||||
from frappe.model.meta import get_field_precision
|
||||
@@ -75,12 +75,6 @@ class GLEntry(Document):
|
||||
if not self.cost_center and self.voucher_type != 'Period Closing Voucher':
|
||||
frappe.throw(_("{0} {1}: Cost Center is required for 'Profit and Loss' account {2}. Please set up a default Cost Center for the Company.")
|
||||
.format(self.voucher_type, self.voucher_no, self.account))
|
||||
else:
|
||||
from erpnext.accounts.utils import get_allow_cost_center_in_entry_of_bs_account
|
||||
if not get_allow_cost_center_in_entry_of_bs_account() and self.cost_center:
|
||||
self.cost_center = None
|
||||
if self.project:
|
||||
self.project = None
|
||||
|
||||
def validate_dimensions_for_pl_and_bs(self):
|
||||
|
||||
@@ -137,10 +131,17 @@ class GLEntry(Document):
|
||||
|
||||
return self.cost_center_company[self.cost_center]
|
||||
|
||||
def _check_is_group():
|
||||
return cint(frappe.get_cached_value('Cost Center', self.cost_center, 'is_group'))
|
||||
|
||||
if self.cost_center and _get_cost_center_company() != self.company:
|
||||
frappe.throw(_("{0} {1}: Cost Center {2} does not belong to Company {3}")
|
||||
.format(self.voucher_type, self.voucher_no, self.cost_center, self.company))
|
||||
|
||||
if self.cost_center and _check_is_group():
|
||||
frappe.throw(_("""{0} {1}: Cost Center {2} is a group cost center and group cost centers cannot
|
||||
be used in transactions""").format(self.voucher_type, self.voucher_no, frappe.bold(self.cost_center)))
|
||||
|
||||
def validate_party(self):
|
||||
validate_party_frozen_disabled(self.party_type, self.party)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
import frappe, json, erpnext
|
||||
from frappe import _
|
||||
from frappe.utils import flt, getdate, nowdate, add_days
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
@@ -134,16 +134,19 @@ class InvoiceDiscounting(AccountsController):
|
||||
je.append("accounts", {
|
||||
"account": self.bank_account,
|
||||
"debit_in_account_currency": flt(self.total_amount) - flt(self.bank_charges),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company)
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.bank_charges_account,
|
||||
"debit_in_account_currency": flt(self.bank_charges)
|
||||
"debit_in_account_currency": flt(self.bank_charges),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company)
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.short_term_loan,
|
||||
"credit_in_account_currency": flt(self.total_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name
|
||||
})
|
||||
@@ -151,6 +154,7 @@ class InvoiceDiscounting(AccountsController):
|
||||
je.append("accounts", {
|
||||
"account": self.accounts_receivable_discounted,
|
||||
"debit_in_account_currency": flt(d.outstanding_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
"party_type": "Customer",
|
||||
@@ -160,6 +164,7 @@ class InvoiceDiscounting(AccountsController):
|
||||
je.append("accounts", {
|
||||
"account": self.accounts_receivable_credit,
|
||||
"credit_in_account_currency": flt(d.outstanding_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
"party_type": "Customer",
|
||||
@@ -177,13 +182,15 @@ class InvoiceDiscounting(AccountsController):
|
||||
je.append("accounts", {
|
||||
"account": self.short_term_loan,
|
||||
"debit_in_account_currency": flt(self.total_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.bank_account,
|
||||
"credit_in_account_currency": flt(self.total_amount)
|
||||
"credit_in_account_currency": flt(self.total_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company)
|
||||
})
|
||||
|
||||
if getdate(self.loan_end_date) > getdate(nowdate()):
|
||||
@@ -193,6 +200,7 @@ class InvoiceDiscounting(AccountsController):
|
||||
je.append("accounts", {
|
||||
"account": self.accounts_receivable_discounted,
|
||||
"credit_in_account_currency": flt(outstanding_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
"party_type": "Customer",
|
||||
@@ -202,6 +210,7 @@ class InvoiceDiscounting(AccountsController):
|
||||
je.append("accounts", {
|
||||
"account": self.accounts_receivable_unpaid,
|
||||
"debit_in_account_currency": flt(outstanding_amount),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"reference_type": "Invoice Discounting",
|
||||
"reference_name": self.name,
|
||||
"party_type": "Customer",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
{
|
||||
"doctype": "Item Tax Template",
|
||||
"title": "_Test Account Excise Duty @ 10",
|
||||
"company": "_Test Company",
|
||||
"taxes": [
|
||||
{
|
||||
"doctype": "Item Tax Template Detail",
|
||||
@@ -14,6 +15,7 @@
|
||||
{
|
||||
"doctype": "Item Tax Template",
|
||||
"title": "_Test Account Excise Duty @ 12",
|
||||
"company": "_Test Company",
|
||||
"taxes": [
|
||||
{
|
||||
"doctype": "Item Tax Template Detail",
|
||||
@@ -26,6 +28,7 @@
|
||||
{
|
||||
"doctype": "Item Tax Template",
|
||||
"title": "_Test Account Excise Duty @ 15",
|
||||
"company": "_Test Company",
|
||||
"taxes": [
|
||||
{
|
||||
"doctype": "Item Tax Template Detail",
|
||||
@@ -38,6 +41,7 @@
|
||||
{
|
||||
"doctype": "Item Tax Template",
|
||||
"title": "_Test Account Excise Duty @ 20",
|
||||
"company": "_Test Company",
|
||||
"taxes": [
|
||||
{
|
||||
"doctype": "Item Tax Template Detail",
|
||||
@@ -50,6 +54,7 @@
|
||||
{
|
||||
"doctype": "Item Tax Template",
|
||||
"title": "_Test Item Tax Template 1",
|
||||
"company": "_Test Company",
|
||||
"taxes": [
|
||||
{
|
||||
"doctype": "Item Tax Template Detail",
|
||||
|
||||
@@ -836,13 +836,34 @@ def get_opening_accounts(company):
|
||||
return [{"account": a, "balance": get_balance_on(a)} for a in accounts]
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
|
||||
from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
|
||||
where jv_detail.parent = jv.name and jv_detail.account = %s and ifnull(jv_detail.party, '') = %s
|
||||
and (jv_detail.reference_type is null or jv_detail.reference_type = '')
|
||||
and jv.docstatus = 1 and jv.`{0}` like %s order by jv.name desc limit %s, %s""".format(searchfield),
|
||||
(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
|
||||
if not frappe.db.has_column('Journal Entry', searchfield):
|
||||
return []
|
||||
|
||||
return frappe.db.sql("""
|
||||
SELECT jv.name, jv.posting_date, jv.user_remark
|
||||
FROM `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
|
||||
WHERE jv_detail.parent = jv.name
|
||||
AND jv_detail.account = %(account)s
|
||||
AND IFNULL(jv_detail.party, '') = %(party)s
|
||||
AND (
|
||||
jv_detail.reference_type IS NULL
|
||||
OR jv_detail.reference_type = ''
|
||||
)
|
||||
AND jv.docstatus = 1
|
||||
AND jv.`{0}` LIKE %(txt)s
|
||||
ORDER BY jv.name DESC
|
||||
LIMIT %(offset)s, %(limit)s
|
||||
""".format(searchfield), dict(
|
||||
account=filters.get("account"),
|
||||
party=cstr(filters.get("party")),
|
||||
txt="%{0}%".format(txt),
|
||||
offset=start,
|
||||
limit=page_len
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
@@ -204,11 +204,8 @@ class TestJournalEntry(unittest.TestCase):
|
||||
self.assertEqual(jv.inter_company_journal_entry_reference, "")
|
||||
self.assertEqual(jv1.inter_company_journal_entry_reference, "")
|
||||
|
||||
def test_jv_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
def test_jv_with_cost_centre(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, cost_center = cost_center, save=False)
|
||||
@@ -237,15 +234,45 @@ class TestJournalEntry(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
def test_jv_with_project(self):
|
||||
from erpnext.projects.doctype.project.test_project import make_project
|
||||
project = make_project({
|
||||
'project_name': 'Journal Entry Project',
|
||||
'project_template_name': 'Test Project Template',
|
||||
'start_date': '2020-01-01'
|
||||
})
|
||||
|
||||
def test_jv_account_and_party_balance_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, save=False)
|
||||
for d in jv.accounts:
|
||||
d.project = project.project_name
|
||||
jv.voucher_type = "Bank Entry"
|
||||
jv.multi_currency = 0
|
||||
jv.cheque_no = "112233"
|
||||
jv.cheque_date = nowdate()
|
||||
jv.insert()
|
||||
jv.submit()
|
||||
|
||||
expected_values = {
|
||||
"_Test Cash - _TC": {
|
||||
"project": project.project_name
|
||||
},
|
||||
"_Test Bank - _TC": {
|
||||
"project": project.project_name
|
||||
}
|
||||
}
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, project, debit, credit
|
||||
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
|
||||
order by account asc""", jv.name, as_dict=1)
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["project"], gle.project)
|
||||
|
||||
def test_jv_account_and_party_balance_with_cost_centre(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, cost_center = cost_center, save=False)
|
||||
@@ -261,9 +288,6 @@ class TestJournalEntry(unittest.TestCase):
|
||||
account_balance = get_balance_on(account="_Test Bank - _TC", cost_center=cost_center)
|
||||
self.assertEqual(expected_account_balance, account_balance)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
|
||||
def make_journal_entry(account1, account2, amount, cost_center=None, posting_date=None, exchange_rate=1, save=True, submit=False, project=None):
|
||||
if not cost_center:
|
||||
cost_center = "_Test Cost Center - _TC"
|
||||
|
||||
@@ -68,6 +68,9 @@ class OpeningInvoiceCreationTool(Document):
|
||||
if not self.company:
|
||||
frappe.throw(_("Please select the Company"))
|
||||
|
||||
company_details = frappe.get_cached_value('Company', self.company,
|
||||
["default_currency", "default_letter_head"], as_dict=1) or {}
|
||||
|
||||
for row in self.invoices:
|
||||
if not row.qty:
|
||||
row.qty = 1.0
|
||||
@@ -99,6 +102,12 @@ class OpeningInvoiceCreationTool(Document):
|
||||
if not args:
|
||||
continue
|
||||
|
||||
if company_details:
|
||||
args.update({
|
||||
"currency": company_details.get("default_currency"),
|
||||
"letter_head": company_details.get("default_letter_head")
|
||||
})
|
||||
|
||||
doc = frappe.get_doc(args).insert()
|
||||
doc.submit()
|
||||
names.append(doc.name)
|
||||
@@ -172,8 +181,7 @@ class OpeningInvoiceCreationTool(Document):
|
||||
"due_date": row.due_date,
|
||||
"posting_date": row.posting_date,
|
||||
frappe.scrub(party_type): row.party,
|
||||
"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice",
|
||||
"currency": frappe.get_cached_value('Company', self.company, "default_currency")
|
||||
"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice"
|
||||
})
|
||||
|
||||
accounting_dimension = get_accounting_dimensions()
|
||||
|
||||
@@ -25,7 +25,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
});
|
||||
frm.set_query("party_type", function() {
|
||||
return{
|
||||
"filters": {
|
||||
filters: {
|
||||
"name": ["in", Object.keys(frappe.boot.party_account_types)],
|
||||
}
|
||||
}
|
||||
@@ -33,14 +33,16 @@ frappe.ui.form.on('Payment Entry', {
|
||||
frm.set_query("party_bank_account", function() {
|
||||
return {
|
||||
filters: {
|
||||
"is_company_account":0
|
||||
is_company_account: 0,
|
||||
party_type: frm.doc.party_type,
|
||||
party: frm.doc.party
|
||||
}
|
||||
}
|
||||
});
|
||||
frm.set_query("bank_account", function() {
|
||||
return {
|
||||
filters: {
|
||||
"is_company_account":1
|
||||
is_company_account: 1
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -326,7 +328,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
() => {
|
||||
frm.set_party_account_based_on_party = false;
|
||||
if (r.message.bank_account) {
|
||||
frm.set_value("party_bank_account", r.message.bank_account);
|
||||
frm.set_value("bank_account", r.message.bank_account);
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -6,7 +6,7 @@ from __future__ import unicode_literals
|
||||
import frappe, erpnext, json
|
||||
from frappe import _, scrub, ValidationError
|
||||
from frappe.utils import flt, comma_or, nowdate, getdate
|
||||
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on, get_allow_cost_center_in_entry_of_bs_account
|
||||
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on
|
||||
from erpnext.accounts.party import get_party_account
|
||||
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
@@ -657,7 +657,7 @@ def get_outstanding_reference_documents(args):
|
||||
.format(frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"]))
|
||||
|
||||
# Add cost center condition
|
||||
if args.get("cost_center") and get_allow_cost_center_in_entry_of_bs_account():
|
||||
if args.get("cost_center"):
|
||||
condition += " and cost_center='%s'" % args.get("cost_center")
|
||||
|
||||
date_fields_dict = {
|
||||
|
||||
@@ -462,11 +462,8 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
||||
self.assertEqual(outstanding_amount, 0)
|
||||
|
||||
def test_payment_entry_against_sales_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
def test_payment_entry_against_sales_invoice_with_cost_centre(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
|
||||
@@ -501,39 +498,8 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
|
||||
def test_payment_entry_against_sales_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
si = create_sales_invoice(debit_to="Debtors - _TC")
|
||||
|
||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
|
||||
|
||||
pe.reference_no = "112211-2"
|
||||
pe.reference_date = nowdate()
|
||||
pe.paid_to = "_Test Bank - _TC"
|
||||
pe.paid_amount = si.grand_total
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
|
||||
debit_in_account_currency, credit_in_account_currency
|
||||
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
|
||||
order by account asc""", pe.name, as_dict=1)
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(gle.cost_center, None)
|
||||
|
||||
def test_payment_entry_against_purchase_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
def test_payment_entry_against_purchase_invoice_with_cost_center(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
|
||||
@@ -568,40 +534,9 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
|
||||
def test_payment_entry_against_purchase_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
pi = make_purchase_invoice(credit_to="Creditors - _TC")
|
||||
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
||||
|
||||
pe.reference_no = "112222-2"
|
||||
pe.reference_date = nowdate()
|
||||
pe.paid_from = "_Test Bank - _TC"
|
||||
pe.paid_amount = pi.grand_total
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
|
||||
debit_in_account_currency, credit_in_account_currency
|
||||
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
|
||||
order by account asc""", pe.name, as_dict=1)
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(gle.cost_center, None)
|
||||
|
||||
def test_payment_entry_account_and_party_balance_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
def test_payment_entry_account_and_party_balance_with_cost_center(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
|
||||
@@ -632,9 +567,6 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
self.assertEqual(expected_party_balance, party_balance)
|
||||
self.assertEqual(expected_party_account_balance, party_account_balance)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
|
||||
def create_payment_terms_template():
|
||||
|
||||
create_payment_term('Basic Amount Receivable')
|
||||
|
||||
@@ -26,6 +26,8 @@ class PaymentOrder(Document):
|
||||
for d in self.references:
|
||||
frappe.db.set_value(self.payment_order_type, d.get(frappe.scrub(self.payment_order_type)), ref_field, status)
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_mop_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql(""" select mode_of_payment from `tabPayment Order Reference`
|
||||
where parent = %(parent)s and mode_of_payment like %(txt)s
|
||||
@@ -36,6 +38,8 @@ def get_mop_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
'txt': "%%%s%%" % txt
|
||||
})
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_supplier_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql(""" select supplier from `tabPayment Order Reference`
|
||||
where parent = %(parent)s and supplier like %(txt)s and
|
||||
@@ -86,4 +90,4 @@ def make_journal_entry(doc, supplier, mode_of_payment=None):
|
||||
|
||||
je.flags.ignore_mandatory = True
|
||||
je.save()
|
||||
frappe.msgprint(_("{0} {1} created").format(je.doctype, je.name))
|
||||
frappe.msgprint(_("{0} {1} created").format(je.doctype, je.name))
|
||||
|
||||
@@ -73,6 +73,10 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
this.frm.set_value('party_type', '');
|
||||
this.frm.set_value('party', '');
|
||||
this.frm.set_value('receivable_payable_account', '');
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
|
||||
@@ -48,7 +48,8 @@ class PaymentReconciliation(Document):
|
||||
select
|
||||
"Journal Entry" as reference_type, t1.name as reference_name,
|
||||
t1.posting_date, t1.remark as remarks, t2.name as reference_row,
|
||||
{dr_or_cr} as amount, t2.is_advance
|
||||
{dr_or_cr} as amount, t2.is_advance,
|
||||
t2.account_currency as currency
|
||||
from
|
||||
`tabJournal Entry` t1, `tabJournal Entry Account` t2
|
||||
where
|
||||
@@ -88,7 +89,8 @@ class PaymentReconciliation(Document):
|
||||
if self.party_type == 'Customer' else "Purchase Invoice")
|
||||
|
||||
return frappe.db.sql(""" SELECT `tab{doc}`.name as reference_name, %(voucher_type)s as reference_type,
|
||||
(sum(`tabGL Entry`.{dr_or_cr}) - sum(`tabGL Entry`.{reconciled_dr_or_cr})) as amount
|
||||
(sum(`tabGL Entry`.{dr_or_cr}) - sum(`tabGL Entry`.{reconciled_dr_or_cr})) as amount,
|
||||
account_currency as currency
|
||||
FROM `tab{doc}`, `tabGL Entry`
|
||||
WHERE
|
||||
(`tab{doc}`.name = `tabGL Entry`.against_voucher or `tab{doc}`.name = `tabGL Entry`.voucher_no)
|
||||
@@ -101,10 +103,10 @@ class PaymentReconciliation(Document):
|
||||
Having
|
||||
amount > 0
|
||||
""".format(
|
||||
doc=voucher_type,
|
||||
dr_or_cr=dr_or_cr,
|
||||
reconciled_dr_or_cr=reconciled_dr_or_cr,
|
||||
party_type_field=frappe.scrub(self.party_type)),
|
||||
doc=voucher_type,
|
||||
dr_or_cr=dr_or_cr,
|
||||
reconciled_dr_or_cr=reconciled_dr_or_cr,
|
||||
party_type_field=frappe.scrub(self.party_type)),
|
||||
{
|
||||
'party': self.party,
|
||||
'party_type': self.party_type,
|
||||
@@ -141,6 +143,7 @@ class PaymentReconciliation(Document):
|
||||
ent.invoice_number = e.get('voucher_no')
|
||||
ent.invoice_date = e.get('posting_date')
|
||||
ent.amount = flt(e.get('invoice_amount'))
|
||||
ent.currency = e.get('currency')
|
||||
ent.outstanding_amount = e.get('outstanding_amount')
|
||||
|
||||
def reconcile(self, args):
|
||||
@@ -170,7 +173,7 @@ class PaymentReconciliation(Document):
|
||||
reconcile_against_document(lst)
|
||||
|
||||
if dr_or_cr_notes:
|
||||
reconcile_dr_cr_note(dr_or_cr_notes)
|
||||
reconcile_dr_cr_note(dr_or_cr_notes, self.company)
|
||||
|
||||
msgprint(_("Successfully Reconciled"))
|
||||
self.get_unreconciled_entries()
|
||||
@@ -261,7 +264,7 @@ class PaymentReconciliation(Document):
|
||||
|
||||
return cond
|
||||
|
||||
def reconcile_dr_cr_note(dr_cr_notes):
|
||||
def reconcile_dr_cr_note(dr_cr_notes, company):
|
||||
for d in dr_cr_notes:
|
||||
voucher_type = ('Credit Note'
|
||||
if d.voucher_type == 'Sales Invoice' else 'Debit Note')
|
||||
@@ -269,10 +272,14 @@ def reconcile_dr_cr_note(dr_cr_notes):
|
||||
reconcile_dr_or_cr = ('debit_in_account_currency'
|
||||
if d.dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency')
|
||||
|
||||
company_currency = erpnext.get_company_currency(company)
|
||||
|
||||
jv = frappe.get_doc({
|
||||
"doctype": "Journal Entry",
|
||||
"voucher_type": voucher_type,
|
||||
"posting_date": today(),
|
||||
"company": company,
|
||||
"multi_currency": 1 if d.currency != company_currency else 0,
|
||||
"accounts": [
|
||||
{
|
||||
'account': d.account,
|
||||
@@ -280,7 +287,8 @@ def reconcile_dr_cr_note(dr_cr_notes):
|
||||
'party_type': d.party_type,
|
||||
d.dr_or_cr: abs(d.allocated_amount),
|
||||
'reference_type': d.against_voucher_type,
|
||||
'reference_name': d.against_voucher
|
||||
'reference_name': d.against_voucher,
|
||||
'cost_center': erpnext.get_default_cost_center(company)
|
||||
},
|
||||
{
|
||||
'account': d.account,
|
||||
@@ -289,7 +297,8 @@ def reconcile_dr_cr_note(dr_cr_notes):
|
||||
reconcile_dr_or_cr: (abs(d.allocated_amount)
|
||||
if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)),
|
||||
'reference_type': d.voucher_type,
|
||||
'reference_name': d.voucher_no
|
||||
'reference_name': d.voucher_no,
|
||||
'cost_center': erpnext.get_default_cost_center(company)
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
@@ -1,183 +1,80 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2014-07-09 16:14:23.672922",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"actions": [],
|
||||
"creation": "2014-07-09 16:14:23.672922",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"invoice_type",
|
||||
"invoice_number",
|
||||
"invoice_date",
|
||||
"col_break1",
|
||||
"amount",
|
||||
"outstanding_amount",
|
||||
"currency"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "invoice_type",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Sales Invoice\nPurchase Invoice\nJournal Entry",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "invoice_type",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice Type",
|
||||
"options": "Sales Invoice\nPurchase Invoice\nJournal Entry",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "invoice_number",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice Number",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "invoice_type",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "invoice_number",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice Number",
|
||||
"options": "invoice_type",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "invoice_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "invoice_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Invoice Date",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
"options": "currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "outstanding_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Outstanding Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
"fieldname": "outstanding_amount",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Outstanding Amount",
|
||||
"options": "currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"label": "Currency",
|
||||
"options": "Currency"
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-11 03:28:03.588476",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation Invoice",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_seen": 0
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-07-19 18:12:27.964073",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation Invoice",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2014-07-09 16:13:35.452759",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"reference_type",
|
||||
"reference_name",
|
||||
@@ -16,7 +18,8 @@
|
||||
"difference_account",
|
||||
"difference_amount",
|
||||
"sec_break1",
|
||||
"remark"
|
||||
"remark",
|
||||
"currency"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -73,6 +76,7 @@
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
"options": "currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@@ -81,6 +85,7 @@
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Allocated amount",
|
||||
"options": "currency",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
@@ -106,16 +111,25 @@
|
||||
"fieldname": "difference_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Difference Amount",
|
||||
"options": "currency",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"label": "Currency",
|
||||
"options": "Currency"
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2019-06-24 00:08:11.150796",
|
||||
"links": [],
|
||||
"modified": "2020-07-19 18:12:41.682347",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation Payment",
|
||||
|
||||
@@ -140,9 +140,6 @@ class PaymentRequest(Document):
|
||||
})
|
||||
|
||||
def set_as_paid(self):
|
||||
if frappe.session.user == "Guest":
|
||||
frappe.set_user("Administrator")
|
||||
|
||||
payment_entry = self.create_payment_entry()
|
||||
self.make_invoice()
|
||||
|
||||
@@ -254,7 +251,7 @@ class PaymentRequest(Document):
|
||||
|
||||
if status in ["Authorized", "Completed"]:
|
||||
redirect_to = None
|
||||
self.run_method("set_as_paid")
|
||||
self.set_as_paid()
|
||||
|
||||
# if shopping cart enabled and in session
|
||||
if (shopping_cart_settings.enabled and hasattr(frappe.local, "session")
|
||||
|
||||
@@ -115,6 +115,8 @@ def get_item_groups(pos_profile):
|
||||
def get_series():
|
||||
return frappe.get_meta("Sales Invoice").get_field("naming_series").options or ""
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
user = frappe.session['user']
|
||||
company = filters.get('company') or frappe.defaults.get_user_default('company')
|
||||
|
||||
@@ -17,6 +17,8 @@ from six import string_types
|
||||
apply_on_dict = {"Item Code": "items",
|
||||
"Item Group": "item_groups", "Brand": "brands"}
|
||||
|
||||
other_fields = ["other_item_code", "other_item_group", "other_brand"]
|
||||
|
||||
class PricingRule(Document):
|
||||
def validate(self):
|
||||
self.validate_mandatory()
|
||||
@@ -51,6 +53,13 @@ class PricingRule(Document):
|
||||
if tocheck and not self.get(tocheck):
|
||||
throw(_("{0} is required").format(self.meta.get_label(tocheck)), frappe.MandatoryError)
|
||||
|
||||
if self.apply_rule_on_other:
|
||||
o_field = 'other_' + frappe.scrub(self.apply_rule_on_other)
|
||||
if not self.get(o_field) and o_field in other_fields:
|
||||
frappe.throw(_("For the 'Apply Rule On Other' condition the field {0} is mandatory")
|
||||
.format(frappe.bold(self.apply_rule_on_other)))
|
||||
|
||||
|
||||
if self.price_or_product_discount == 'Price' and not self.rate_or_discount:
|
||||
throw(_("Rate or Discount is required for the price discount."), frappe.MandatoryError)
|
||||
|
||||
@@ -84,13 +93,27 @@ class PricingRule(Document):
|
||||
for f in options:
|
||||
if not f: continue
|
||||
|
||||
f = frappe.scrub(f)
|
||||
if f!=fieldname:
|
||||
self.set(f, None)
|
||||
scrubbed_f = frappe.scrub(f)
|
||||
|
||||
if logic_field == 'apply_on':
|
||||
apply_on_f = apply_on_dict.get(f, f)
|
||||
else:
|
||||
apply_on_f = scrubbed_f
|
||||
|
||||
if scrubbed_f != fieldname:
|
||||
self.set(apply_on_f, None)
|
||||
|
||||
if self.mixed_conditions and self.get("same_item"):
|
||||
self.same_item = 0
|
||||
|
||||
apply_rule_on_other = frappe.scrub(self.apply_rule_on_other or "")
|
||||
|
||||
cleanup_other_fields = (other_fields if not apply_rule_on_other
|
||||
else [o_field for o_field in other_fields if o_field != 'other_' + apply_rule_on_other])
|
||||
|
||||
for other_field in cleanup_other_fields:
|
||||
self.set(other_field, None)
|
||||
|
||||
def validate_rate_or_discount(self):
|
||||
for field in ["Rate"]:
|
||||
if flt(self.get(frappe.scrub(field))) < 0:
|
||||
@@ -248,7 +271,7 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=Fa
|
||||
|
||||
if pricing_rule.coupon_code_based==1 and args.coupon_code==None:
|
||||
return item_details
|
||||
|
||||
|
||||
if not pricing_rule.validate_applied_rule:
|
||||
if pricing_rule.price_or_product_discount == "Price":
|
||||
apply_price_discount_rule(pricing_rule, item_details, args)
|
||||
@@ -257,7 +280,7 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=Fa
|
||||
|
||||
item_details.has_pricing_rule = 1
|
||||
|
||||
item_details.pricing_rules = ','.join([d.pricing_rule for d in rules])
|
||||
item_details.pricing_rules = frappe.as_json([d.pricing_rule for d in rules])
|
||||
|
||||
if not doc: return item_details
|
||||
|
||||
@@ -347,7 +370,7 @@ def set_discount_amount(rate, item_details):
|
||||
|
||||
def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None):
|
||||
from erpnext.accounts.doctype.pricing_rule.utils import get_pricing_rule_items
|
||||
for d in pricing_rules.split(','):
|
||||
for d in json.loads(pricing_rules):
|
||||
if not d or not frappe.db.exists("Pricing Rule", d): continue
|
||||
pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
|
||||
|
||||
@@ -413,14 +436,15 @@ def make_pricing_rule(doctype, docname):
|
||||
|
||||
return doc
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_item_uoms(doctype, txt, searchfield, start, page_len, filters):
|
||||
items = [filters.get('value')]
|
||||
if filters.get('apply_on') != 'Item Code':
|
||||
field = frappe.scrub(filters.get('apply_on'))
|
||||
items = [d.name for d in frappe.db.get_all("Item", filters={field: filters.get('value')})]
|
||||
|
||||
items = frappe.db.sql_list("""select name
|
||||
from `tabItem` where {0} = %s""".format(field), filters.get('value'))
|
||||
|
||||
return frappe.get_all('UOM Conversion Detail',
|
||||
filters = {'parent': ('in', items), 'uom': ("like", "{0}%".format(txt))},
|
||||
fields = ["distinct uom"], as_list=1)
|
||||
return frappe.get_all('UOM Conversion Detail', filters={
|
||||
'parent': ('in', items),
|
||||
'uom': ("like", "{0}%".format(txt))
|
||||
}, fields = ["distinct uom"], as_list=1)
|
||||
|
||||
@@ -11,6 +11,7 @@ import json
|
||||
from six import string_types
|
||||
|
||||
import frappe
|
||||
from erpnext.accounts.doctype.pricing_rule.pricing_rule import set_transaction_type
|
||||
from erpnext.setup.doctype.item_group.item_group import get_child_item_groups
|
||||
from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses
|
||||
from erpnext.stock.get_item_details import get_conversion_factor, get_default_income_account
|
||||
@@ -322,7 +323,9 @@ def apply_internal_priority(pricing_rules, field_set, args):
|
||||
filtered_rules = []
|
||||
for field in field_set:
|
||||
if args.get(field):
|
||||
filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules)
|
||||
# filter function always returns a filter object even if empty
|
||||
# list conversion is necessary to check for an empty result
|
||||
filtered_rules = list(filter(lambda x: x.get(field)==args.get(field), pricing_rules))
|
||||
if filtered_rules: break
|
||||
|
||||
return filtered_rules or pricing_rules
|
||||
@@ -416,9 +419,28 @@ def apply_pricing_rule_on_transaction(doc):
|
||||
values = {}
|
||||
conditions = get_other_conditions(conditions, values, doc)
|
||||
|
||||
pricing_rules = frappe.db.sql(""" Select `tabPricing Rule`.* from `tabPricing Rule`
|
||||
where {conditions} and `tabPricing Rule`.disable = 0
|
||||
""".format(conditions = conditions), values, as_dict=1)
|
||||
args = frappe._dict({
|
||||
'doctype': doc.doctype,
|
||||
'transaction_type': None,
|
||||
})
|
||||
set_transaction_type(args)
|
||||
tran_type_condition = '{} = 1'.format(args.transaction_type)
|
||||
|
||||
sql = """
|
||||
SELECT
|
||||
`tabPricing Rule`.*
|
||||
FROM
|
||||
`tabPricing Rule`
|
||||
WHERE
|
||||
{conditions} and
|
||||
{tran_type_condition} and
|
||||
`tabPricing Rule`.disable = 0
|
||||
""".format(
|
||||
conditions=conditions,
|
||||
tran_type_condition=tran_type_condition,
|
||||
)
|
||||
|
||||
pricing_rules = frappe.db.sql(sql, values, as_dict=1)
|
||||
|
||||
if pricing_rules:
|
||||
pricing_rules = filter_pricing_rules_for_qty_amount(doc.total_qty,
|
||||
@@ -449,7 +471,7 @@ def apply_pricing_rule_on_transaction(doc):
|
||||
doc.set_missing_values()
|
||||
|
||||
def get_applied_pricing_rules(item_row):
|
||||
return (item_row.get("pricing_rules").split(',')
|
||||
return (json.loads(item_row.get("pricing_rules"))
|
||||
if item_row.get("pricing_rules") else [])
|
||||
|
||||
def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None):
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-05-21 16:16:39",
|
||||
@@ -26,6 +25,7 @@
|
||||
"accounting_dimensions_section",
|
||||
"cost_center",
|
||||
"dimension_col_break",
|
||||
"project",
|
||||
"sb_14",
|
||||
"on_hold",
|
||||
"release_date",
|
||||
@@ -963,8 +963,10 @@
|
||||
{
|
||||
"fieldname": "clearance_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 1,
|
||||
"label": "Clearance Date"
|
||||
"label": "Clearance Date",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "col_br_payments",
|
||||
@@ -1233,6 +1235,7 @@
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "subscription_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Subscription Section",
|
||||
@@ -1286,6 +1289,12 @@
|
||||
"fieldname": "dimension_col_break",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "project",
|
||||
"fieldtype": "Link",
|
||||
"label": "Project",
|
||||
"options": "Project"
|
||||
},
|
||||
{
|
||||
"fieldname": "tax_withholding_category",
|
||||
"fieldtype": "Link",
|
||||
@@ -1298,8 +1307,7 @@
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 204,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-18 13:05:25.199832",
|
||||
"modified": "2020-08-20 11:08:19.611710",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
|
||||
@@ -413,6 +413,8 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
self.make_tax_gl_entries(gl_entries)
|
||||
|
||||
gl_entries = make_regional_gl_entries(gl_entries, self)
|
||||
|
||||
gl_entries = merge_similar_entries(gl_entries)
|
||||
|
||||
self.make_payment_gl_entries(gl_entries)
|
||||
@@ -451,7 +453,8 @@ class PurchaseInvoice(BuyingController):
|
||||
if self.party_account_currency==self.company_currency else grand_total,
|
||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": self.project
|
||||
}, self.party_account_currency, item=self)
|
||||
)
|
||||
|
||||
@@ -492,7 +495,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"debit": warehouse_debit_amount,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, account_currency, item=item)
|
||||
)
|
||||
|
||||
@@ -505,7 +508,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"cost_center": item.cost_center,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"credit": flt(amount),
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
# sub-contracting warehouse
|
||||
@@ -518,6 +521,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"account": supplier_warehouse_account,
|
||||
"against": item.expense_account,
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project or self.project,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"credit": flt(item.rm_supp_cost)
|
||||
}, warehouse_account[self.supplier_warehouse]["account_currency"], item=item))
|
||||
@@ -536,7 +540,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"against": self.supplier,
|
||||
"debit": amount,
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, account_currency, item=item))
|
||||
|
||||
# If asset is bought through this document and not linked to PR
|
||||
@@ -549,7 +553,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"cost_center": item.cost_center,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"credit": flt(item.landed_cost_voucher_amount),
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
@@ -558,7 +562,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"cost_center": item.cost_center,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"debit": flt(item.landed_cost_voucher_amount),
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
# update gross amount of asset bought through this document
|
||||
@@ -584,7 +588,8 @@ class PurchaseInvoice(BuyingController):
|
||||
"against": self.supplier,
|
||||
"debit": flt(item.item_tax_amount, item.precision("item_tax_amount")),
|
||||
"remarks": self.remarks or "Accounting Entry for Stock",
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": item.project or self.project
|
||||
}, item=item)
|
||||
)
|
||||
|
||||
@@ -613,7 +618,8 @@ class PurchaseInvoice(BuyingController):
|
||||
"debit": base_asset_amount,
|
||||
"debit_in_account_currency": (base_asset_amount
|
||||
if arbnb_currency == self.company_currency else asset_amount),
|
||||
"cost_center": item.cost_center
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
if item.item_tax_amount:
|
||||
@@ -623,6 +629,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"against": self.supplier,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project or self.project,
|
||||
"credit": item.item_tax_amount,
|
||||
"credit_in_account_currency": (item.item_tax_amount
|
||||
if asset_eiiav_currency == self.company_currency else
|
||||
@@ -639,7 +646,8 @@ class PurchaseInvoice(BuyingController):
|
||||
"debit": base_asset_amount,
|
||||
"debit_in_account_currency": (base_asset_amount
|
||||
if cwip_account_currency == self.company_currency else asset_amount),
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
if item.item_tax_amount and not cint(erpnext.is_perpetual_inventory_enabled(self.company)):
|
||||
@@ -650,6 +658,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||
"cost_center": item.cost_center,
|
||||
"credit": item.item_tax_amount,
|
||||
"project": item.project or self.project,
|
||||
"credit_in_account_currency": (item.item_tax_amount
|
||||
if asset_eiiav_currency == self.company_currency else
|
||||
item.item_tax_amount / self.conversion_rate)
|
||||
@@ -665,7 +674,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"cost_center": item.cost_center,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"credit": flt(item.landed_cost_voucher_amount),
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
@@ -674,7 +683,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"cost_center": item.cost_center,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"debit": flt(item.landed_cost_voucher_amount),
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, item=item))
|
||||
|
||||
# update gross amount of assets bought through this document
|
||||
@@ -709,7 +718,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"debit": stock_adjustment_amt,
|
||||
"remarks": self.get("remarks") or _("Stock Adjustment"),
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project
|
||||
"project": item.project or self.project
|
||||
}, account_currency, item=item)
|
||||
)
|
||||
|
||||
@@ -801,7 +810,8 @@ class PurchaseInvoice(BuyingController):
|
||||
if self.party_account_currency==self.company_currency else self.paid_amount,
|
||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": self.project
|
||||
}, self.party_account_currency, item=self)
|
||||
)
|
||||
|
||||
@@ -833,7 +843,8 @@ class PurchaseInvoice(BuyingController):
|
||||
if self.party_account_currency==self.company_currency else self.write_off_amount,
|
||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": self.project
|
||||
}, self.party_account_currency, item=self)
|
||||
)
|
||||
gl_entries.append(
|
||||
@@ -980,7 +991,7 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
# calculate totals again after applying TDS
|
||||
self.calculate_taxes_and_totals()
|
||||
|
||||
|
||||
def set_status(self, update=False, status=None, update_modified=True):
|
||||
if self.is_new():
|
||||
if self.get('amended_from'):
|
||||
@@ -1026,6 +1037,10 @@ def get_list_context(context=None):
|
||||
})
|
||||
return list_context
|
||||
|
||||
@erpnext.allow_regional
|
||||
def make_regional_gl_entries(gl_entries, doc):
|
||||
return gl_entries
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_debit_note(source_name, target_doc=None):
|
||||
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||
|
||||
@@ -16,7 +16,7 @@ frappe.listview_settings['Purchase Invoice'] = {
|
||||
} else if(frappe.datetime.get_diff(doc.due_date) < 0) {
|
||||
return [__("Overdue"), "red", "outstanding_amount,>,0|due_date,<,Today"];
|
||||
} else {
|
||||
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due,>=,Today"];
|
||||
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due_date,>=,Today"];
|
||||
}
|
||||
} else if(cint(doc.is_return)) {
|
||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||
|
||||
@@ -15,6 +15,7 @@ from erpnext.controllers.accounts_controller import get_payment_terms
|
||||
from erpnext.exceptions import InvalidCurrency
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_transaction
|
||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
||||
from erpnext.projects.doctype.project.test_project import make_project
|
||||
|
||||
test_dependencies = ["Item", "Cost Center", "Payment Term", "Payment Terms Template"]
|
||||
test_ignore = ["Serial No"]
|
||||
@@ -434,6 +435,8 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_total_purchase_cost_for_project(self):
|
||||
make_project({'project_name':'_Test Project'})
|
||||
|
||||
existing_purchase_cost = frappe.db.sql("""select sum(base_net_amount)
|
||||
from `tabPurchase Invoice Item` where project = '_Test Project' and docstatus=1""")
|
||||
existing_purchase_cost = existing_purchase_cost and existing_purchase_cost[0][0] or 0
|
||||
@@ -807,11 +810,8 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
pi_doc = frappe.get_doc('Purchase Invoice', pi.name)
|
||||
self.assertEqual(pi_doc.outstanding_amount, 0)
|
||||
|
||||
def test_purchase_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
def test_purchase_invoice_with_cost_center(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
|
||||
@@ -837,13 +837,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
|
||||
def test_purchase_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
def test_purchase_invoice_without_cost_center(self):
|
||||
cost_center = "_Test Cost Center - _TC"
|
||||
pi = make_purchase_invoice(credit_to="Creditors - _TC")
|
||||
|
||||
@@ -866,6 +860,42 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
def test_purchase_invoice_with_project_link(self):
|
||||
project = make_project({
|
||||
'project_name': 'Purchase Invoice Project',
|
||||
'project_template_name': 'Test Project Template',
|
||||
'start_date': '2020-01-01'
|
||||
})
|
||||
item_project = make_project({
|
||||
'project_name': 'Purchase Invoice Item Project',
|
||||
'project_template_name': 'Test Project Template',
|
||||
'start_date': '2019-06-01'
|
||||
})
|
||||
|
||||
pi = make_purchase_invoice(credit_to="Creditors - _TC" ,do_not_save=1)
|
||||
pi.items[0].project = item_project.project_name
|
||||
pi.project = project.project_name
|
||||
|
||||
pi.submit()
|
||||
|
||||
expected_values = {
|
||||
"Creditors - _TC": {
|
||||
"project": project.project_name
|
||||
},
|
||||
"_Test Account Cost for Goods Sold - _TC": {
|
||||
"project": item_project.project_name
|
||||
}
|
||||
}
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, cost_center, project, account_currency, debit, credit,
|
||||
debit_in_account_currency, credit_in_account_currency
|
||||
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
|
||||
order by account asc""", pi.name, as_dict=1)
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["project"], gle.project)
|
||||
|
||||
def unlink_payment_on_cancel_of_invoice(enable=1):
|
||||
accounts_settings = frappe.get_doc("Accounts Settings")
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "hash",
|
||||
"creation": "2013-05-22 12:43:10",
|
||||
"doctype": "DocType",
|
||||
@@ -86,6 +85,7 @@
|
||||
"item_tax_rate",
|
||||
"bom",
|
||||
"include_exploded_items",
|
||||
"purchase_invoice_item",
|
||||
"col_break6",
|
||||
"purchase_order",
|
||||
"po_detail",
|
||||
@@ -764,12 +764,21 @@
|
||||
"label": "Asset Category",
|
||||
"options": "Asset Category",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:parent.update_stock == 1",
|
||||
"fieldname": "purchase_invoice_item",
|
||||
"fieldtype": "Data",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Purchase Invoice Item",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-07 18:34:35.104178",
|
||||
"modified": "2020-06-30 16:48:01.398356",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Item",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-05-24 19:29:05",
|
||||
@@ -1494,6 +1493,7 @@
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "subscription_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Subscription Section"
|
||||
@@ -1569,8 +1569,7 @@
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 181,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-05-19 17:00:57.208696",
|
||||
"modified": "2020-07-01 12:41:29.484813",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
||||
@@ -786,7 +786,8 @@ class SalesInvoice(SellingController):
|
||||
if self.party_account_currency==self.company_currency else grand_total,
|
||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": self.project
|
||||
}, self.party_account_currency, item=self)
|
||||
)
|
||||
|
||||
@@ -841,7 +842,8 @@ class SalesInvoice(SellingController):
|
||||
"credit_in_account_currency": (flt(item.base_net_amount, item.precision("base_net_amount"))
|
||||
if account_currency==self.company_currency
|
||||
else flt(item.net_amount, item.precision("net_amount"))),
|
||||
"cost_center": item.cost_center
|
||||
"cost_center": item.cost_center,
|
||||
"project": item.project or self.project
|
||||
}, account_currency, item=item)
|
||||
)
|
||||
|
||||
@@ -922,7 +924,8 @@ class SalesInvoice(SellingController):
|
||||
if self.party_account_currency==self.company_currency else flt(self.change_amount),
|
||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": self.project
|
||||
}, self.party_account_currency, item=self)
|
||||
)
|
||||
|
||||
@@ -955,7 +958,8 @@ class SalesInvoice(SellingController):
|
||||
else flt(self.write_off_amount, self.precision("write_off_amount"))),
|
||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
"cost_center": self.cost_center
|
||||
"cost_center": self.cost_center,
|
||||
"project": self.project
|
||||
}, self.party_account_currency, item=self)
|
||||
)
|
||||
gl_entries.append(
|
||||
@@ -1105,7 +1109,10 @@ class SalesInvoice(SellingController):
|
||||
expiry_date=self.posting_date, include_expired_entry=True)
|
||||
if lp_details and getdate(lp_details.from_date) <= getdate(self.posting_date) and \
|
||||
(not lp_details.to_date or getdate(lp_details.to_date) >= getdate(self.posting_date)):
|
||||
points_earned = cint(eligible_amount/lp_details.collection_factor)
|
||||
|
||||
collection_factor = lp_details.collection_factor if lp_details.collection_factor else 1.0
|
||||
points_earned = cint(eligible_amount/collection_factor)
|
||||
|
||||
doc = frappe.get_doc({
|
||||
"doctype": "Loyalty Point Entry",
|
||||
"company": self.company,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"company": "_Test Company",
|
||||
"conversion_rate": 1.0,
|
||||
"currency": "INR",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"customer": "_Test Customer",
|
||||
"customer_name": "_Test Customer",
|
||||
"debit_to": "_Test Receivable - _TC",
|
||||
@@ -37,7 +38,8 @@
|
||||
"charge_type": "On Net Total",
|
||||
"description": "VAT",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"parentfield": "taxes",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"rate": 6
|
||||
},
|
||||
{
|
||||
@@ -45,7 +47,8 @@
|
||||
"charge_type": "On Net Total",
|
||||
"description": "Service Tax",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"parentfield": "taxes",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"rate": 6.36
|
||||
}
|
||||
],
|
||||
@@ -76,6 +79,7 @@
|
||||
"customer_name": "_Test Customer",
|
||||
"debit_to": "_Test Receivable - _TC",
|
||||
"doctype": "Sales Invoice",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"items": [
|
||||
{
|
||||
"amount": 500.0,
|
||||
@@ -107,7 +111,8 @@
|
||||
"charge_type": "On Net Total",
|
||||
"description": "VAT",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"parentfield": "taxes",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"rate": 16
|
||||
},
|
||||
{
|
||||
@@ -115,7 +120,8 @@
|
||||
"charge_type": "On Net Total",
|
||||
"description": "Service Tax",
|
||||
"doctype": "Sales Taxes and Charges",
|
||||
"parentfield": "taxes",
|
||||
"parentfield": "taxes",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"rate": 10
|
||||
}
|
||||
],
|
||||
@@ -132,6 +138,7 @@
|
||||
"customer_name": "_Test Customer",
|
||||
"debit_to": "_Test Receivable - _TC",
|
||||
"doctype": "Sales Invoice",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"items": [
|
||||
{
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
@@ -259,6 +266,7 @@
|
||||
"customer_name": "_Test Customer",
|
||||
"debit_to": "_Test Receivable - _TC",
|
||||
"doctype": "Sales Invoice",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"items": [
|
||||
{
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
|
||||
@@ -206,10 +206,19 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
"rate": 14,
|
||||
'included_in_print_rate': 1
|
||||
})
|
||||
si.append("taxes", {
|
||||
"charge_type": "On Item Quantity",
|
||||
"account_head": "_Test Account Education Cess - _TC",
|
||||
"cost_center": "_Test Cost Center - _TC",
|
||||
"description": "CESS",
|
||||
"rate": 5,
|
||||
'included_in_print_rate': 1
|
||||
})
|
||||
si.insert()
|
||||
|
||||
# with inclusive tax
|
||||
self.assertEqual(si.net_total, 4385.96)
|
||||
self.assertEqual(si.items[0].net_amount, 3947.368421052631)
|
||||
self.assertEqual(si.net_total, 3947.37)
|
||||
self.assertEqual(si.grand_total, 5000)
|
||||
|
||||
si.reload()
|
||||
@@ -222,8 +231,8 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
si.save()
|
||||
|
||||
# with inclusive tax and additional discount
|
||||
self.assertEqual(si.net_total, 4285.96)
|
||||
self.assertEqual(si.grand_total, 4885.99)
|
||||
self.assertEqual(si.net_total, 3847.37)
|
||||
self.assertEqual(si.grand_total, 4886)
|
||||
|
||||
si.reload()
|
||||
|
||||
@@ -235,7 +244,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
si.save()
|
||||
|
||||
# with inclusive tax and additional discount
|
||||
self.assertEqual(si.net_total, 4298.25)
|
||||
self.assertEqual(si.net_total, 3859.65)
|
||||
self.assertEqual(si.grand_total, 4900.00)
|
||||
|
||||
def test_sales_invoice_discount_amount(self):
|
||||
@@ -1575,11 +1584,8 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
si_doc = frappe.get_doc('Sales Invoice', si.name)
|
||||
self.assertEqual(si_doc.outstanding_amount, 0)
|
||||
|
||||
def test_sales_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
def test_sales_invoice_with_cost_center(self):
|
||||
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
cost_center = "_Test Cost Center for BS Account - _TC"
|
||||
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
|
||||
|
||||
@@ -1604,14 +1610,47 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
def test_sales_invoice_with_project_link(self):
|
||||
from erpnext.projects.doctype.project.test_project import make_project
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
project = make_project({
|
||||
'project_name': 'Sales Invoice Project',
|
||||
'project_template_name': 'Test Project Template',
|
||||
'start_date': '2020-01-01'
|
||||
})
|
||||
item_project = make_project({
|
||||
'project_name': 'Sales Invoice Item Project',
|
||||
'project_template_name': 'Test Project Template',
|
||||
'start_date': '2019-06-01'
|
||||
})
|
||||
|
||||
def test_sales_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
|
||||
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
|
||||
accounts_settings.save()
|
||||
sales_invoice = create_sales_invoice(do_not_save=1)
|
||||
sales_invoice.items[0].project = item_project.project_name
|
||||
sales_invoice.project = project.project_name
|
||||
|
||||
sales_invoice.submit()
|
||||
|
||||
expected_values = {
|
||||
"Debtors - _TC": {
|
||||
"project": project.project_name
|
||||
},
|
||||
"Sales - _TC": {
|
||||
"project": item_project.project_name
|
||||
}
|
||||
}
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, cost_center, project, account_currency, debit, credit,
|
||||
debit_in_account_currency, credit_in_account_currency
|
||||
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
|
||||
order by account asc""", sales_invoice.name, as_dict=1)
|
||||
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["project"], gle.project)
|
||||
|
||||
def test_sales_invoice_without_cost_center(self):
|
||||
cost_center = "_Test Cost Center - _TC"
|
||||
si = create_sales_invoice(debit_to="Debtors - _TC")
|
||||
|
||||
@@ -1634,9 +1673,6 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
for gle in gl_entries:
|
||||
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
|
||||
|
||||
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
|
||||
accounts_settings.save()
|
||||
|
||||
def test_deferred_revenue(self):
|
||||
deferred_account = create_account(account_name="Deferred Revenue",
|
||||
parent_account="Current Liabilities - _TC", company="_Test Company")
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "hash",
|
||||
"creation": "2013-06-04 11:02:19",
|
||||
"doctype": "DocType",
|
||||
@@ -87,6 +86,7 @@
|
||||
"edit_references",
|
||||
"sales_order",
|
||||
"so_detail",
|
||||
"sales_invoice_item",
|
||||
"column_break_74",
|
||||
"delivery_note",
|
||||
"dn_detail",
|
||||
@@ -94,6 +94,7 @@
|
||||
"accounting_dimensions_section",
|
||||
"cost_center",
|
||||
"dimension_col_break",
|
||||
"project",
|
||||
"section_break_54",
|
||||
"page_break"
|
||||
],
|
||||
@@ -783,12 +784,28 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Finance Book",
|
||||
"options": "Finance Book"
|
||||
},
|
||||
{
|
||||
"fieldname": "project",
|
||||
"fieldtype": "Link",
|
||||
"label": "Project",
|
||||
"options": "Project"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:parent.update_stock == 1",
|
||||
"fieldname": "sales_invoice_item",
|
||||
"fieldtype": "Data",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Sales Invoice Item",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2019-12-04 12:22:38.517710",
|
||||
"modified": "2020-08-20 11:24:41.749986",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Item",
|
||||
|
||||
@@ -1,314 +1,89 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2016-05-08 23:49:38.842621",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"creation": "2016-05-08 23:49:38.842621",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"default",
|
||||
"mode_of_payment",
|
||||
"amount",
|
||||
"column_break_3",
|
||||
"account",
|
||||
"type",
|
||||
"base_amount",
|
||||
"clearance_date"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:parent.doctype == 'POS Profile'",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "default",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Default",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"default": "0",
|
||||
"depends_on": "eval:parent.doctype == 'POS Profile'",
|
||||
"fieldname": "default",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Default"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "mode_of_payment",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Mode of Payment",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Mode of Payment",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "mode_of_payment",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Mode of Payment",
|
||||
"options": "Mode of Payment",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"depends_on": "eval:parent.doctype == 'Sales Invoice'",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"default": "0",
|
||||
"depends_on": "eval:parent.doctype == 'Sales Invoice'",
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
"options": "currency",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Account",
|
||||
"options": "Account",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "mode_of_payment.type",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "type",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fetch_from": "mode_of_payment.type",
|
||||
"fieldname": "type",
|
||||
"fieldtype": "Read Only",
|
||||
"label": "Type"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Base Amount (Company Currency)",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "base_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Base Amount (Company Currency)",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "clearance_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Clearance Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"fieldname": "clearance_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Clearance Date",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-03-19 14:54:56.524556",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Payment",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2020-08-03 13:07:49.260534",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Payment",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
||||
@@ -45,8 +45,8 @@ def validate_accounting_period(gl_map):
|
||||
}, as_dict=1)
|
||||
|
||||
if accounting_periods:
|
||||
frappe.throw(_("You can't create accounting entries in the closed accounting period {0}")
|
||||
.format(accounting_periods[0].name), ClosedAccountingPeriod)
|
||||
frappe.throw(_("You cannot create or cancel any accounting entries within in the closed Accounting Period {0}")
|
||||
.format(frappe.bold(accounting_periods[0].name)), ClosedAccountingPeriod)
|
||||
|
||||
def process_gl_map(gl_map, merge_entries=True):
|
||||
if merge_entries:
|
||||
@@ -296,6 +296,7 @@ def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
|
||||
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no), as_dict=True)
|
||||
|
||||
if gl_entries:
|
||||
validate_accounting_period(gl_entries)
|
||||
check_freezing_date(gl_entries[0]["posting_date"], adv_adj)
|
||||
|
||||
frappe.db.sql("""delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s""",
|
||||
|
||||
@@ -285,6 +285,8 @@ def get_matching_transactions_payments(description_matching):
|
||||
else:
|
||||
return []
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def payment_entry_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
|
||||
if not account:
|
||||
@@ -313,6 +315,8 @@ def payment_entry_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
}
|
||||
)
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def journal_entry_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
|
||||
|
||||
@@ -348,6 +352,8 @@ def journal_entry_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
}
|
||||
)
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def sales_invoices_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql("""
|
||||
SELECT
|
||||
@@ -373,4 +379,4 @@ def sales_invoices_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
'start': start,
|
||||
'page_len': page_len
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1062,7 +1062,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
}
|
||||
if(index < me.page_len) {
|
||||
$(frappe.render_template("pos_item", {
|
||||
item_code: obj.name,
|
||||
item_code: escape(obj.name),
|
||||
item_price: item_price,
|
||||
item_name: obj.name === obj.item_name ? "" : obj.item_name,
|
||||
item_image: obj.image,
|
||||
@@ -1098,7 +1098,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
|
||||
get_items: function (item_code) {
|
||||
// To search item as per the key enter
|
||||
|
||||
item_code = unescape(item_code);
|
||||
item_code = item_code === "undefined" ? undefined : item_code;
|
||||
var me = this;
|
||||
this.item_serial_no = {};
|
||||
this.item_batch_no = {};
|
||||
@@ -1164,7 +1165,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
$(this).addClass('active');
|
||||
me.numeric_val = "";
|
||||
me.numeric_id = ""
|
||||
me.item_code = $(this).attr("data-item-code");
|
||||
me.item_code = unescape($(this).attr("data-item-code"));
|
||||
me.render_selected_item()
|
||||
me.bind_qty_event()
|
||||
me.update_rate()
|
||||
@@ -1176,33 +1177,33 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
var me = this;
|
||||
|
||||
$(this.wrapper).on("change", ".pos-item-qty", function () {
|
||||
var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
|
||||
var item_code = unescape($(this).parents(".pos-selected-item-action").attr("data-item-code"));
|
||||
var qty = $(this).val();
|
||||
me.update_qty(item_code, qty);
|
||||
me.update_value();
|
||||
})
|
||||
|
||||
$(this.wrapper).on("focusout", ".pos-item-qty", function () {
|
||||
var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
|
||||
var item_code = unescape($(this).parents(".pos-selected-item-action").attr("data-item-code"));
|
||||
var qty = $(this).val();
|
||||
me.update_qty(item_code, qty, true);
|
||||
me.update_value();
|
||||
})
|
||||
|
||||
$(this.wrapper).find("[data-action='increase-qty']").on("click", function () {
|
||||
var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
|
||||
var item_code = unescape($(this).parents(".pos-bill-item").attr("data-item-code"));
|
||||
var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) + 1;
|
||||
me.update_qty(item_code, qty);
|
||||
})
|
||||
|
||||
$(this.wrapper).find("[data-action='decrease-qty']").on("click", function () {
|
||||
var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
|
||||
var item_code = unescape($(this).parents(".pos-bill-item").attr("data-item-code"));
|
||||
var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) - 1;
|
||||
me.update_qty(item_code, qty);
|
||||
})
|
||||
|
||||
$(this.wrapper).on("change", ".pos-item-disc", function () {
|
||||
var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
|
||||
var item_code = unescape($(this).parents(".pos-selected-item-action").attr("data-item-code"));
|
||||
var discount = $(this).val();
|
||||
if(discount > 100){
|
||||
discount = $(this).val('');
|
||||
@@ -1253,7 +1254,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
update_rate: function () {
|
||||
var me = this;
|
||||
$(this.wrapper).on("change", ".pos-item-price", function () {
|
||||
var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
|
||||
var item_code = unescape($(this).parents(".pos-selected-item-action").attr("data-item-code"));
|
||||
me.set_item_details(item_code, "rate", $(this).val());
|
||||
me.update_value()
|
||||
})
|
||||
@@ -1282,9 +1283,17 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
this.child_doc = this.get_child_item(this.item_code);
|
||||
$(this.wrapper).find('.selected-item').empty();
|
||||
if(this.child_doc.length) {
|
||||
this.child_doc[0]["allow_user_to_edit_rate"] = this.pos_profile_data["allow_user_to_edit_rate"] ? true : false,
|
||||
this.child_doc[0]["allow_user_to_edit_discount"] = this.pos_profile_data["allow_user_to_edit_discount"] ? true : false;
|
||||
this.selected_row = $(frappe.render_template("pos_selected_item", this.child_doc[0]))
|
||||
this.selected_row = $(frappe.render_template("pos_selected_item", {
|
||||
idx: this.child_doc[0].idx,
|
||||
item_code: escape(this.child_doc[0].item_code),
|
||||
qty: this.child_doc[0].qty,
|
||||
price_list_rate: this.child_doc[0].price_list_rate,
|
||||
allow_user_to_edit_rate: this.pos_profile_data["allow_user_to_edit_rate"] ? true : false,
|
||||
allow_user_to_edit_discount: this.pos_profile_data["allow_user_to_edit_discount"] ? true : false,
|
||||
discount_percentage: this.child_doc[0].discount_percentage,
|
||||
rate: this.child_doc[0].rate,
|
||||
amount: this.child_doc[0].amount
|
||||
}))
|
||||
$(this.wrapper).find('.selected-item').html(this.selected_row)
|
||||
}
|
||||
|
||||
@@ -1535,7 +1544,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
|
||||
$.each(this.frm.doc.items || [], function (i, d) {
|
||||
$(frappe.render_template("pos_bill_item_new", {
|
||||
item_code: d.item_code,
|
||||
item_code: escape(d.item_code),
|
||||
item_name: (d.item_name === d.item_code || !d.item_name) ? "" : ("<br>" + d.item_name),
|
||||
qty: d.qty,
|
||||
discount_percentage: d.discount_percentage || 0.0,
|
||||
|
||||
@@ -61,7 +61,7 @@ def make_sales_invoice():
|
||||
debit_to = 'Debtors - _TC2',
|
||||
income_account = 'Sales - _TC2',
|
||||
expense_account = 'Cost of Goods Sold - _TC2',
|
||||
cost_center = '_Test Company 2 - _TC2')
|
||||
cost_center = 'Main - _TC2')
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -643,8 +643,10 @@ class ReceivablePayableReport(object):
|
||||
account_type = "Receivable" if self.party_type == "Customer" else "Payable"
|
||||
accounts = [d.name for d in frappe.get_all("Account",
|
||||
filters={"account_type": account_type, "company": self.filters.company})]
|
||||
conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts)))
|
||||
values += accounts
|
||||
|
||||
if accounts:
|
||||
conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts)))
|
||||
values += accounts
|
||||
|
||||
def add_customer_filters(self, conditions, values):
|
||||
if self.filters.get("customer_group"):
|
||||
|
||||
@@ -63,7 +63,7 @@ def make_sales_invoice():
|
||||
debit_to = 'Debtors - _TC2',
|
||||
income_account = 'Sales - _TC2',
|
||||
expense_account = 'Cost of Goods Sold - _TC2',
|
||||
cost_center = '_Test Company 2 - _TC2',
|
||||
cost_center = 'Main - _TC2',
|
||||
do_not_save=1)
|
||||
|
||||
si.append('payment_schedule', dict(due_date=getdate(add_days(today(), 30)), invoice_portion=30.00, payment_amount=30))
|
||||
@@ -83,14 +83,14 @@ def make_payment(docname):
|
||||
|
||||
def make_credit_note(docname):
|
||||
create_sales_invoice(company="_Test Company 2",
|
||||
customer = '_Test Customer 2',
|
||||
currency = 'EUR',
|
||||
qty = -1,
|
||||
warehouse = 'Finished Goods - _TC2',
|
||||
debit_to = 'Debtors - _TC2',
|
||||
income_account = 'Sales - _TC2',
|
||||
expense_account = 'Cost of Goods Sold - _TC2',
|
||||
cost_center = '_Test Company 2 - _TC2',
|
||||
is_return = 1,
|
||||
return_against = docname)
|
||||
customer = '_Test Customer 2',
|
||||
currency = 'EUR',
|
||||
qty = -1,
|
||||
warehouse = 'Finished Goods - _TC2',
|
||||
debit_to = 'Debtors - _TC2',
|
||||
income_account = 'Sales - _TC2',
|
||||
expense_account = 'Cost of Goods Sold - _TC2',
|
||||
cost_center = 'Main - _TC2',
|
||||
is_return = 1,
|
||||
return_against = docname)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ from __future__ import unicode_literals
|
||||
import re
|
||||
from past.builtins import cmp
|
||||
import functools
|
||||
import math
|
||||
|
||||
import frappe, erpnext
|
||||
from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
|
||||
@@ -42,7 +43,7 @@ def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_v
|
||||
start_date = year_start_date
|
||||
months = get_months(year_start_date, year_end_date)
|
||||
|
||||
for i in range(months // months_to_add):
|
||||
for i in range(math.ceil(months / months_to_add)):
|
||||
period = frappe._dict({
|
||||
"from_date": start_date
|
||||
})
|
||||
|
||||
@@ -113,7 +113,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
|
||||
acc = frappe.get_doc("Account", account)
|
||||
|
||||
try:
|
||||
year_start_date = get_fiscal_year(date, verbose=0)[1]
|
||||
year_start_date = get_fiscal_year(date, company=company, verbose=0)[1]
|
||||
except FiscalYearError:
|
||||
if getdate(date) > getdate(nowdate()):
|
||||
# if fiscal year not found and the date is greater than today
|
||||
@@ -124,14 +124,12 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
|
||||
# hence, assuming balance as 0.0
|
||||
return 0.0
|
||||
|
||||
allow_cost_center_in_entry_of_bs_account = get_allow_cost_center_in_entry_of_bs_account()
|
||||
|
||||
if account:
|
||||
report_type = acc.report_type
|
||||
else:
|
||||
report_type = ""
|
||||
|
||||
if cost_center and (allow_cost_center_in_entry_of_bs_account or report_type =='Profit and Loss'):
|
||||
if cost_center and report_type == 'Profit and Loss':
|
||||
cc = frappe.get_doc("Cost Center", cost_center)
|
||||
if cc.is_group:
|
||||
cond.append(""" exists (
|
||||
@@ -658,7 +656,8 @@ def get_outstanding_invoices(party_type, party, account, condition=None, filters
|
||||
invoice_list = frappe.db.sql("""
|
||||
select
|
||||
voucher_no, voucher_type, posting_date, due_date,
|
||||
ifnull(sum({dr_or_cr}), 0) as invoice_amount
|
||||
ifnull(sum({dr_or_cr}), 0) as invoice_amount,
|
||||
account_currency as currency
|
||||
from
|
||||
`tabGL Entry`
|
||||
where
|
||||
@@ -715,7 +714,8 @@ def get_outstanding_invoices(party_type, party, account, condition=None, filters
|
||||
'invoice_amount': flt(d.invoice_amount),
|
||||
'payment_amount': payment_amount,
|
||||
'outstanding_amount': outstanding_amount,
|
||||
'due_date': d.due_date
|
||||
'due_date': d.due_date,
|
||||
'currency': d.currency
|
||||
})
|
||||
)
|
||||
|
||||
@@ -767,10 +767,10 @@ def get_children(doctype, parent, company, is_root=False):
|
||||
company_currency = frappe.get_cached_value('Company', company, "default_currency")
|
||||
for each in acc:
|
||||
each["company_currency"] = company_currency
|
||||
each["balance"] = flt(get_balance_on(each.get("value"), in_account_currency=False))
|
||||
each["balance"] = flt(get_balance_on(each.get("value"), in_account_currency=False, company=company))
|
||||
|
||||
if each.account_currency != company_currency:
|
||||
each["balance_in_account_currency"] = flt(get_balance_on(each.get("value")))
|
||||
each["balance_in_account_currency"] = flt(get_balance_on(each.get("value"), company=company))
|
||||
|
||||
return acc
|
||||
|
||||
@@ -817,7 +817,7 @@ def create_payment_gateway_account(gateway):
|
||||
pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_cost_center(docname, cost_center_name, cost_center_number, company):
|
||||
def update_cost_center(docname, cost_center_name, cost_center_number, company, merge):
|
||||
'''
|
||||
Renames the document by adding the number as a prefix to the current name and updates
|
||||
all transaction where it was present.
|
||||
@@ -833,7 +833,7 @@ def update_cost_center(docname, cost_center_name, cost_center_number, company):
|
||||
|
||||
new_name = get_autoname_with_number(cost_center_number, cost_center_name, docname, company)
|
||||
if docname != new_name:
|
||||
frappe.rename_doc("Cost Center", docname, new_name, force=1)
|
||||
frappe.rename_doc("Cost Center", docname, new_name, force=1, merge=merge)
|
||||
return new_name
|
||||
|
||||
def validate_field_number(doctype_name, docname, number_value, company, field_name):
|
||||
@@ -877,11 +877,6 @@ def get_coa(doctype, parent, is_root, chart=None):
|
||||
|
||||
return accounts
|
||||
|
||||
def get_allow_cost_center_in_entry_of_bs_account():
|
||||
def generator():
|
||||
return cint(frappe.db.get_value('Accounts Settings', None, 'allow_cost_center_in_entry_of_bs_account'))
|
||||
return frappe.local_cache("get_allow_cost_center_in_entry_of_bs_account", (), generator, regenerate_if_none=True)
|
||||
|
||||
def get_stock_accounts(company):
|
||||
return frappe.get_all("Account", filters = {
|
||||
"account_type": "Stock",
|
||||
|
||||
@@ -407,6 +407,8 @@ class Asset(AccountsController):
|
||||
row.expected_value_after_useful_life = asset_value_after_full_schedule
|
||||
|
||||
def validate_cancellation(self):
|
||||
if self.status in ("In Maintenance", "Out of Order"):
|
||||
frappe.throw(_("There are active maintenance or repairs against the asset. You must complete all of them before cancelling the asset."))
|
||||
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
|
||||
frappe.throw(_("Asset cannot be cancelled, as it is already {0}").format(self.status))
|
||||
|
||||
|
||||
@@ -58,7 +58,8 @@ def make_depreciation_entry(asset_name, date=None):
|
||||
"account": accumulated_depreciation_account,
|
||||
"credit_in_account_currency": d.depreciation_amount,
|
||||
"reference_type": "Asset",
|
||||
"reference_name": asset.name
|
||||
"reference_name": asset.name,
|
||||
"cost_center": ""
|
||||
}
|
||||
|
||||
debit_entry = {
|
||||
@@ -196,12 +197,14 @@ def get_gl_entries_on_asset_disposal(asset, selling_amount=0, finance_book=None)
|
||||
{
|
||||
"account": fixed_asset_account,
|
||||
"credit_in_account_currency": asset.gross_purchase_amount,
|
||||
"credit": asset.gross_purchase_amount
|
||||
"credit": asset.gross_purchase_amount,
|
||||
"cost_center": depreciation_cost_center
|
||||
},
|
||||
{
|
||||
"account": accumulated_depr_account,
|
||||
"debit_in_account_currency": accumulated_depr_amount,
|
||||
"debit": accumulated_depr_amount
|
||||
"debit": accumulated_depr_amount,
|
||||
"cost_center": depreciation_cost_center
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ def update_maintenance_log(asset_maintenance, item_code, item_name, task):
|
||||
maintenance_log.save()
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_team_members(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.get_values('Maintenance Team Member', { 'parent': filters.get("maintenance_team") })
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from erpnext.assets.doctype.asset_maintenance.asset_maintenance import calculate
|
||||
|
||||
class AssetMaintenanceLog(Document):
|
||||
def validate(self):
|
||||
if getdate(self.due_date) < getdate(nowdate()):
|
||||
if getdate(self.due_date) < getdate(nowdate()) and self.maintenance_status not in ["Completed", "Cancelled"]:
|
||||
self.maintenance_status = "Overdue"
|
||||
|
||||
if self.maintenance_status == "Completed" and not self.completion_date:
|
||||
@@ -41,6 +41,7 @@ class AssetMaintenanceLog(Document):
|
||||
asset_maintenance_doc.save()
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_maintenance_tasks(doctype, txt, searchfield, start, page_len, filters):
|
||||
asset_maintenance_tasks = frappe.db.get_values('Asset Maintenance Task', {'parent':filters.get("asset_maintenance")}, 'maintenance_task')
|
||||
return asset_maintenance_tasks
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
frappe.listview_settings['Asset Maintenance Log'] = {
|
||||
add_fields: ["maintenance_status"],
|
||||
has_indicator_for_draft: 1,
|
||||
get_indicator: function(doc) {
|
||||
if(doc.maintenance_status=="Pending") {
|
||||
return [__("Pending"), "orange"];
|
||||
} else if(doc.maintenance_status=="Completed") {
|
||||
return [__("Completed"), "green"];
|
||||
} else if(doc.maintenance_status=="Cancelled") {
|
||||
return [__("Cancelled"), "red"];
|
||||
} else if(doc.maintenance_status=="Overdue") {
|
||||
return [__("Overdue"), "red"];
|
||||
if (doc.maintenance_status=="Planned") {
|
||||
return [__(doc.maintenance_status), "orange", "status,=," + doc.maintenance_status];
|
||||
} else if (doc.maintenance_status=="Completed") {
|
||||
return [__(doc.maintenance_status), "green", "status,=," + doc.maintenance_status];
|
||||
} else if (doc.maintenance_status=="Cancelled") {
|
||||
return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status];
|
||||
} else if (doc.maintenance_status=="Overdue") {
|
||||
return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -7,12 +7,6 @@ frappe.provide("erpnext.buying");
|
||||
|
||||
frappe.ui.form.on("Purchase Order", {
|
||||
setup: function(frm) {
|
||||
frm.custom_make_buttons = {
|
||||
'Purchase Receipt': 'Receipt',
|
||||
'Purchase Invoice': 'Invoice',
|
||||
'Stock Entry': 'Material to Supplier',
|
||||
'Payment Entry': 'Payment'
|
||||
}
|
||||
|
||||
frm.set_query("reserve_warehouse", "supplied_items", function() {
|
||||
return {
|
||||
@@ -36,20 +30,6 @@ frappe.ui.form.on("Purchase Order", {
|
||||
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
if(frm.doc.docstatus === 1 && frm.doc.status !== 'Closed'
|
||||
&& flt(frm.doc.per_received) < 100 && flt(frm.doc.per_billed) < 100) {
|
||||
frm.add_custom_button(__('Update Items'), () => {
|
||||
erpnext.utils.update_child_items({
|
||||
frm: frm,
|
||||
child_docname: "items",
|
||||
child_doctype: "Purchase Order Detail",
|
||||
cannot_add_row: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onload: function(frm) {
|
||||
set_schedule_date(frm);
|
||||
if (!frm.doc.transaction_date){
|
||||
@@ -76,6 +56,18 @@ frappe.ui.form.on("Purchase Order Item", {
|
||||
});
|
||||
|
||||
erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({
|
||||
setup: function() {
|
||||
this.frm.custom_make_buttons = {
|
||||
'Purchase Receipt': 'Receipt',
|
||||
'Purchase Invoice': 'Invoice',
|
||||
'Stock Entry': 'Material to Supplier',
|
||||
'Payment Entry': 'Payment',
|
||||
}
|
||||
|
||||
this._super();
|
||||
|
||||
},
|
||||
|
||||
refresh: function(doc, cdt, cdn) {
|
||||
var me = this;
|
||||
this._super();
|
||||
@@ -99,6 +91,16 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
||||
|
||||
if(doc.docstatus == 1) {
|
||||
if(!in_list(["Closed", "Delivered"], doc.status)) {
|
||||
if(this.frm.doc.status !== 'Closed' && flt(this.frm.doc.per_received) < 100 && flt(this.frm.doc.per_billed) < 100) {
|
||||
this.frm.add_custom_button(__('Update Items'), () => {
|
||||
erpnext.utils.update_child_items({
|
||||
frm: this.frm,
|
||||
child_docname: "items",
|
||||
child_doctype: "Purchase Order Detail",
|
||||
cannot_add_row: false,
|
||||
})
|
||||
});
|
||||
}
|
||||
if (this.frm.has_perm("submit")) {
|
||||
if(flt(doc.per_billed, 6) < 100 || flt(doc.per_received, 6) < 100) {
|
||||
if (doc.status != "On Hold") {
|
||||
@@ -123,14 +125,14 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
||||
}
|
||||
if(doc.status != "Closed") {
|
||||
if (doc.status != "On Hold") {
|
||||
if(flt(doc.per_received, 2) < 100 && allow_receipt) {
|
||||
if(flt(doc.per_received) < 100 && allow_receipt) {
|
||||
cur_frm.add_custom_button(__('Receipt'), this.make_purchase_receipt, __('Create'));
|
||||
if(doc.is_subcontracted==="Yes" && me.has_unsupplied_items()) {
|
||||
cur_frm.add_custom_button(__('Material to Supplier'),
|
||||
function() { me.make_stock_entry(); }, __("Transfer"));
|
||||
}
|
||||
}
|
||||
if(flt(doc.per_billed, 2) < 100)
|
||||
if(flt(doc.per_billed) < 100)
|
||||
cur_frm.add_custom_button(__('Invoice'),
|
||||
this.make_purchase_invoice, __('Create'));
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-05-21 16:16:39",
|
||||
@@ -998,6 +997,7 @@
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "subscription_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Subscription Section"
|
||||
@@ -1055,8 +1055,7 @@
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 105,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-06-12 14:08:11.777120",
|
||||
"modified": "2020-07-01 12:40:45.240948",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
||||
@@ -166,7 +166,8 @@ frappe.ui.form.on("Request for Quotation",{
|
||||
{ "fieldtype": "Select", "label": __("Supplier"),
|
||||
"fieldname": "supplier",
|
||||
"options": doc.suppliers.map(d => d.supplier),
|
||||
"reqd": 1 },
|
||||
"reqd": 1,
|
||||
"default": doc.suppliers.length === 1 ? doc.suppliers[0].supplier_name : "" },
|
||||
{ "fieldtype": "Button", "label": __('Create Supplier Quotation'),
|
||||
"fieldname": "make_supplier_quotation", "cssClass": "btn-primary" },
|
||||
]
|
||||
|
||||
@@ -25,6 +25,7 @@ class RequestforQuotation(BuyingController):
|
||||
self.validate_duplicate_supplier()
|
||||
self.validate_supplier_list()
|
||||
validate_for_items(self)
|
||||
super(RequestforQuotation, self).set_qty_as_per_stock_uom()
|
||||
self.update_email_id()
|
||||
|
||||
def validate_duplicate_supplier(self):
|
||||
@@ -50,7 +51,7 @@ class RequestforQuotation(BuyingController):
|
||||
|
||||
def validate_email_id(self, args):
|
||||
if not args.email_id:
|
||||
frappe.throw(_("Row {0}: For supplier {0} Email Address is required to send email").format(args.idx, args.supplier))
|
||||
frappe.throw(_("Row {0}: For Supplier {0}, Email Address is Required to Send Email").format(args.idx, args.supplier))
|
||||
|
||||
def on_submit(self):
|
||||
frappe.db.set(self, 'status', 'Submitted')
|
||||
@@ -153,7 +154,7 @@ class RequestforQuotation(BuyingController):
|
||||
sender=sender,attachments = attachments, send_email=True,
|
||||
doctype=self.doctype, name=self.name)["name"]
|
||||
|
||||
frappe.msgprint(_("Email sent to supplier {0}").format(data.supplier))
|
||||
frappe.msgprint(_("Email Sent to Supplier {0}").format(data.supplier))
|
||||
|
||||
def get_attachments(self):
|
||||
attachments = [d.name for d in get_attachments(self.doctype, self.name)]
|
||||
@@ -192,7 +193,7 @@ def send_supplier_emails(rfq_name):
|
||||
def check_portal_enabled(reference_doctype):
|
||||
if not frappe.db.get_value('Portal Menu Item',
|
||||
{'reference_doctype': reference_doctype}, 'enabled'):
|
||||
frappe.throw(_("Request for Quotation is disabled to access from portal, for more check portal settings."))
|
||||
frappe.throw(_("The Access to Request for Quotation From Portal is Disabled. To Allow Access, Enable it in Portal Settings."))
|
||||
|
||||
def get_list_context(context=None):
|
||||
from erpnext.controllers.website_list_for_contact import get_list_context
|
||||
@@ -205,6 +206,8 @@ def get_list_context(context=None):
|
||||
})
|
||||
return list_context
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql("""select `tabContact`.name from `tabContact`, `tabDynamic Link`
|
||||
where `tabDynamic Link`.link_doctype = 'Supplier' and (`tabDynamic Link`.link_name=%(name)s
|
||||
@@ -258,7 +261,7 @@ def create_supplier_quotation(doc):
|
||||
sq_doc.flags.ignore_permissions = True
|
||||
sq_doc.run_method("set_missing_values")
|
||||
sq_doc.save()
|
||||
frappe.msgprint(_("Supplier Quotation {0} created").format(sq_doc.name))
|
||||
frappe.msgprint(_("Supplier Quotation {0} Created").format(sq_doc.name))
|
||||
return sq_doc.name
|
||||
except Exception:
|
||||
return None
|
||||
@@ -278,6 +281,7 @@ def create_rfq_items(sq_doc, supplier, data):
|
||||
"description": data.description,
|
||||
"qty": data.qty,
|
||||
"rate": data.rate,
|
||||
"conversion_factor": data.conversion_factor if data.conversion_factor else None,
|
||||
"supplier_part_no": frappe.db.get_value("Item Supplier", {'parent': data.item_code, 'supplier': supplier}, "supplier_part_no"),
|
||||
"warehouse": data.warehouse or '',
|
||||
"request_for_quotation_item": data.name,
|
||||
|
||||
@@ -6,12 +6,14 @@ from __future__ import unicode_literals
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
||||
from frappe.utils import nowdate
|
||||
from erpnext.stock.doctype.item.test_item import make_item
|
||||
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
|
||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
|
||||
|
||||
class TestRequestforQuotation(unittest.TestCase):
|
||||
def test_quote_status(self):
|
||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
|
||||
rfq = make_request_for_quotation()
|
||||
|
||||
self.assertEqual(rfq.get('suppliers')[0].quote_status, 'Pending')
|
||||
@@ -31,7 +33,6 @@ class TestRequestforQuotation(unittest.TestCase):
|
||||
self.assertEqual(rfq.get('suppliers')[1].quote_status, 'No Quote')
|
||||
|
||||
def test_make_supplier_quotation(self):
|
||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
|
||||
rfq = make_request_for_quotation()
|
||||
|
||||
sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
|
||||
@@ -51,15 +52,13 @@ class TestRequestforQuotation(unittest.TestCase):
|
||||
self.assertEqual(sq1.get('items')[0].qty, 5)
|
||||
|
||||
def test_make_supplier_quotation_with_special_characters(self):
|
||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
|
||||
|
||||
frappe.delete_doc_if_exists("Supplier", "_Test Supplier '1", force=1)
|
||||
supplier = frappe.new_doc("Supplier")
|
||||
supplier.supplier_name = "_Test Supplier '1"
|
||||
supplier.supplier_group = "_Test Supplier Group"
|
||||
supplier.insert()
|
||||
|
||||
rfq = make_request_for_quotation(supplier_wt_appos)
|
||||
rfq = make_request_for_quotation(supplier_data=supplier_wt_appos)
|
||||
|
||||
sq = make_supplier_quotation(rfq.name, supplier_wt_appos[0].get("supplier"))
|
||||
sq.submit()
|
||||
@@ -76,7 +75,6 @@ class TestRequestforQuotation(unittest.TestCase):
|
||||
frappe.form_dict.name = None
|
||||
|
||||
def test_make_supplier_quotation_from_portal(self):
|
||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
|
||||
rfq = make_request_for_quotation()
|
||||
rfq.get('items')[0].rate = 100
|
||||
rfq.supplier = rfq.suppliers[0].supplier
|
||||
@@ -90,12 +88,34 @@ class TestRequestforQuotation(unittest.TestCase):
|
||||
self.assertEqual(supplier_quotation_doc.get('items')[0].qty, 5)
|
||||
self.assertEqual(supplier_quotation_doc.get('items')[0].amount, 500)
|
||||
|
||||
def test_make_multi_uom_supplier_quotation(self):
|
||||
item_code = "_Test Multi UOM RFQ Item"
|
||||
if not frappe.db.exists('Item', item_code):
|
||||
item = make_item(item_code, {'stock_uom': '_Test UOM'})
|
||||
row = item.append('uoms', {
|
||||
'uom': 'Kg',
|
||||
'conversion_factor': 2
|
||||
})
|
||||
row.db_update()
|
||||
|
||||
def make_request_for_quotation(supplier_data=None):
|
||||
rfq = make_request_for_quotation(item_code="_Test Multi UOM RFQ Item", uom="Kg", conversion_factor=2)
|
||||
rfq.get('items')[0].rate = 100
|
||||
rfq.supplier = rfq.suppliers[0].supplier
|
||||
|
||||
self.assertEqual(rfq.items[0].stock_qty, 10)
|
||||
|
||||
supplier_quotation_name = create_supplier_quotation(rfq)
|
||||
supplier_quotation = frappe.get_doc('Supplier Quotation', supplier_quotation_name)
|
||||
|
||||
self.assertEqual(supplier_quotation.items[0].qty, 5)
|
||||
self.assertEqual(supplier_quotation.items[0].stock_qty, 10)
|
||||
|
||||
def make_request_for_quotation(**args):
|
||||
"""
|
||||
:param supplier_data: List containing supplier data
|
||||
"""
|
||||
supplier_data = supplier_data if supplier_data else get_supplier_data()
|
||||
args = frappe._dict(args)
|
||||
supplier_data = args.get("supplier_data") if args.get("supplier_data") else get_supplier_data()
|
||||
rfq = frappe.new_doc('Request for Quotation')
|
||||
rfq.transaction_date = nowdate()
|
||||
rfq.status = 'Draft'
|
||||
@@ -106,11 +126,13 @@ def make_request_for_quotation(supplier_data=None):
|
||||
rfq.append('suppliers', data)
|
||||
|
||||
rfq.append("items", {
|
||||
"item_code": "_Test Item",
|
||||
"item_code": args.item_code or "_Test Item",
|
||||
"description": "_Test Item",
|
||||
"uom": "_Test UOM",
|
||||
"qty": 5,
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"uom": args.uom or "_Test UOM",
|
||||
"stock_uom": args.stock_uom or "_Test UOM",
|
||||
"qty": args.qty or 5,
|
||||
"conversion_factor": args.conversion_factor or 1.0,
|
||||
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
||||
"schedule_date": nowdate()
|
||||
})
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "hash",
|
||||
"creation": "2016-02-25 08:04:02.452958",
|
||||
"doctype": "DocType",
|
||||
@@ -9,6 +10,7 @@
|
||||
"supplier_part_no",
|
||||
"column_break_3",
|
||||
"item_name",
|
||||
"schedule_date",
|
||||
"section_break_5",
|
||||
"description",
|
||||
"item_group",
|
||||
@@ -18,9 +20,11 @@
|
||||
"image_view",
|
||||
"quantity",
|
||||
"qty",
|
||||
"stock_uom",
|
||||
"col_break2",
|
||||
"schedule_date",
|
||||
"uom",
|
||||
"conversion_factor",
|
||||
"stock_qty",
|
||||
"warehouse_and_reference",
|
||||
"warehouse",
|
||||
"project_name",
|
||||
@@ -33,7 +37,7 @@
|
||||
"fields": [
|
||||
{
|
||||
"bold": 1,
|
||||
"columns": 3,
|
||||
"columns": 2,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
@@ -98,7 +102,7 @@
|
||||
{
|
||||
"fieldname": "quantity",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Quantity"
|
||||
"label": "Quantity & Stock"
|
||||
},
|
||||
{
|
||||
"bold": 1,
|
||||
@@ -129,12 +133,12 @@
|
||||
{
|
||||
"fieldname": "uom",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "UOM",
|
||||
"oldfieldname": "uom",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "UOM",
|
||||
"print_width": "100px",
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"width": "100px"
|
||||
},
|
||||
@@ -144,7 +148,7 @@
|
||||
"label": "Warehouse and Reference"
|
||||
},
|
||||
{
|
||||
"columns": 3,
|
||||
"columns": 2,
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
@@ -202,6 +206,7 @@
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"default": "0",
|
||||
"fieldname": "page_break",
|
||||
"fieldtype": "Check",
|
||||
"label": "Page Break",
|
||||
@@ -219,10 +224,36 @@
|
||||
{
|
||||
"fieldname": "section_break_23",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "Stock UOM",
|
||||
"options": "UOM",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "conversion_factor",
|
||||
"fieldtype": "Float",
|
||||
"label": "UOM Conversion Factor",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "stock_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Qty as per Stock UOM",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2019-05-01 17:50:23.703801",
|
||||
"links": [],
|
||||
"modified": "2020-06-12 19:10:36.333441",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Request for Quotation Item",
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
{
|
||||
"fieldname": "default_bank_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Bank Account",
|
||||
"label": "Default Company Bank Account",
|
||||
"options": "Bank Account"
|
||||
},
|
||||
{
|
||||
@@ -385,7 +385,7 @@
|
||||
"idx": 370,
|
||||
"image_field": "image",
|
||||
"links": [],
|
||||
"modified": "2020-03-17 09:48:30.578242",
|
||||
"modified": "2020-06-17 23:28:30",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier",
|
||||
|
||||
@@ -67,4 +67,5 @@ class TestProcurementTracker(unittest.TestCase):
|
||||
"expected_delivery_date": date_obj,
|
||||
"actual_delivery_date": date_obj
|
||||
}
|
||||
|
||||
return expected_data
|
||||
@@ -12,7 +12,6 @@ from erpnext.stock.doctype.item.item import validate_end_of_life
|
||||
|
||||
def update_last_purchase_rate(doc, is_submit):
|
||||
"""updates last_purchase_rate in item table for each item"""
|
||||
|
||||
import frappe.utils
|
||||
this_purchase_date = frappe.utils.getdate(doc.get('posting_date') or doc.get('transaction_date'))
|
||||
|
||||
@@ -23,7 +22,7 @@ def update_last_purchase_rate(doc, is_submit):
|
||||
# compare last purchase date and this transaction's date
|
||||
last_purchase_rate = None
|
||||
if last_purchase_details and \
|
||||
(last_purchase_details.purchase_date > this_purchase_date):
|
||||
(doc.get('docstatus') == 2 or last_purchase_details.purchase_date > this_purchase_date):
|
||||
last_purchase_rate = last_purchase_details['base_net_rate']
|
||||
elif is_submit == 1:
|
||||
# even if this transaction is the latest one, it should be submitted
|
||||
|
||||
66
erpnext/change_log/v12/v12_11_0.md
Normal file
66
erpnext/change_log/v12/v12_11_0.md
Normal file
@@ -0,0 +1,66 @@
|
||||
## ERPNext v12.11.0 Release Note
|
||||
|
||||
- Enabled translation on html files in LMS [Proposal] ([#21582](https://github.com/frappe/erpnext/pull/21582))
|
||||
- Multi UOM support in Request for Quotation ([#22250](https://github.com/frappe/erpnext/pull/22250))
|
||||
- Exploded Item Rate ([#22816](https://github.com/frappe/erpnext/pull/22816))
|
||||
- asset maintenance fixes ([#21277](https://github.com/frappe/erpnext/pull/21277))
|
||||
- Error due to comma in Pricing rule name ([#22927](https://github.com/frappe/erpnext/pull/22927))
|
||||
- Set default reference Id for "On Previous Row Amount" and "On Previous Row Total" ([#22387](https://github.com/frappe/erpnext/pull/22387))
|
||||
- fix(Education): course wise assessment report labels ([#22805](https://github.com/frappe/erpnext/pull/22805))
|
||||
- ewaybill json had json dump of json dump, and other related fixes ([#22656](https://github.com/frappe/erpnext/pull/22656))
|
||||
- Unable to change link from new lead to existing customer ([#22795](https://github.com/frappe/erpnext/pull/22795))
|
||||
- Incorrect delivered qty in Supplier-Wise Sales Analytics ([#22642](https://github.com/frappe/erpnext/pull/22642))
|
||||
- Dont merge items if both exist in stock reco ([#22784](https://github.com/frappe/erpnext/pull/22784))
|
||||
- Status error in purchase invoice ([#22389](https://github.com/frappe/erpnext/pull/22389))
|
||||
- Whitelist all query functions for search widget ([#22606](https://github.com/frappe/erpnext/pull/22606))
|
||||
- SQL query in accounts receivable, payable reports ([#22891](https://github.com/frappe/erpnext/pull/22891))
|
||||
- In POS serial no popup coming two times ([#22268](https://github.com/frappe/erpnext/pull/22268))
|
||||
- Cannot cancel assets with repair pending (bp #22440) ([#22453](https://github.com/frappe/erpnext/pull/22453))
|
||||
- Take parent cost center for child if no cost center at child ([#22496](https://github.com/frappe/erpnext/pull/22496))
|
||||
- Handle nonetype issue for packed items ([#22493](https://github.com/frappe/erpnext/pull/22493))
|
||||
- Cannot cancel assets with repair pending ([#22440](https://github.com/frappe/erpnext/pull/22440))
|
||||
- Show or hide section or attributes depending on other attributes… ([#22933](https://github.com/frappe/erpnext/pull/22933))
|
||||
- Insert Supplier Group via List View (bp #22403) ([#22407](https://github.com/frappe/erpnext/pull/22407))
|
||||
- Skip Progress and Completed by fields on Task Duplication ([#22640](https://github.com/frappe/erpnext/pull/22640))
|
||||
- Incorrect variable used while adding new item in the submitted Sales Order ([#22308](https://github.com/frappe/erpnext/pull/22308))
|
||||
- Incorrect stock value in return case ([#22528](https://github.com/frappe/erpnext/pull/22528))
|
||||
- staffing Plan validation ([#22379](https://github.com/frappe/erpnext/pull/22379))
|
||||
- Cancellation of accounting transactions within closed accounting period ([#22986](https://github.com/frappe/erpnext/pull/22986))
|
||||
- Not able to submit sales invoice ([#22699](https://github.com/frappe/erpnext/pull/22699))
|
||||
- Offline pos not working for special character item ([#22391](https://github.com/frappe/erpnext/pull/22391))
|
||||
- Due to decimal issue make purchase receipt button not showing in Purchase Order ([#22643](https://github.com/frappe/erpnext/pull/22643))
|
||||
- Stock Reconciliation Invalid Quantity for Batched Item ([#22716](https://github.com/frappe/erpnext/pull/22716))
|
||||
- Quality procedure fixes ([#22287](https://github.com/frappe/erpnext/pull/22287))
|
||||
- Set label if domains is set ([#22523](https://github.com/frappe/erpnext/pull/22523))
|
||||
- Update item tax only if item code available ([#22575](https://github.com/frappe/erpnext/pull/22575))
|
||||
- Inclusive tax based on item quantity ([#23015](https://github.com/frappe/erpnext/pull/23015))
|
||||
- Quotation lost reason options fix ([#23016](https://github.com/frappe/erpnext/pull/23016))
|
||||
- GSTR 1 report for exports without payment of Tax ([#22968](https://github.com/frappe/erpnext/pull/22968))
|
||||
- Period list fixes in financial statements ([#22679](https://github.com/frappe/erpnext/pull/22679))
|
||||
- Don't set asset maintenance log status as Overdue when Completed or Cancelled ([#23012](https://github.com/frappe/erpnext/pull/23012))
|
||||
- Update state code and union territory for Daman and Diu ([#22989](https://github.com/frappe/erpnext/pull/22989))
|
||||
- Set Root as Parent if no parent in new tree view node ([#22507](https://github.com/frappe/erpnext/pull/22507))
|
||||
- Serial no / batch no Popup is coming for the non serialized items ([#22362](https://github.com/frappe/erpnext/pull/22362))
|
||||
- update shopify api version ([#22284](https://github.com/frappe/erpnext/pull/22284))
|
||||
- Unable to create batched item ([#22332](https://github.com/frappe/erpnext/pull/22332))
|
||||
- Incorrect balance qty in stock ledger report ([#22649](https://github.com/frappe/erpnext/pull/22649))
|
||||
- Setup status indicators for Job Offer and Job Applicant (v12) ([#22444](https://github.com/frappe/erpnext/pull/22444))
|
||||
- Set half day date None if half day is unchecked ([#22905](https://github.com/frappe/erpnext/pull/22905))
|
||||
- Completed qty not updated in work order ([#22372](https://github.com/frappe/erpnext/pull/22372))
|
||||
- Handling Empty tables in Production Plan ([#22469](https://github.com/frappe/erpnext/pull/22469))
|
||||
- Fetch project-related info in Timesheet (v12) ([#22422](https://github.com/frappe/erpnext/pull/22422))
|
||||
- Pricing Rule breaks if no item_code ([#22653](https://github.com/frappe/erpnext/pull/22653))
|
||||
- Made "Subscription Section", "Auto Repeat" and Hub Publishing" c… ([#22535](https://github.com/frappe/erpnext/pull/22535))
|
||||
- Update Packed Items via Update Items in SO ([#22404](https://github.com/frappe/erpnext/pull/22404))
|
||||
- Do not add tax amount in grand total for reverse charge invoices ([#22686](https://github.com/frappe/erpnext/pull/22686))
|
||||
- Other charges on income tax in salary slip ([#22798](https://github.com/frappe/erpnext/pull/22798))
|
||||
- Serial No Rename does not affect Stock Ledger Entry ([#22780](https://github.com/frappe/erpnext/pull/22780))
|
||||
- Quotation list view blank if quotation_to field not set as a standard filter ([#22659](https://github.com/frappe/erpnext/pull/22659))
|
||||
- cannot change customer fields if credit exhausted ([#22838](https://github.com/frappe/erpnext/pull/22838))
|
||||
- Project link not set in accounts other than profit and loss accounts ([#22049](https://github.com/frappe/erpnext/pull/22049))
|
||||
- Bank Clearance of POS purchase invoice ([#22884](https://github.com/frappe/erpnext/pull/22884))
|
||||
- Multiple GST fixes ([#22730](https://github.com/frappe/erpnext/pull/22730))
|
||||
- Add default cost center in payment reconciliation JV ([#22930](https://github.com/frappe/erpnext/pull/22930))
|
||||
- Do not copy Item Tax template from SO to PO ([#22324](https://github.com/frappe/erpnext/pull/22324))
|
||||
- Tax amounts in HSN Wise Outward summary ([#22755](https://github.com/frappe/erpnext/pull/22755))
|
||||
- Multi currency payment reconciliation ([#22928](https://github.com/frappe/erpnext/pull/22928))
|
||||
@@ -20,6 +20,7 @@ from erpnext.exceptions import InvalidCurrency
|
||||
from six import text_type
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
|
||||
from erpnext.stock.get_item_details import get_item_warehouse
|
||||
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
|
||||
|
||||
force_item_fields = ("item_group", "brand", "stock_uom", "is_fixed_asset", "item_tax_rate", "pricing_rules")
|
||||
|
||||
@@ -953,7 +954,7 @@ def validate_inclusive_tax(tax, doc):
|
||||
# all rows about the reffered tax should be inclusive
|
||||
_on_previous_row_error("1 - %d" % (tax.row_id,))
|
||||
elif tax.get("category") == "Valuation":
|
||||
frappe.throw(_("Valuation type charges can not marked as Inclusive"))
|
||||
frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
|
||||
|
||||
|
||||
def set_balance_in_account_currency(gl_dict, account_currency=None, conversion_rate=None, company_currency=None):
|
||||
@@ -1010,6 +1011,7 @@ def get_advance_journal_entries(party_type, party, party_account, amount_field,
|
||||
def get_advance_payment_entries(party_type, party, party_account, order_doctype,
|
||||
order_list=None, include_unallocated=True, against_all_orders=False, limit=None):
|
||||
party_account_field = "paid_from" if party_type == "Customer" else "paid_to"
|
||||
currency_field = "paid_from_account_currency" if party_type == "Customer" else "paid_to_account_currency"
|
||||
payment_type = "Receive" if party_type == "Customer" else "Pay"
|
||||
payment_entries_against_order, unallocated_payment_entries = [], []
|
||||
limit_cond = "limit %s" % limit if limit else ""
|
||||
@@ -1026,14 +1028,15 @@ def get_advance_payment_entries(party_type, party, party_account, order_doctype,
|
||||
select
|
||||
"Payment Entry" as reference_type, t1.name as reference_name,
|
||||
t1.remarks, t2.allocated_amount as amount, t2.name as reference_row,
|
||||
t2.reference_name as against_order, t1.posting_date
|
||||
t2.reference_name as against_order, t1.posting_date,
|
||||
t1.{0} as currency
|
||||
from `tabPayment Entry` t1, `tabPayment Entry Reference` t2
|
||||
where
|
||||
t1.name = t2.parent and t1.{0} = %s and t1.payment_type = %s
|
||||
t1.name = t2.parent and t1.{1} = %s and t1.payment_type = %s
|
||||
and t1.party_type = %s and t1.party = %s and t1.docstatus = 1
|
||||
and t2.reference_doctype = %s {1}
|
||||
order by t1.posting_date {2}
|
||||
""".format(party_account_field, reference_condition, limit_cond),
|
||||
and t2.reference_doctype = %s {2}
|
||||
order by t1.posting_date {3}
|
||||
""".format(currency_field, party_account_field, reference_condition, limit_cond),
|
||||
[party_account, payment_type, party_type, party,
|
||||
order_doctype] + order_list, as_dict=1)
|
||||
|
||||
@@ -1298,6 +1301,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
||||
parent.set_qty_as_per_stock_uom()
|
||||
parent.calculate_taxes_and_totals()
|
||||
if parent_doctype == "Sales Order":
|
||||
make_packing_list(parent)
|
||||
parent.set_gross_profit()
|
||||
frappe.get_doc('Authorization Control').validate_approving_authority(parent.doctype,
|
||||
parent.company, parent.base_grand_total)
|
||||
|
||||
@@ -182,7 +182,7 @@ class BuyingController(StockController):
|
||||
if item.item_code and item.qty and item.item_code in stock_and_asset_items:
|
||||
item_proportion = flt(item.base_net_amount) / stock_and_asset_items_amount if stock_and_asset_items_amount \
|
||||
else flt(item.qty) / stock_and_asset_items_qty
|
||||
|
||||
|
||||
if i == (last_item_idx - 1):
|
||||
item.item_tax_amount = flt(valuation_amount_adjustment,
|
||||
self.precision("item_tax_amount", item))
|
||||
@@ -540,9 +540,19 @@ class BuyingController(StockController):
|
||||
"serial_no": cstr(d.serial_no).strip()
|
||||
})
|
||||
if self.is_return:
|
||||
original_incoming_rate = frappe.db.get_value("Stock Ledger Entry",
|
||||
{"voucher_type": "Purchase Receipt", "voucher_no": self.return_against,
|
||||
"item_code": d.item_code}, "incoming_rate")
|
||||
filters = {
|
||||
"voucher_type": self.doctype,
|
||||
"voucher_no": self.return_against,
|
||||
"item_code": d.item_code
|
||||
}
|
||||
|
||||
if (self.doctype == "Purchase Invoice" and self.update_stock
|
||||
and d.get("purchase_invoice_item")):
|
||||
filters["voucher_detail_no"] = d.purchase_invoice_item
|
||||
elif self.doctype == "Purchase Receipt" and d.get("purchase_receipt_item"):
|
||||
filters["voucher_detail_no"] = d.purchase_receipt_item
|
||||
|
||||
original_incoming_rate = frappe.db.get_value("Stock Ledger Entry", filters, "incoming_rate")
|
||||
|
||||
sle.update({
|
||||
"outgoing_rate": original_incoming_rate
|
||||
@@ -728,7 +738,7 @@ class BuyingController(StockController):
|
||||
if delete_asset and is_auto_create_enabled:
|
||||
# need to delete movements to delete assets otherwise throws link exists error
|
||||
movements = frappe.db.sql(
|
||||
"""SELECT asm.name
|
||||
"""SELECT asm.name
|
||||
FROM `tabAsset Movement` asm, `tabAsset Movement Item` asm_item
|
||||
WHERE asm_item.parent=asm.name and asm_item.asset=%s""", asset.name, as_dict=1)
|
||||
for movement in movements:
|
||||
|
||||
@@ -10,7 +10,9 @@ from collections import defaultdict
|
||||
from erpnext.stock.get_item_details import _get_item_tax_template
|
||||
from frappe.utils import unique
|
||||
|
||||
# searches for active employees
|
||||
# searches for active employees
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def employee_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
conditions = []
|
||||
fields = get_fields("Employee", ["name", "employee_name"])
|
||||
@@ -40,6 +42,8 @@ def employee_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
|
||||
# searches for leads which are not converted
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def lead_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
fields = get_fields("Lead", ["name", "lead_name", "company_name"])
|
||||
|
||||
@@ -68,7 +72,9 @@ def lead_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
})
|
||||
|
||||
|
||||
# searches for customer
|
||||
# searches for customer
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def customer_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
conditions = []
|
||||
cust_master_name = frappe.defaults.get_user_default("cust_master_name")
|
||||
@@ -106,8 +112,11 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
|
||||
# searches for supplier
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def supplier_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
supp_master_name = frappe.defaults.get_user_default("supp_master_name")
|
||||
|
||||
if supp_master_name == "Supplier Name":
|
||||
fields = ["name", "supplier_group"]
|
||||
else:
|
||||
@@ -137,31 +146,50 @@ def supplier_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
})
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
company_currency = erpnext.get_company_currency(filters.get('company'))
|
||||
|
||||
tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
|
||||
where tabAccount.docstatus!=2
|
||||
and account_type in (%s)
|
||||
and is_group = 0
|
||||
and company = %s
|
||||
and account_currency = %s
|
||||
and `%s` LIKE %s
|
||||
order by idx desc, name
|
||||
limit %s, %s""" %
|
||||
(", ".join(['%s']*len(filters.get("account_type"))), "%s", "%s", searchfield, "%s", "%s", "%s"),
|
||||
tuple(filters.get("account_type") + [filters.get("company"), company_currency, "%%%s%%" % txt,
|
||||
start, page_len]))
|
||||
def get_accounts(with_account_type_filter):
|
||||
account_type_condition = ''
|
||||
if with_account_type_filter:
|
||||
account_type_condition = "AND account_type in %(account_types)s"
|
||||
|
||||
accounts = frappe.db.sql("""
|
||||
SELECT name, parent_account
|
||||
FROM `tabAccount`
|
||||
WHERE `tabAccount`.docstatus!=2
|
||||
{account_type_condition}
|
||||
AND is_group = 0
|
||||
AND company = %(company)s
|
||||
AND account_currency = %(currency)s
|
||||
AND `{searchfield}` LIKE %(txt)s
|
||||
ORDER BY idx DESC, name
|
||||
LIMIT %(offset)s, %(limit)s
|
||||
""".format(account_type_condition=account_type_condition, searchfield=searchfield),
|
||||
dict(
|
||||
account_types=filters.get("account_type"),
|
||||
company=filters.get("company"),
|
||||
currency=company_currency,
|
||||
txt="%{}%".format(txt),
|
||||
offset=start,
|
||||
limit=page_len
|
||||
)
|
||||
)
|
||||
|
||||
return accounts
|
||||
|
||||
tax_accounts = get_accounts(True)
|
||||
|
||||
if not tax_accounts:
|
||||
tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
|
||||
where tabAccount.docstatus!=2 and is_group = 0
|
||||
and company = %s and account_currency = %s and `%s` LIKE %s limit %s, %s""" #nosec
|
||||
% ("%s", "%s", searchfield, "%s", "%s", "%s"),
|
||||
(filters.get("company"), company_currency, "%%%s%%" % txt, start, page_len))
|
||||
tax_accounts = get_accounts(False)
|
||||
|
||||
return tax_accounts
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
|
||||
conditions = []
|
||||
|
||||
@@ -209,7 +237,6 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
idx desc,
|
||||
name, item_name
|
||||
limit %(start)s, %(page_len)s """.format(
|
||||
key=searchfield,
|
||||
columns=columns,
|
||||
scond=searchfields,
|
||||
fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'),
|
||||
@@ -224,6 +251,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
}, as_dict=as_dict)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def bom(doctype, txt, searchfield, start, page_len, filters):
|
||||
conditions = []
|
||||
fields = get_fields("BOM", ["name", "item"])
|
||||
@@ -250,6 +279,8 @@ def bom(doctype, txt, searchfield, start, page_len, filters):
|
||||
})
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_project_name(doctype, txt, searchfield, start, page_len, filters):
|
||||
cond = ''
|
||||
if filters.get('customer'):
|
||||
@@ -276,6 +307,8 @@ def get_project_name(doctype, txt, searchfield, start, page_len, filters):
|
||||
})
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters, as_dict):
|
||||
fields = get_fields("Delivery Note", ["name", "customer", "posting_date"])
|
||||
|
||||
@@ -305,6 +338,8 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len,
|
||||
}, {"txt": ("%%%s%%" % txt)}, as_dict=as_dict)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
cond = ""
|
||||
if filters.get("posting_date"):
|
||||
@@ -362,6 +397,8 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_account_list(doctype, txt, searchfield, start, page_len, filters):
|
||||
filter_list = []
|
||||
|
||||
@@ -384,7 +421,8 @@ def get_account_list(doctype, txt, searchfield, start, page_len, filters):
|
||||
fields = ["name", "parent_account"],
|
||||
limit_start=start, limit_page_length=page_len, as_list=True)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_blanket_orders(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql("""select distinct bo.name, bo.blanket_order_type, bo.to_date
|
||||
from `tabBlanket Order` bo, `tabBlanket Order Item` boi
|
||||
@@ -401,6 +439,7 @@ def get_blanket_orders(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_income_account(doctype, txt, searchfield, start, page_len, filters):
|
||||
from erpnext.controllers.queries import get_match_cond
|
||||
|
||||
@@ -427,6 +466,7 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
|
||||
from erpnext.controllers.queries import get_match_cond
|
||||
|
||||
@@ -451,6 +491,7 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def warehouse_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
# Should be used when item code is passed in filters.
|
||||
conditions, bin_conditions = [], []
|
||||
@@ -494,6 +535,7 @@ def get_doctype_wise_filters(filters):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters):
|
||||
query = """select batch_id from `tabBatch`
|
||||
where disabled = 0
|
||||
@@ -507,6 +549,7 @@ def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def item_manufacturer_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
item_filters = [
|
||||
['manufacturer', 'like', '%' + txt + '%'],
|
||||
@@ -525,6 +568,7 @@ def item_manufacturer_query(doctype, txt, searchfield, start, page_len, filters)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_purchase_receipts(doctype, txt, searchfield, start, page_len, filters):
|
||||
query = """
|
||||
select pr.name
|
||||
@@ -539,6 +583,7 @@ def get_purchase_receipts(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters):
|
||||
query = """
|
||||
select pi.name
|
||||
@@ -553,6 +598,7 @@ def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
item_doc = frappe.get_cached_doc('Item', filters.get('item_code'))
|
||||
|
||||
@@ -74,7 +74,7 @@ def validate_returned_items(doc):
|
||||
for d in doc.get("items"):
|
||||
if d.item_code and (flt(d.qty) < 0 or flt(d.get('received_qty')) < 0):
|
||||
if d.item_code not in valid_items:
|
||||
frappe.throw(_("Row # {0}: Returned Item {1} does not exists in {2} {3}")
|
||||
frappe.throw(_("Row # {0}: Returned Item {1} does not exist in {2} {3}")
|
||||
.format(d.idx, d.item_code, doc.doctype, doc.return_against))
|
||||
else:
|
||||
ref = valid_items.get(d.item_code, frappe._dict())
|
||||
@@ -266,6 +266,8 @@ def make_return_doc(doctype, source_name, target_doc=None):
|
||||
target_doc.purchase_order = source_doc.purchase_order
|
||||
target_doc.purchase_order_item = source_doc.purchase_order_item
|
||||
target_doc.rejected_warehouse = source_doc.rejected_warehouse
|
||||
target_doc.purchase_receipt_item = source_doc.name
|
||||
|
||||
elif doctype == "Purchase Invoice":
|
||||
target_doc.received_qty = -1* source_doc.received_qty
|
||||
target_doc.rejected_qty = -1* source_doc.rejected_qty
|
||||
@@ -276,20 +278,25 @@ def make_return_doc(doctype, source_name, target_doc=None):
|
||||
target_doc.rejected_warehouse = source_doc.rejected_warehouse
|
||||
target_doc.po_detail = source_doc.po_detail
|
||||
target_doc.pr_detail = source_doc.pr_detail
|
||||
target_doc.purchase_invoice_item = source_doc.name
|
||||
|
||||
elif doctype == "Delivery Note":
|
||||
target_doc.against_sales_order = source_doc.against_sales_order
|
||||
target_doc.against_sales_invoice = source_doc.against_sales_invoice
|
||||
target_doc.so_detail = source_doc.so_detail
|
||||
target_doc.si_detail = source_doc.si_detail
|
||||
target_doc.expense_account = source_doc.expense_account
|
||||
target_doc.dn_detail = source_doc.name
|
||||
if default_warehouse_for_sales_return:
|
||||
target_doc.warehouse = default_warehouse_for_sales_return
|
||||
|
||||
elif doctype == "Sales Invoice":
|
||||
target_doc.sales_order = source_doc.sales_order
|
||||
target_doc.delivery_note = source_doc.delivery_note
|
||||
target_doc.so_detail = source_doc.so_detail
|
||||
target_doc.dn_detail = source_doc.dn_detail
|
||||
target_doc.expense_account = source_doc.expense_account
|
||||
target_doc.sales_invoice_item = source_doc.name
|
||||
if default_warehouse_for_sales_return:
|
||||
target_doc.warehouse = default_warehouse_for_sales_return
|
||||
|
||||
|
||||
@@ -216,7 +216,9 @@ class SellingController(StockController):
|
||||
'target_warehouse': p.target_warehouse,
|
||||
'company': self.company,
|
||||
'voucher_type': self.doctype,
|
||||
'allow_zero_valuation': d.allow_zero_valuation_rate
|
||||
'allow_zero_valuation': d.allow_zero_valuation_rate,
|
||||
'sales_invoice_item': d.get("sales_invoice_item"),
|
||||
'delivery_note_item': d.get("dn_detail")
|
||||
}))
|
||||
else:
|
||||
il.append(frappe._dict({
|
||||
@@ -232,7 +234,9 @@ class SellingController(StockController):
|
||||
'target_warehouse': d.target_warehouse,
|
||||
'company': self.company,
|
||||
'voucher_type': self.doctype,
|
||||
'allow_zero_valuation': d.allow_zero_valuation_rate
|
||||
'allow_zero_valuation': d.allow_zero_valuation_rate,
|
||||
'sales_invoice_item': d.get("sales_invoice_item"),
|
||||
'delivery_note_item': d.get("dn_detail")
|
||||
}))
|
||||
return il
|
||||
|
||||
@@ -301,7 +305,11 @@ class SellingController(StockController):
|
||||
d.conversion_factor = get_conversion_factor(d.item_code, d.uom).get("conversion_factor") or 1.0
|
||||
return_rate = 0
|
||||
if cint(self.is_return) and self.return_against and self.docstatus==1:
|
||||
return_rate = self.get_incoming_rate_for_sales_return(d.item_code, self.return_against)
|
||||
against_document_no = (d.get("sales_invoice_item")
|
||||
if self.doctype == "Sales Invoice" else d.get("delivery_note_item"))
|
||||
|
||||
return_rate = self.get_incoming_rate_for_sales_return(d.item_code,
|
||||
self.return_against, against_document_no)
|
||||
|
||||
# On cancellation or if return entry submission, make stock ledger entry for
|
||||
# target warehouse first, to update serial no values properly
|
||||
|
||||
@@ -94,6 +94,7 @@ class StockController(AccountsController):
|
||||
"account": warehouse_account[sle.warehouse]["account"],
|
||||
"against": item_row.expense_account,
|
||||
"cost_center": item_row.cost_center,
|
||||
"project": item_row.get("project") or self.get("project"),
|
||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||
"debit": flt(sle.stock_value_difference, precision),
|
||||
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
|
||||
@@ -104,6 +105,7 @@ class StockController(AccountsController):
|
||||
"account": item_row.expense_account,
|
||||
"against": warehouse_account[sle.warehouse]["account"],
|
||||
"cost_center": item_row.cost_center,
|
||||
"project": item_row.get("project") or self.get("project"),
|
||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||
"credit": flt(sle.stock_value_difference, precision),
|
||||
"project": item_row.get("project") or self.get("project"),
|
||||
@@ -297,14 +299,19 @@ class StockController(AccountsController):
|
||||
|
||||
return serialized_items
|
||||
|
||||
def get_incoming_rate_for_sales_return(self, item_code, against_document):
|
||||
def get_incoming_rate_for_sales_return(self, item_code, against_document, against_document_no=None):
|
||||
incoming_rate = 0.0
|
||||
cond = ''
|
||||
if against_document and item_code:
|
||||
if against_document_no:
|
||||
cond = " and voucher_detail_no = %s" %(frappe.db.escape(against_document_no))
|
||||
|
||||
incoming_rate = frappe.db.sql("""select abs(stock_value_difference / actual_qty)
|
||||
from `tabStock Ledger Entry`
|
||||
where voucher_type = %s and voucher_no = %s
|
||||
and item_code = %s limit 1""",
|
||||
and item_code = %s {0} limit 1""".format(cond),
|
||||
(self.doctype, against_document, item_code))
|
||||
|
||||
incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0
|
||||
|
||||
return incoming_rate
|
||||
|
||||
@@ -160,8 +160,9 @@ class calculate_taxes_and_totals(object):
|
||||
for item in self.doc.get("items"):
|
||||
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
|
||||
cumulated_tax_fraction = 0
|
||||
total_inclusive_tax_amount_per_qty = 0
|
||||
for i, tax in enumerate(self.doc.get("taxes")):
|
||||
tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax, item_tax_map)
|
||||
tax.tax_fraction_for_current_item, inclusive_tax_amount_per_qty = self.get_current_tax_fraction(tax, item_tax_map)
|
||||
|
||||
if i==0:
|
||||
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item
|
||||
@@ -171,9 +172,12 @@ class calculate_taxes_and_totals(object):
|
||||
+ tax.tax_fraction_for_current_item
|
||||
|
||||
cumulated_tax_fraction += tax.tax_fraction_for_current_item
|
||||
total_inclusive_tax_amount_per_qty += inclusive_tax_amount_per_qty * flt(item.qty)
|
||||
|
||||
if cumulated_tax_fraction and not self.discount_amount_applied and item.qty:
|
||||
item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction))
|
||||
if not self.discount_amount_applied and item.qty and (cumulated_tax_fraction or total_inclusive_tax_amount_per_qty):
|
||||
amount = flt(item.amount) - total_inclusive_tax_amount_per_qty
|
||||
|
||||
item.net_amount = flt(amount / (1 + cumulated_tax_fraction))
|
||||
item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate"))
|
||||
item.discount_percentage = flt(item.discount_percentage,
|
||||
item.precision("discount_percentage"))
|
||||
@@ -189,6 +193,7 @@ class calculate_taxes_and_totals(object):
|
||||
from tax inclusive amount
|
||||
"""
|
||||
current_tax_fraction = 0
|
||||
inclusive_tax_amount_per_qty = 0
|
||||
|
||||
if cint(tax.included_in_print_rate):
|
||||
tax_rate = self._get_tax_rate(tax, item_tax_map)
|
||||
@@ -203,10 +208,15 @@ class calculate_taxes_and_totals(object):
|
||||
elif tax.charge_type == "On Previous Row Total":
|
||||
current_tax_fraction = (tax_rate / 100.0) * \
|
||||
self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
|
||||
|
||||
elif tax.charge_type == "On Item Quantity":
|
||||
inclusive_tax_amount_per_qty = flt(tax_rate)
|
||||
|
||||
if getattr(tax, "add_deduct_tax", None):
|
||||
current_tax_fraction *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
|
||||
return current_tax_fraction
|
||||
if getattr(tax, "add_deduct_tax", None) and tax.add_deduct_tax == "Deduct":
|
||||
current_tax_fraction *= -1.0
|
||||
inclusive_tax_amount_per_qty *= -1.0
|
||||
|
||||
return current_tax_fraction, inclusive_tax_amount_per_qty
|
||||
|
||||
def _get_tax_rate(self, tax, item_tax_map):
|
||||
if tax.account_head in item_tax_map:
|
||||
@@ -320,7 +330,7 @@ class calculate_taxes_and_totals(object):
|
||||
current_tax_amount = (tax_rate / 100.0) * \
|
||||
self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_for_current_item
|
||||
elif tax.charge_type == "On Item Quantity":
|
||||
current_tax_amount = tax_rate * item.stock_qty
|
||||
current_tax_amount = tax_rate * item.qty
|
||||
|
||||
self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount)
|
||||
|
||||
@@ -471,7 +481,7 @@ class calculate_taxes_and_totals(object):
|
||||
actual_taxes_dict = {}
|
||||
|
||||
for tax in self.doc.get("taxes"):
|
||||
if tax.charge_type == "Actual":
|
||||
if tax.charge_type in ["Actual", "On Item Quantity"]:
|
||||
tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(tax.tax_amount, tax)
|
||||
actual_taxes_dict.setdefault(tax.idx, tax_amount)
|
||||
elif tax.row_id in actual_taxes_dict:
|
||||
@@ -593,7 +603,7 @@ class calculate_taxes_and_totals(object):
|
||||
base_rate_with_margin = 0.0
|
||||
if item.price_list_rate:
|
||||
if item.pricing_rules and not self.doc.ignore_pricing_rule:
|
||||
for d in item.pricing_rules.split(','):
|
||||
for d in json.loads(item.pricing_rules):
|
||||
pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
|
||||
|
||||
if (pricing_rule.margin_type == 'Amount' and pricing_rule.currency == self.doc.currency)\
|
||||
|
||||
@@ -13,14 +13,12 @@ class TestMapper(unittest.TestCase):
|
||||
'''Test mapping of multiple source docs on a single target doc'''
|
||||
|
||||
make_test_records("Item")
|
||||
items = frappe.get_all("Item", fields = ["name", "item_code"], filters = {'is_sales_item': 1, 'has_variants': 0})
|
||||
customers = frappe.get_all("Customer")
|
||||
if items and customers:
|
||||
# Make source docs (quotations) and a target doc (sales order)
|
||||
customer = random.choice(customers).name
|
||||
qtn1, item_list_1 = self.make_quotation(items, customer)
|
||||
qtn2, item_list_2 = self.make_quotation(items, customer)
|
||||
so, item_list_3 = self.make_sales_order()
|
||||
items = ['_Test Item', '_Test Item 2', '_Test FG Item']
|
||||
|
||||
# Make source docs (quotations) and a target doc (sales order)
|
||||
qtn1, item_list_1 = self.make_quotation(items, '_Test Customer')
|
||||
qtn2, item_list_2 = self.make_quotation(items, '_Test Customer')
|
||||
so, item_list_3 = self.make_sales_order()
|
||||
|
||||
# Map source docs to target with corresponding mapper method
|
||||
method = "erpnext.selling.doctype.quotation.quotation.make_sales_order"
|
||||
@@ -28,18 +26,12 @@ class TestMapper(unittest.TestCase):
|
||||
|
||||
# Assert that all inserted items are present in updated sales order
|
||||
src_items = item_list_1 + item_list_2 + item_list_3
|
||||
self.assertEqual(set([d.item_code for d in src_items]),
|
||||
self.assertEqual(set([d for d in src_items]),
|
||||
set([d.item_code for d in updated_so.items]))
|
||||
|
||||
def get_random_items(self, items, limit):
|
||||
'''Get a number of random items from a list of given items'''
|
||||
random_items = []
|
||||
for i in range(0, limit):
|
||||
random_items.append(random.choice(items))
|
||||
return random_items
|
||||
|
||||
def make_quotation(self, items, customer):
|
||||
item_list = self.get_random_items(items, 3)
|
||||
def make_quotation(self, item_list, customer):
|
||||
|
||||
qtn = frappe.get_doc({
|
||||
"doctype": "Quotation",
|
||||
"quotation_to": "Customer",
|
||||
@@ -49,7 +41,7 @@ class TestMapper(unittest.TestCase):
|
||||
"valid_till" : add_months(nowdate(), 1)
|
||||
})
|
||||
for item in item_list:
|
||||
qtn.append("items", {"qty": "2", "item_code": item.item_code})
|
||||
qtn.append("items", {"qty": "2", "item_code": item})
|
||||
|
||||
qtn.submit()
|
||||
return qtn, item_list
|
||||
@@ -60,7 +52,7 @@ class TestMapper(unittest.TestCase):
|
||||
"base_rate": 100.0,
|
||||
"description": "CPU",
|
||||
"doctype": "Sales Order Item",
|
||||
"item_code": "_Test Item Home Desktop 100",
|
||||
"item_code": "_Test Item",
|
||||
"item_name": "CPU",
|
||||
"parentfield": "items",
|
||||
"qty": 10.0,
|
||||
@@ -72,4 +64,4 @@ class TestMapper(unittest.TestCase):
|
||||
})
|
||||
so = frappe.get_doc(frappe.get_test_records('Sales Order')[0])
|
||||
so.insert(ignore_permissions=True)
|
||||
return so, [item]
|
||||
return so, [item.item_code]
|
||||
|
||||
@@ -30,6 +30,7 @@ class TestTaxes(unittest.TestCase):
|
||||
self.item_tax_template = frappe.get_doc({
|
||||
'doctype': 'Item Tax Template',
|
||||
'title': uuid4(),
|
||||
'company': self.company.name,
|
||||
'taxes': [
|
||||
{
|
||||
'tax_type': self.account.name,
|
||||
|
||||
@@ -33,7 +33,7 @@ def validate_filters(filters):
|
||||
frappe.throw(_("{0} is mandatory").format(f))
|
||||
|
||||
if not frappe.db.exists("Fiscal Year", filters.get("fiscal_year")):
|
||||
frappe.throw(_("Fiscal Year: {0} does not exists").format(filters.get("fiscal_year")))
|
||||
frappe.throw(_("Fiscal Year {0} Does Not Exist").format(filters.get("fiscal_year")))
|
||||
|
||||
if filters.get("based_on") == filters.get("group_by"):
|
||||
frappe.throw(_("'Based On' and 'Group By' can not be same"))
|
||||
|
||||
@@ -60,12 +60,18 @@ frappe.ui.form.on("Opportunity", {
|
||||
|
||||
opportunity_from: function(frm) {
|
||||
frm.toggle_reqd("party_name", frm.doc.opportunity_from);
|
||||
frm.trigger("setup_opportunity_from");
|
||||
frm.set_value("party_name","");
|
||||
},
|
||||
|
||||
setup_opportunity_from: function(frm) {
|
||||
frm.trigger('setup_queries');
|
||||
frm.trigger("set_dynamic_field_label");
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
var doc = frm.doc;
|
||||
frm.events.opportunity_from(frm);
|
||||
frm.trigger("setup_opportunity_from");
|
||||
frm.trigger('toggle_mandatory');
|
||||
erpnext.toggle_naming_series();
|
||||
|
||||
@@ -95,6 +101,7 @@ frappe.ui.form.on("Opportunity", {
|
||||
});
|
||||
} else {
|
||||
frm.add_custom_button(__("Reopen"), function() {
|
||||
frm.set_value("lost_reasons",[])
|
||||
frm.set_value("status", "Open");
|
||||
frm.save();
|
||||
});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "naming_series:",
|
||||
@@ -402,7 +401,7 @@
|
||||
"fieldname": "lost_reasons",
|
||||
"fieldtype": "Table MultiSelect",
|
||||
"label": "Lost Reasons",
|
||||
"options": "Lost Reason Detail",
|
||||
"options": "Opportunity Lost Reason Detail",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
@@ -414,8 +413,7 @@
|
||||
],
|
||||
"icon": "fa fa-info-sign",
|
||||
"idx": 195,
|
||||
"links": [],
|
||||
"modified": "2020-03-20 12:28:45.228994",
|
||||
"modified": "2020-08-12 23:34:39.665513",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Opportunity",
|
||||
|
||||
@@ -321,7 +321,7 @@ def auto_close_opportunity():
|
||||
doc.save()
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_opportunity_from_communication(communication, ignore_communication_links=False):
|
||||
def make_opportunity_from_communication(communication, company, ignore_communication_links=False):
|
||||
from erpnext.crm.doctype.lead.lead import make_lead_from_communication
|
||||
doc = frappe.get_doc("Communication", communication)
|
||||
|
||||
@@ -333,8 +333,9 @@ def make_opportunity_from_communication(communication, ignore_communication_link
|
||||
|
||||
opportunity = frappe.get_doc({
|
||||
"doctype": "Opportunity",
|
||||
"company": company,
|
||||
"opportunity_from": opportunity_from,
|
||||
"lead": lead
|
||||
"party_name": lead
|
||||
}).insert(ignore_permissions=True)
|
||||
|
||||
link_communication_to_document(doc, "Opportunity", opportunity.name, ignore_communication_links)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"creation": "2020-07-16 16:11:39.830389",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"lost_reason"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "lost_reason",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Opportunity Lost Reason",
|
||||
"options": "Opportunity Lost Reason"
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2020-08-12 23:32:55.930406",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Opportunity Lost Reason Detail",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class OpportunityLostReasonDetail(Document):
|
||||
pass
|
||||
@@ -17,7 +17,8 @@ def get_columns():
|
||||
{
|
||||
"fieldname": "lead_owner",
|
||||
"label": _("Lead Owner"),
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Link",
|
||||
"options": "User",
|
||||
"width": "130"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -151,7 +151,7 @@ def get_fee_components(fee_structure):
|
||||
:param fee_structure: Fee Structure.
|
||||
"""
|
||||
if fee_structure:
|
||||
fs = frappe.get_list("Fee Component", fields=["fees_category", "amount"] , filters={"parent": fee_structure}, order_by= "idx")
|
||||
fs = frappe.get_list("Fee Component", fields=["fees_category", "description", "amount"] , filters={"parent": fee_structure}, order_by= "idx")
|
||||
return fs
|
||||
|
||||
|
||||
@@ -363,9 +363,9 @@ def get_current_enrollment(student, academic_year=None):
|
||||
select
|
||||
name as program_enrollment, student_name, program, student_batch_name as student_batch,
|
||||
student_category, academic_term, academic_year
|
||||
from
|
||||
from
|
||||
`tabProgram Enrollment`
|
||||
where
|
||||
where
|
||||
student = %s and academic_year = %s
|
||||
order by creation''', (student, current_academic_year), as_dict=1)
|
||||
|
||||
|
||||
@@ -161,6 +161,7 @@ frappe.ui.form.on("Fees", {
|
||||
$.each(r.message, function(i, d) {
|
||||
var row = frappe.model.add_child(frm.doc, "Fee Component", "components");
|
||||
row.fees_category = d.fees_category;
|
||||
row.description = d.description;
|
||||
row.amount = d.amount;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ class ProgramEnrollment(Document):
|
||||
return quiz_progress
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_program_courses(doctype, txt, searchfield, start, page_len, filters):
|
||||
if filters.get('program'):
|
||||
return frappe.db.sql("""select course, course_name from `tabProgram Course`
|
||||
@@ -115,6 +116,7 @@ def get_program_courses(doctype, txt, searchfield, start, page_len, filters):
|
||||
})
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_students(doctype, txt, searchfield, start, page_len, filters):
|
||||
if not filters.get("academic_term"):
|
||||
filters["academic_term"] = frappe.defaults.get_defaults().academic_term
|
||||
|
||||
@@ -1,398 +1,119 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 1,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 1,
|
||||
"autoname": "",
|
||||
"beta": 0,
|
||||
"creation": "2016-09-13 03:05:27.154713",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"actions": [],
|
||||
"allow_guest_to_view": 1,
|
||||
"allow_rename": 1,
|
||||
"creation": "2016-09-13 03:05:27.154713",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"title",
|
||||
"route",
|
||||
"column_break_3",
|
||||
"academic_year",
|
||||
"admission_start_date",
|
||||
"admission_end_date",
|
||||
"published",
|
||||
"enable_admission_application",
|
||||
"section_break_5",
|
||||
"program_details",
|
||||
"introduction"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Title",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"label": "Title"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "route",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Route",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"fieldname": "route",
|
||||
"fieldtype": "Data",
|
||||
"label": "Route",
|
||||
"no_copy": 1,
|
||||
"unique": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "application_form_route",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Application Form Route",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "academic_year",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Academic Year",
|
||||
"no_copy": 1,
|
||||
"options": "Academic Year",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "academic_year",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Academic Year",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Academic Year",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "admission_start_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Admission Start Date",
|
||||
"no_copy": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "admission_start_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Admission Start Date",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "admission_end_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Admission End Date",
|
||||
"no_copy": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "admission_end_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Admission End Date",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"default": "0",
|
||||
"fieldname": "published",
|
||||
"fieldtype": "Check",
|
||||
"label": "Publish on website"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "published",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Publish on website",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Eligibility and Details"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Eligibility and Details",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "program_details",
|
||||
"fieldtype": "Table",
|
||||
"label": "Eligibility and Details",
|
||||
"options": "Student Admission Program"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "program_details",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Eligibility and Details",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Student Admission Program",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "introduction",
|
||||
"fieldtype": "Text Editor",
|
||||
"label": "Introduction"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "introduction",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Introduction",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
"default": "0",
|
||||
"fieldname": "enable_admission_application",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enable Admission Application"
|
||||
}
|
||||
],
|
||||
"has_web_view": 1,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_published_field": "published",
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-10 18:57:34.570376",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Education",
|
||||
"name": "Student Admission",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"has_web_view": 1,
|
||||
"is_published_field": "published",
|
||||
"links": [],
|
||||
"modified": "2020-06-15 20:18:38.591626",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Education",
|
||||
"name": "Student Admission",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Academics User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Academics User",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"restrict_to_domain": "Education",
|
||||
"route": "admissions",
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "title",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
],
|
||||
"restrict_to_domain": "Education",
|
||||
"route": "admissions",
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "title"
|
||||
}
|
||||
@@ -43,8 +43,8 @@
|
||||
<thead>
|
||||
<tr class="active">
|
||||
<th style="width: 90px">Program/Std.</th>
|
||||
<th style="width: 170px">Minumum Age(DOB)</th>
|
||||
<th style="width: 170px">Maximum Age(DOB)</th>
|
||||
<th style="width: 170px">Minumum Age</th>
|
||||
<th style="width: 170px">Maximum Age</th>
|
||||
<th style="width: 100px">Application Fee</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -52,8 +52,8 @@
|
||||
{% for row in program_details %}
|
||||
<tr>
|
||||
<td>{{ row.program }}</td>
|
||||
<td>{{ row.minimum_age }}</td>
|
||||
<td>{{ row.maximum_age }}</td>
|
||||
<td>{{ row.min_age }}</td>
|
||||
<td>{{ row.max_age }}</td>
|
||||
<td>{{ row.application_fee }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -61,12 +61,11 @@
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{%- if application_form_route -%}
|
||||
{%- if doc.enable_admission_application -%}
|
||||
<br>
|
||||
<p>
|
||||
<a class='btn btn-primary'
|
||||
href='/{{ doc.application_form_route }}?new=1'>
|
||||
href='/student-applicant?new=1&student_admission={{doc.name}}'>
|
||||
{{ _("Apply Now") }}</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
@@ -11,7 +11,7 @@ QUnit.test('Test: Student Admission', function(assert) {
|
||||
{admission_start_date: '2016-04-20'},
|
||||
{admission_end_date: '2016-05-31'},
|
||||
{title: '2016-17 Admissions'},
|
||||
{application_form_route: 'student-applicant'},
|
||||
{enable_admission_application: 1},
|
||||
{introduction: 'Test intro'},
|
||||
{program_details: [
|
||||
[
|
||||
@@ -28,7 +28,7 @@ QUnit.test('Test: Student Admission', function(assert) {
|
||||
assert.ok(cur_frm.doc.admission_start_date == '2016-04-20');
|
||||
assert.ok(cur_frm.doc.admission_end_date == '2016-05-31');
|
||||
assert.ok(cur_frm.doc.title == '2016-17 Admissions');
|
||||
assert.ok(cur_frm.doc.application_form_route == 'student-applicant');
|
||||
assert.ok(cur_frm.doc.enable_admission_application == 1);
|
||||
assert.ok(cur_frm.doc.introduction == 'Test intro');
|
||||
assert.ok(cur_frm.doc.program_details[0].program == 'Standard Test', 'Program correctly selected');
|
||||
assert.ok(cur_frm.doc.program_details[0].application_fee == 1000);
|
||||
|
||||
@@ -1,237 +1,77 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "",
|
||||
"beta": 0,
|
||||
"creation": "2017-09-15 12:59:43.207923",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"actions": [],
|
||||
"creation": "2017-09-15 12:59:43.207923",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"program",
|
||||
"min_age",
|
||||
"max_age",
|
||||
"column_break_4",
|
||||
"application_fee",
|
||||
"applicant_naming_series"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "program",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Program",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Program",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "program",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Program",
|
||||
"options": "Program",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "minimum_age",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Minimum Age",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "maximum_age",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Maximum Age",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "application_fee",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Application Fee",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "applicant_naming_series",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Naming Series (for Student Applicant)",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "application_fee",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Application Fee",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "min_age",
|
||||
"fieldtype": "Int",
|
||||
"in_list_view": 1,
|
||||
"label": "Minimum Age",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "applicant_naming_series",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Naming Series (for Student Applicant)",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"fieldname": "max_age",
|
||||
"fieldtype": "Int",
|
||||
"in_list_view": 1,
|
||||
"label": "Maximum Age",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-11-04 03:37:17.408427",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Education",
|
||||
"name": "Student Admission Program",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"restrict_to_domain": "Education",
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
],
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-06-10 23:06:30.037404",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Education",
|
||||
"name": "Student Admission Program",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"restrict_to_domain": "Education",
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -6,7 +6,7 @@ from __future__ import print_function, unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import getdate
|
||||
from frappe.utils import getdate, add_years, nowdate, date_diff
|
||||
|
||||
class StudentApplicant(Document):
|
||||
def autoname(self):
|
||||
@@ -30,6 +30,7 @@ class StudentApplicant(Document):
|
||||
|
||||
def validate(self):
|
||||
self.title = " ".join(filter(None, [self.first_name, self.middle_name, self.last_name]))
|
||||
|
||||
if self.student_admission and self.program and self.date_of_birth:
|
||||
self.validation_from_student_admission()
|
||||
|
||||
@@ -43,16 +44,16 @@ class StudentApplicant(Document):
|
||||
frappe.throw(_("Please select Student Admission which is mandatory for the paid student applicant"))
|
||||
|
||||
def validation_from_student_admission(self):
|
||||
|
||||
student_admission = get_student_admission_data(self.student_admission, self.program)
|
||||
|
||||
# different validation for minimum and maximum age so that either min/max can also work independently.
|
||||
if student_admission and student_admission.minimum_age and \
|
||||
getdate(student_admission.minimum_age) < getdate(self.date_of_birth):
|
||||
frappe.throw(_("Not eligible for the admission in this program as per DOB"))
|
||||
if student_admission and student_admission.min_age and \
|
||||
date_diff(nowdate(), add_years(getdate(self.date_of_birth), student_admission.min_age)) < 0:
|
||||
frappe.throw(_("Not eligible for the admission in this program as per Date Of Birth"))
|
||||
|
||||
if student_admission and student_admission.maximum_age and \
|
||||
getdate(student_admission.maximum_age) > getdate(self.date_of_birth):
|
||||
frappe.throw(_("Not eligible for the admission in this program as per DOB"))
|
||||
if student_admission and student_admission.max_age and \
|
||||
date_diff(nowdate(), add_years(getdate(self.date_of_birth), student_admission.max_age)) > 0:
|
||||
frappe.throw(_("Not eligible for the admission in this program as per Date Of Birth"))
|
||||
|
||||
|
||||
def on_payment_authorized(self, *args, **kwargs):
|
||||
@@ -60,10 +61,12 @@ class StudentApplicant(Document):
|
||||
|
||||
|
||||
def get_student_admission_data(student_admission, program):
|
||||
|
||||
student_admission = frappe.db.sql("""select sa.admission_start_date, sa.admission_end_date,
|
||||
sap.program, sap.minimum_age, sap.maximum_age, sap.applicant_naming_series
|
||||
sap.program, sap.min_age, sap.max_age, sap.applicant_naming_series
|
||||
from `tabStudent Admission` sa, `tabStudent Admission Program` sap
|
||||
where sa.name = sap.parent and sa.name = %s and sap.program = %s""", (student_admission, program), as_dict=1)
|
||||
|
||||
if student_admission:
|
||||
return student_admission[0]
|
||||
else:
|
||||
|
||||
@@ -140,7 +140,7 @@ education.StudentsEditor = Class.extend({
|
||||
frappe.call({
|
||||
method: "erpnext.education.api.mark_attendance",
|
||||
freeze: true,
|
||||
freeze_message: "Marking attendance",
|
||||
freeze_message: __("Marking attendance"),
|
||||
args: {
|
||||
"students_present": students_present,
|
||||
"students_absent": students_absent,
|
||||
@@ -180,4 +180,4 @@ education.StudentsEditor = Class.extend({
|
||||
</div>`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -106,6 +106,7 @@ def get_program_enrollment(academic_year, academic_term=None, program=None, batc
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def fetch_students(doctype, txt, searchfield, start, page_len, filters):
|
||||
if filters.get("group_based_on") != "Activity":
|
||||
enrolled_students = get_program_enrollment(filters.get('academic_year'), filters.get('academic_term'),
|
||||
|
||||
@@ -42,7 +42,7 @@ def execute(filters=None):
|
||||
# create the list of possible grades
|
||||
if student_row[scrub_criteria] not in grades:
|
||||
grades.append(student_row[scrub_criteria])
|
||||
|
||||
|
||||
# create the dict of for gradewise analysis
|
||||
if student_row[scrub_criteria] not in grade_wise_analysis[criteria]:
|
||||
grade_wise_analysis[criteria][student_row[scrub_criteria]] = 1
|
||||
@@ -101,7 +101,7 @@ def get_formatted_result(args, get_assessment_criteria=False, get_course=False,
|
||||
|
||||
# create the nested dictionary structure as given below:
|
||||
# <variable_name>.<student_name>.<course>.<assessment_group>.<assessment_criteria>.<grade/score/max_score>
|
||||
# "Total Score" -> assessment criteria used for totaling and args.assessment_group -> for totaling all the assesments
|
||||
# "Final Grade" -> assessment criteria used for totaling and args.assessment_group -> for totaling all the assesments
|
||||
|
||||
student_details = {}
|
||||
formatted_assessment_result = defaultdict(dict)
|
||||
@@ -123,13 +123,13 @@ def get_formatted_result(args, get_assessment_criteria=False, get_course=False,
|
||||
formatted_assessment_result[result.student][result.course][assessment_group]\
|
||||
[assessment_criteria]["grade"] = tmp_grade
|
||||
|
||||
# create the assessment criteria "Total Score" with the sum of all the scores of the assessment criteria in a given assessment group
|
||||
# create the assessment criteria "Final Grade" with the sum of all the scores of the assessment criteria in a given assessment group
|
||||
def add_total_score(result, assessment_group):
|
||||
if "Total Score" not in formatted_assessment_result[result.student][result.course][assessment_group]:
|
||||
formatted_assessment_result[result.student][result.course][assessment_group]["Total Score"] = frappe._dict({
|
||||
"assessment_criteria": "Total Score", "maximum_score": result.maximum_score, "score": result.score, "grade": result.grade})
|
||||
if "Final Grade" not in formatted_assessment_result[result.student][result.course][assessment_group]:
|
||||
formatted_assessment_result[result.student][result.course][assessment_group]["Final Grade"] = frappe._dict({
|
||||
"assessment_criteria": "Final Grade", "maximum_score": result.maximum_score, "score": result.score, "grade": result.grade})
|
||||
else:
|
||||
add_score_and_recalculate_grade(result, assessment_group, "Total Score")
|
||||
add_score_and_recalculate_grade(result, assessment_group, "Final Grade")
|
||||
|
||||
for result in assessment_result:
|
||||
if result.student not in student_details:
|
||||
@@ -152,7 +152,7 @@ def get_formatted_result(args, get_assessment_criteria=False, get_course=False,
|
||||
elif create_total_dict:
|
||||
if get_all_assessment_groups:
|
||||
formatted_assessment_result[result.student][result.course][result.assessment_group]\
|
||||
[result.assessment_criteria] = assessment_criteria_details
|
||||
[result.assessment_criteria] = assessment_criteria_details
|
||||
if not formatted_assessment_result[result.student][result.course][args.assessment_group]:
|
||||
formatted_assessment_result[result.student][result.course][args.assessment_group] = defaultdict(dict)
|
||||
formatted_assessment_result[result.student][result.course][args.assessment_group]\
|
||||
@@ -166,7 +166,7 @@ def get_formatted_result(args, get_assessment_criteria=False, get_course=False,
|
||||
add_total_score(result, args.assessment_group)
|
||||
|
||||
total_maximum_score = formatted_assessment_result[result.student][result.course][args.assessment_group]\
|
||||
["Total Score"]["maximum_score"]
|
||||
["Final Grade"]["maximum_score"]
|
||||
if get_assessment_criteria:
|
||||
assessment_criteria_dict[result.assessment_criteria] = formatted_assessment_result[result.student][result.course]\
|
||||
[args.assessment_group][result.assessment_criteria]["maximum_score"]
|
||||
@@ -174,7 +174,7 @@ def get_formatted_result(args, get_assessment_criteria=False, get_course=False,
|
||||
course_dict[result.course] = total_maximum_score
|
||||
|
||||
if get_assessment_criteria and total_maximum_score:
|
||||
assessment_criteria_dict["Total Score"] = total_maximum_score
|
||||
assessment_criteria_dict["Final Grade"] = total_maximum_score
|
||||
|
||||
return {
|
||||
"student_details": student_details,
|
||||
@@ -220,7 +220,7 @@ def get_chart_data(grades, criteria_list, kounter):
|
||||
datasets = []
|
||||
|
||||
for grade in grades:
|
||||
tmp = frappe._dict({"values":[], "title": grade})
|
||||
tmp = frappe._dict({"name": grade, "values":[]})
|
||||
for criteria in criteria_list:
|
||||
if grade in kounter[criteria]:
|
||||
tmp["values"].append(kounter[criteria][grade])
|
||||
|
||||
@@ -1,200 +1,248 @@
|
||||
{
|
||||
"accept_payment": 0,
|
||||
"allow_comments": 0,
|
||||
"allow_delete": 0,
|
||||
"allow_edit": 1,
|
||||
"allow_incomplete": 0,
|
||||
"allow_multiple": 1,
|
||||
"allow_print": 0,
|
||||
"amount": 0.0,
|
||||
"amount_based_on_field": 0,
|
||||
"creation": "2016-09-22 13:10:10.792735",
|
||||
"doc_type": "Student Applicant",
|
||||
"docstatus": 0,
|
||||
"doctype": "Web Form",
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"login_required": 1,
|
||||
"max_attachment_size": 0,
|
||||
"modified": "2017-02-21 05:44:46.022738",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Education",
|
||||
"name": "student-applicant",
|
||||
"owner": "Administrator",
|
||||
"payment_button_label": "Buy Now",
|
||||
"published": 1,
|
||||
"route": "student-applicant",
|
||||
"show_sidebar": 1,
|
||||
"sidebar_items": [],
|
||||
"success_url": "/student-applicant",
|
||||
"title": "Student Applicant",
|
||||
"accept_payment": 0,
|
||||
"allow_comments": 0,
|
||||
"allow_delete": 0,
|
||||
"allow_edit": 1,
|
||||
"allow_incomplete": 0,
|
||||
"allow_multiple": 1,
|
||||
"allow_print": 0,
|
||||
"amount": 0.0,
|
||||
"amount_based_on_field": 0,
|
||||
"creation": "2016-09-22 13:10:10.792735",
|
||||
"doc_type": "Student Applicant",
|
||||
"docstatus": 0,
|
||||
"doctype": "Web Form",
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"login_required": 1,
|
||||
"max_attachment_size": 0,
|
||||
"modified": "2020-06-11 22:53:45.875310",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Education",
|
||||
"name": "student-applicant",
|
||||
"owner": "Administrator",
|
||||
"payment_button_label": "Buy Now",
|
||||
"published": 1,
|
||||
"route": "student-applicant",
|
||||
"route_to_success_link": 0,
|
||||
"show_attachments": 0,
|
||||
"show_in_grid": 0,
|
||||
"show_sidebar": 1,
|
||||
"sidebar_items": [],
|
||||
"success_url": "/student-applicant",
|
||||
"title": "Student Applicant",
|
||||
"web_form_fields": [
|
||||
{
|
||||
"fieldname": "first_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "First Name",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "first_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "First Name",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "middle_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Middle Name",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "middle_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Middle Name",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "last_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Last Name",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "last_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Last Name",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "image",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Image",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "image",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Image",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "program",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"label": "Program",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "Program",
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "program",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"label": "Program",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "Program",
|
||||
"read_only": 0,
|
||||
"reqd": 1,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "academic_year",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"label": "Academic Year",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "Academic Year",
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "academic_year",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"label": "Academic Year",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "Academic Year",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "date_of_birth",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"label": "Date of Birth",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "date_of_birth",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"label": "Date of Birth",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "blood_group",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"label": "Blood Group",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "\nA+\nA-\nB+\nB-\nO+\nO-\nAB+\nAB-",
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "blood_group",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"label": "Blood Group",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "\nA+\nA-\nB+\nB-\nO+\nO-\nAB+\nAB-",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "student_email_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Student Email ID",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "student_email_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Student Email ID",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "student_mobile_number",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Student Mobile Number",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "student_mobile_number",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Student Mobile Number",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"default": "INDIAN",
|
||||
"fieldname": "nationality",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Nationality",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "",
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"default": "INDIAN",
|
||||
"fieldname": "nationality",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Nationality",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "address_line_1",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Address Line 1",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "address_line_1",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Address Line 1",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "address_line_2",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Address Line 2",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "address_line_2",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Address Line 2",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "pincode",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Pincode",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "pincode",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Pincode",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "guardians",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"label": "Guardians",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "Student Guardian",
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "guardians",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"label": "Guardians",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "Student Guardian",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "siblings",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"label": "Siblings",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "Student Sibling",
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "siblings",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"label": "Siblings",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "Student Sibling",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
},
|
||||
{
|
||||
"allow_read_on_all_link_options": 0,
|
||||
"fieldname": "student_admission",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"label": "Student Admission",
|
||||
"max_length": 0,
|
||||
"max_value": 0,
|
||||
"options": "Student Admission",
|
||||
"read_only": 0,
|
||||
"reqd": 0,
|
||||
"show_in_filter": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -67,6 +67,8 @@ def validate_service_item(item, msg):
|
||||
if frappe.db.get_value("Item", item, "is_stock_item") == 1:
|
||||
frappe.throw(_(msg))
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_practitioner_list(doctype, txt, searchfield, start, page_len, filters=None):
|
||||
fields = ["name", "first_name", "mobile_phone"]
|
||||
|
||||
|
||||
@@ -168,6 +168,7 @@ def patient_leave_service_unit(inpatient_record, check_out, leave_from):
|
||||
inpatient_record.save(ignore_permissions = True)
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_leave_from(doctype, txt, searchfield, start, page_len, filters):
|
||||
docname = filters['docname']
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ var create_multiple_dialog = function(listview){
|
||||
}
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: "Creating Lab Test..."
|
||||
freeze_message: __("Creating Lab Test...")
|
||||
});
|
||||
dialog.hide();
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ var schedule_inpatient = function(frm) {
|
||||
}
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: "Process Inpatient Scheduling"
|
||||
freeze_message: __("Process Inpatient Scheduling")
|
||||
});
|
||||
};
|
||||
|
||||
@@ -130,7 +130,7 @@ var schedule_discharge = function(frm) {
|
||||
}
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: "Process Discharge"
|
||||
freeze_message: __("Process Discharge")
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -195,10 +195,21 @@ def create_sensitivity():
|
||||
|
||||
def add_healthcare_service_unit_tree_root():
|
||||
record = [
|
||||
{
|
||||
"doctype": "Healthcare Service Unit",
|
||||
"healthcare_service_unit_name": "All Healthcare Service Units",
|
||||
"is_group": 1
|
||||
}
|
||||
{
|
||||
"doctype": "Healthcare Service Unit",
|
||||
"healthcare_service_unit_name": "All Healthcare Service Units",
|
||||
"is_group": 1,
|
||||
"company": get_company()
|
||||
}
|
||||
]
|
||||
insert_record(record)
|
||||
|
||||
def get_company():
|
||||
company = frappe.defaults.get_defaults().company
|
||||
if company:
|
||||
return company
|
||||
else:
|
||||
company = frappe.get_list("Company", limit=1)
|
||||
if company:
|
||||
return company[0].name
|
||||
return None
|
||||
@@ -244,6 +244,9 @@ doc_events = {
|
||||
"on_cancel": "erpnext.regional.italy.utils.sales_invoice_on_cancel",
|
||||
"on_trash": "erpnext.regional.check_deletion_permission"
|
||||
},
|
||||
"Purchase Invoice": {
|
||||
"validate": "erpnext.regional.india.utils.update_grand_total_for_rcm"
|
||||
},
|
||||
"Payment Entry": {
|
||||
"on_submit": ["erpnext.regional.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.update_payment_req_status"],
|
||||
"on_trash": "erpnext.regional.check_deletion_permission"
|
||||
@@ -353,7 +356,8 @@ regional_overrides = {
|
||||
'erpnext.controllers.taxes_and_totals.get_itemised_tax_breakup_data': 'erpnext.regional.india.utils.get_itemised_tax_breakup_data',
|
||||
'erpnext.accounts.party.get_regional_address_details': 'erpnext.regional.india.utils.get_regional_address_details',
|
||||
'erpnext.hr.utils.calculate_annual_eligible_hra_exemption': 'erpnext.regional.india.utils.calculate_annual_eligible_hra_exemption',
|
||||
'erpnext.hr.utils.calculate_hra_exemption_for_period': 'erpnext.regional.india.utils.calculate_hra_exemption_for_period'
|
||||
'erpnext.hr.utils.calculate_hra_exemption_for_period': 'erpnext.regional.india.utils.calculate_hra_exemption_for_period',
|
||||
'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_regional_gl_entries': 'erpnext.regional.india.utils.make_regional_gl_entries'
|
||||
},
|
||||
'United Arab Emirates': {
|
||||
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.united_arab_emirates.utils.update_itemised_tax_data'
|
||||
|
||||
@@ -11,6 +11,7 @@ class DepartmentApprover(Document):
|
||||
pass
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_approvers(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
if not filters.get("employee"):
|
||||
|
||||
@@ -119,12 +119,14 @@ def make_bank_entry(dt, dn):
|
||||
"reference_type": "Employee Advance",
|
||||
"reference_name": doc.name,
|
||||
"party_type": "Employee",
|
||||
"cost_center": erpnext.get_default_cost_center(doc.company),
|
||||
"party": doc.employee,
|
||||
"is_advance": "Yes"
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": payment_account.account,
|
||||
"cost_center": erpnext.get_default_cost_center(doc.company),
|
||||
"credit_in_account_currency": flt(doc.advance_amount),
|
||||
"account_currency": payment_account.account_currency,
|
||||
"account_type": payment_account.account_type
|
||||
|
||||
@@ -223,6 +223,8 @@ def get_benefit_amount_based_on_pro_rata(sal_struct, component_max_benefit):
|
||||
return benefit_amount
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_earning_components(doctype, txt, searchfield, start, page_len, filters):
|
||||
if len(filters) < 2:
|
||||
return {}
|
||||
@@ -238,4 +240,4 @@ def get_earning_components(doctype, txt, searchfield, start, page_len, filters):
|
||||
""", salary_structure)
|
||||
else:
|
||||
frappe.throw(_("Salary Structure not found for employee {0} and date {1}")
|
||||
.format(filters['employee'], filters['date']))
|
||||
.format(filters['employee'], filters['date']))
|
||||
|
||||
@@ -221,7 +221,6 @@ frappe.ui.form.on("Expense Claim", {
|
||||
},
|
||||
|
||||
update_employee_advance_claimed_amount: function(frm) {
|
||||
console.log("update_employee_advance_claimed_amount")
|
||||
let amount_to_be_allocated = frm.doc.grand_total;
|
||||
$.each(frm.doc.advances || [], function(i, advance){
|
||||
if (amount_to_be_allocated >= advance.unclaimed_amount){
|
||||
@@ -297,6 +296,21 @@ frappe.ui.form.on("Expense Claim", {
|
||||
frm.events.get_advances(frm);
|
||||
},
|
||||
|
||||
cost_center: function(frm) {
|
||||
frm.events.set_child_cost_center(frm);
|
||||
},
|
||||
|
||||
validate: function(frm) {
|
||||
frm.events.set_child_cost_center(frm);
|
||||
},
|
||||
|
||||
set_child_cost_center: function(frm){
|
||||
(frm.doc.expenses || []).forEach(function(d) {
|
||||
if (!d.cost_center){
|
||||
d.cost_center = frm.doc.cost_center;
|
||||
}
|
||||
});
|
||||
},
|
||||
get_taxes: function(frm) {
|
||||
if(frm.doc.taxes) {
|
||||
frappe.call({
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user