Merge branch 'develop' into multi-barcode
This commit is contained in:
commit
76dddbf26e
@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '9.2.21'
|
||||
__version__ = '10.0.7'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
@ -53,14 +53,12 @@ class Account(NestedSet):
|
||||
def set_root_and_report_type(self):
|
||||
if self.parent_account:
|
||||
par = frappe.db.get_value("Account", self.parent_account,
|
||||
["report_type", "root_type", "account_type"], as_dict=1)
|
||||
["report_type", "root_type"], as_dict=1)
|
||||
|
||||
if par.report_type:
|
||||
self.report_type = par.report_type
|
||||
if par.root_type:
|
||||
self.root_type = par.root_type
|
||||
if par.account_type and not self.account_type:
|
||||
self.account_type = par.account_type
|
||||
|
||||
if self.is_group:
|
||||
db_value = frappe.db.get_value("Account", self.name, ["report_type", "root_type"], as_dict=1)
|
||||
@ -165,16 +163,16 @@ class Account(NestedSet):
|
||||
if self.check_gle_exists():
|
||||
throw(_("Account with existing transaction can not be deleted"))
|
||||
|
||||
super(Account, self).on_trash()
|
||||
super(Account, self).on_trash(True)
|
||||
|
||||
def before_rename(self, old, new, merge=False):
|
||||
# Add company abbr if not provided
|
||||
from erpnext.setup.doctype.company.company import get_name_with_abbr
|
||||
new_account = get_name_with_abbr(new, self.company)
|
||||
new_account = get_name_with_number(new_account, self.account_number)
|
||||
|
||||
# Validate properties before merging
|
||||
if merge:
|
||||
if not merge:
|
||||
new_account = get_name_with_number(new_account, self.account_number)
|
||||
else:
|
||||
# Validate properties before merging
|
||||
if not frappe.db.exists("Account", new):
|
||||
throw(_("Account {0} does not exist").format(new))
|
||||
|
||||
|
@ -79,15 +79,17 @@ frappe.treeview_settings["Account"] = {
|
||||
|
||||
},
|
||||
onrender: function(node) {
|
||||
var dr_or_cr = node.data.balance < 0 ? "Cr" : "Dr";
|
||||
if (node.data && node.data.balance!==undefined) {
|
||||
$('<span class="balance-area pull-right text-muted small">'
|
||||
+ (node.data.balance_in_account_currency ?
|
||||
(format_currency(Math.abs(node.data.balance_in_account_currency),
|
||||
node.data.account_currency) + " / ") : "")
|
||||
+ format_currency(Math.abs(node.data.balance), node.data.company_currency)
|
||||
+ " " + dr_or_cr
|
||||
+ '</span>').insertBefore(node.$ul);
|
||||
if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){
|
||||
var dr_or_cr = node.data.balance < 0 ? "Cr" : "Dr";
|
||||
if (node.data && node.data.balance!==undefined) {
|
||||
$('<span class="balance-area pull-right text-muted small">'
|
||||
+ (node.data.balance_in_account_currency ?
|
||||
(format_currency(Math.abs(node.data.balance_in_account_currency),
|
||||
node.data.account_currency) + " / ") : "")
|
||||
+ format_currency(Math.abs(node.data.balance), node.data.company_currency)
|
||||
+ " " + dr_or_cr
|
||||
+ '</span>').insertBefore(node.$ul);
|
||||
}
|
||||
}
|
||||
},
|
||||
toolbar: [
|
||||
|
@ -52,6 +52,7 @@ def _make_test_records(verbose):
|
||||
["_Test Account Customs Duty", "_Test Account Stock Expenses", 0, "Tax", None],
|
||||
["_Test Account Insurance Charges", "_Test Account Stock Expenses", 0, "Chargeable", None],
|
||||
["_Test Account Stock Adjustment", "_Test Account Stock Expenses", 0, "Stock Adjustment", None],
|
||||
["_Test Employee Advance", "Current Liabilities", 0, None, None],
|
||||
|
||||
["_Test Account Tax Assets", "Current Assets", 1, None, None],
|
||||
["_Test Account VAT", "_Test Account Tax Assets", 0, "Tax", None],
|
||||
|
@ -287,6 +287,125 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "print_settings",
|
||||
"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": "Print Settings",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "show_inclusive_tax_in_print",
|
||||
"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": "Show Inclusive Tax In Print",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_12",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "show_payment_schedule_in_print",
|
||||
"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": "Show Payment Schedule in Print",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -392,7 +511,7 @@
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-09-05 10:10:03.117505",
|
||||
"modified": "2018-01-05 15:26:10.357085",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
|
@ -7,6 +7,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import cint
|
||||
from frappe.model.document import Document
|
||||
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
|
||||
|
||||
|
||||
class AccountsSettings(Document):
|
||||
@ -15,6 +16,7 @@ class AccountsSettings(Document):
|
||||
|
||||
def validate(self):
|
||||
self.validate_stale_days()
|
||||
self.enable_payment_schedule_in_print()
|
||||
|
||||
def validate_stale_days(self):
|
||||
if not self.allow_stale and cint(self.stale_days) <= 0:
|
||||
@ -22,3 +24,8 @@ class AccountsSettings(Document):
|
||||
"Stale Days should start from 1.", title='Error', indicator='red',
|
||||
raise_exception=1)
|
||||
|
||||
def enable_payment_schedule_in_print(self):
|
||||
show_in_print = cint(self.show_payment_schedule_in_print)
|
||||
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")
|
@ -74,36 +74,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "due_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": "Due Date",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -748,7 +718,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-08-10 18:06:44.904081",
|
||||
"modified": "2017-12-20 12:40:09.611951",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "GL Entry",
|
||||
|
0
erpnext/accounts/doctype/gst_account/__init__.py
Normal file
0
erpnext/accounts/doctype/gst_account/__init__.py
Normal file
196
erpnext/accounts/doctype/gst_account/gst_account.json
Normal file
196
erpnext/accounts/doctype/gst_account/gst_account.json
Normal file
@ -0,0 +1,196 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-01-02 15:48:58.768352",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company",
|
||||
"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": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cgst_account",
|
||||
"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": "CGST Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "sgst_account",
|
||||
"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": "SGST Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "igst_account",
|
||||
"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": "IGST Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "cess_account",
|
||||
"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": "CESS Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"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-01-02 15:52:22.335988",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "GST Account",
|
||||
"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": 1,
|
||||
"track_seen": 0
|
||||
}
|
10
erpnext/accounts/doctype/gst_account/gst_account.py
Normal file
10
erpnext/accounts/doctype/gst_account/gst_account.py
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, 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 GSTAccount(Document):
|
||||
pass
|
@ -124,6 +124,15 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
};
|
||||
}
|
||||
|
||||
if(jvd.reference_type==="Employee Advance") {
|
||||
return {
|
||||
filters: {
|
||||
'status': ['=', 'Unpaid'],
|
||||
'docstatus': 1
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// journal entry
|
||||
if(jvd.reference_type==="Journal Entry") {
|
||||
frappe.model.validate_missing(jvd, "account");
|
||||
@ -185,56 +194,21 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
})
|
||||
},
|
||||
|
||||
due_date_options_cache: {},
|
||||
|
||||
reference_name: function(doc, cdt, cdn) {
|
||||
var d = frappe.get_doc(cdt, cdn);
|
||||
var me = this;
|
||||
|
||||
const get_invoice_due_dates = invoice_name => {
|
||||
const options = this.due_date_options_cache[invoice_name];
|
||||
const input = $(cur_frm.fields_dict["accounts"].wrapper).find("select[data-fieldname=reference_due_date]");
|
||||
|
||||
if (options) {
|
||||
input.empty();
|
||||
input.add_options(options);
|
||||
frappe.model.set_value(cdt, cdn, "reference_due_date", options[0]);
|
||||
}
|
||||
else {
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_invoice_due_dates",
|
||||
args: {name: invoice_name},
|
||||
callback: function(r) {
|
||||
const options = [];
|
||||
$.each(r.message, function(key, value) {
|
||||
options.push(value.due_date);
|
||||
});
|
||||
input.empty();
|
||||
input.add_options(options);
|
||||
frappe.model.set_value(cdt, cdn, "reference_due_date", options[0]);
|
||||
me.due_date_options_cache[d.reference_name] = options;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(d.reference_name) {
|
||||
if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) {
|
||||
this.get_outstanding('Purchase Invoice', d.reference_name, doc.company, d);
|
||||
}
|
||||
if (d.reference_type==="Sales Invoice" && !flt(d.credit)) {
|
||||
} else if (d.reference_type==="Sales Invoice" && !flt(d.credit)) {
|
||||
this.get_outstanding('Sales Invoice', d.reference_name, doc.company, d);
|
||||
}
|
||||
if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
|
||||
} else if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
|
||||
this.get_outstanding('Journal Entry', d.reference_name, doc.company, d);
|
||||
}
|
||||
if( in_list(["Sales Invoice", "Purchase Invoice"]), d.reference_type) {
|
||||
get_invoice_due_dates(d.reference_name);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get_outstanding: function(doctype, docname, company, child) {
|
||||
get_outstanding: function(doctype, docname, company, child, due_date) {
|
||||
var me = this;
|
||||
var args = {
|
||||
"doctype": doctype,
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, erpnext, json
|
||||
from frappe.utils import cstr, flt, fmt_money, formatdate
|
||||
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate
|
||||
from frappe import msgprint, _, scrub
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
from erpnext.accounts.utils import get_balance_on, get_account_currency
|
||||
@ -54,8 +54,8 @@ class JournalEntry(AccountsController):
|
||||
def update_advance_paid(self):
|
||||
advance_paid = frappe._dict()
|
||||
for d in self.get("accounts"):
|
||||
if d.is_advance == "Yes":
|
||||
if d.reference_type in ("Sales Order", "Purchase Order"):
|
||||
if d.is_advance:
|
||||
if d.reference_type in ("Sales Order", "Purchase Order", "Employee Advance"):
|
||||
advance_paid.setdefault(d.reference_type, []).append(d.reference_name)
|
||||
|
||||
for voucher_type, order_list in advance_paid.items():
|
||||
@ -101,8 +101,6 @@ class JournalEntry(AccountsController):
|
||||
if account_type in ["Receivable", "Payable"]:
|
||||
if not (d.party_type and d.party):
|
||||
frappe.throw(_("Row {0}: Party Type and Party is required for Receivable / Payable account {1}").format(d.idx, d.account))
|
||||
elif d.party_type and d.party:
|
||||
frappe.throw(_("Row {0}: Party Type and Party is only applicable against Receivable / Payable account").format(d.idx))
|
||||
|
||||
def check_credit_limit(self):
|
||||
customers = list(set([d.party for d in self.get("accounts")
|
||||
@ -436,8 +434,7 @@ class JournalEntry(AccountsController):
|
||||
"against_voucher": d.reference_name,
|
||||
"remarks": self.remark,
|
||||
"cost_center": d.cost_center,
|
||||
"project": d.project,
|
||||
"due_date": d.reference_due_date
|
||||
"project": d.project
|
||||
})
|
||||
)
|
||||
|
||||
@ -649,9 +646,8 @@ def get_payment_entry_against_invoice(dt, dn, amount=None, debit_in_account_cur
|
||||
party_type = "Supplier"
|
||||
party_account = ref_doc.credit_to
|
||||
|
||||
|
||||
if (dt=="Sales Invoice" and ref_doc.outstanding_amount > 0) \
|
||||
or (dt=="Purchase Invoice" and ref_doc.outstanding_amount < 0):
|
||||
if (dt == "Sales Invoice" and ref_doc.outstanding_amount > 0) \
|
||||
or (dt == "Purchase Invoice" and ref_doc.outstanding_amount < 0):
|
||||
amount_field_party = "credit_in_account_currency"
|
||||
amount_field_bank = "debit_in_account_currency"
|
||||
else:
|
||||
@ -672,6 +668,7 @@ def get_payment_entry_against_invoice(dt, dn, amount=None, debit_in_account_cur
|
||||
"journal_entry": journal_entry
|
||||
})
|
||||
|
||||
|
||||
def get_payment_entry(ref_doc, args):
|
||||
cost_center = frappe.db.get_value("Company", ref_doc.company, "cost_center")
|
||||
exchange_rate = 1
|
||||
@ -696,7 +693,7 @@ def get_payment_entry(ref_doc, args):
|
||||
"cost_center": cost_center,
|
||||
"account_type": frappe.db.get_value("Account", args.get("party_account"), "account_type"),
|
||||
"account_currency": args.get("party_account_currency") or \
|
||||
get_account_currency(args.get("party_account")),
|
||||
get_account_currency(args.get("party_account")),
|
||||
"balance": get_balance_on(args.get("party_account")),
|
||||
"party_balance": get_balance_on(party=args.get("party"), party_type=args.get("party_type")),
|
||||
"exchange_rate": exchange_rate,
|
||||
@ -708,7 +705,7 @@ def get_payment_entry(ref_doc, args):
|
||||
|
||||
bank_row = je.append("accounts")
|
||||
|
||||
#make it bank_details
|
||||
# Make it bank_details
|
||||
bank_account = get_default_bank_cash_account(ref_doc.company, "Bank", account=args.get("bank_account"))
|
||||
if bank_account:
|
||||
bank_row.update(bank_account)
|
||||
@ -727,7 +724,7 @@ def get_payment_entry(ref_doc, args):
|
||||
else:
|
||||
bank_row.set(args.get("amount_field_bank"), amount * exchange_rate)
|
||||
|
||||
# set multi currency check
|
||||
# Multi currency check again
|
||||
if party_row.account_currency != ref_doc.company_currency \
|
||||
or (bank_row.account_currency and bank_row.account_currency != ref_doc.company_currency):
|
||||
je.multi_currency = 1
|
||||
@ -737,6 +734,7 @@ def get_payment_entry(ref_doc, args):
|
||||
|
||||
return je if args.get("journal_entry") else je.as_dict()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_opening_accounts(company):
|
||||
"""get all balance sheet accounts for opening entry"""
|
||||
@ -759,6 +757,7 @@ def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
|
||||
and jv.docstatus = 1 and jv.`{0}` like %s order by jv.name desc limit %s, %s""".format(frappe.db.escape(searchfield)),
|
||||
(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_outstanding(args):
|
||||
if not frappe.has_permission("Account"):
|
||||
@ -820,6 +819,7 @@ def get_party_account_and_balance(company, party_type, party):
|
||||
"account_currency": frappe.db.get_value("Account", account, "account_currency")
|
||||
}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_account_balance_and_party_type(account, date, company, debit=None, credit=None, exchange_rate=None):
|
||||
"""Returns dict of account balance and party type to be set in Journal Entry on selection of account."""
|
||||
@ -857,7 +857,7 @@ def get_account_balance_and_party_type(account, date, company, debit=None, credi
|
||||
|
||||
return grid_values
|
||||
|
||||
# Added posting_date as one of the parameters of get_exchange_rate
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_exchange_rate(posting_date, account=None, account_currency=None, company=None,
|
||||
reference_type=None, reference_name=None, debit=None, credit=None, exchange_rate=None):
|
||||
@ -890,6 +890,7 @@ def get_exchange_rate(posting_date, account=None, account_currency=None, company
|
||||
# don't return None or 0 as it is multipled with a value and that value could be lost
|
||||
return exchange_rate or 1
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_average_exchange_rate(account):
|
||||
exchange_rate = 0
|
||||
@ -899,14 +900,3 @@ def get_average_exchange_rate(account):
|
||||
exchange_rate = bank_balance_in_company_currency / bank_balance_in_account_currency
|
||||
|
||||
return exchange_rate
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_invoice_due_dates(name):
|
||||
result = frappe.get_list(
|
||||
doctype='GL Entry', group_by='name, due_date',
|
||||
filters={'voucher_no': name, "ifnull(due_date, '')": ('!=', '')},
|
||||
fields=['due_date'], distinct=True
|
||||
)
|
||||
|
||||
return result
|
||||
|
@ -618,7 +618,7 @@
|
||||
"label": "Reference Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset\nEmployee Loan\nPayroll Entry",
|
||||
"options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim\nAsset\nEmployee Loan\nPayroll Entry\nEmployee Advance",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -662,38 +662,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.reference_type&&!in_list(doc.reference_type, ['Expense Claim', 'Asset', 'Employee Loan'])",
|
||||
"fieldname": "reference_due_date",
|
||||
"fieldtype": "Select",
|
||||
"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": "Reference Due Date",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -827,7 +795,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-06 19:54:19.851534",
|
||||
"modified": "2017-12-07 19:54:19.851534",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Entry Account",
|
||||
|
@ -4,10 +4,11 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
from frappe import _, scrub
|
||||
from frappe.utils import flt, nowdate
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class OpeningInvoiceCreationTool(Document):
|
||||
def onload(self):
|
||||
"""Load the Opening Invoice summary"""
|
||||
@ -67,29 +68,25 @@ class OpeningInvoiceCreationTool(Document):
|
||||
for row in self.invoices:
|
||||
if not row.qty:
|
||||
row.qty = 1.0
|
||||
if not row.party:
|
||||
frappe.throw(mandatory_error_msg.format(
|
||||
idx=row.idx,
|
||||
field= _("Party"),
|
||||
invoice_type=self.invoice_type
|
||||
))
|
||||
# set party type if not available
|
||||
if not row.party_type:
|
||||
row.party_type = "Customer" if self.invoice_type == "Sales" else "Supplier"
|
||||
|
||||
# always mandatory fields for the invoices
|
||||
if not row.temporary_opening_account:
|
||||
row.temporary_opening_account = get_temporary_opening_account(self.company)
|
||||
row.party_type = "Customer" if self.invoice_type == "Sales" else "Supplier"
|
||||
if not row.item_name:
|
||||
row.item_name = _("Opening Invoice Item")
|
||||
if not row.posting_date:
|
||||
frappe.throw(mandatory_error_msg.format(
|
||||
idx=row.idx,
|
||||
field= _("Party"),
|
||||
invoice_type=self.invoice_type
|
||||
))
|
||||
row.posting_date = nowdate()
|
||||
if not row.due_date:
|
||||
row.due_date = nowdate()
|
||||
|
||||
if not row.outstanding_amount:
|
||||
frappe.throw(mandatory_error_msg.format(
|
||||
idx=row.idx,
|
||||
field= _("Outstanding Amount"),
|
||||
invoice_type=self.invoice_type
|
||||
))
|
||||
for d in ("Party", "Outstanding Amount", "Temporary Opening Account"):
|
||||
if not row.get(scrub(d)):
|
||||
frappe.throw(mandatory_error_msg.format(
|
||||
idx=row.idx,
|
||||
field=_(d),
|
||||
invoice_type=self.invoice_type
|
||||
))
|
||||
|
||||
args = self.get_invoice_dict(row=row)
|
||||
if not args:
|
||||
@ -99,10 +96,14 @@ class OpeningInvoiceCreationTool(Document):
|
||||
doc.submit()
|
||||
names.append(doc.name)
|
||||
|
||||
if(len(self.invoices) > 5):
|
||||
frappe.publish_realtime("progress",
|
||||
dict(progress=[row.idx, len(self.invoices)], title=_('Creating {0}').format(doc.doctype)),
|
||||
user=frappe.session.user)
|
||||
if len(self.invoices) > 5:
|
||||
frappe.publish_realtime(
|
||||
"progress", dict(
|
||||
progress=[row.idx, len(self.invoices)],
|
||||
title=_('Creating {0}').format(doc.doctype)
|
||||
),
|
||||
user=frappe.session.user
|
||||
)
|
||||
|
||||
return names
|
||||
|
||||
@ -111,8 +112,10 @@ class OpeningInvoiceCreationTool(Document):
|
||||
default_uom = frappe.db.get_single_value("Stock Settings", "stock_uom") or _("Nos")
|
||||
cost_center = frappe.db.get_value("Company", self.company, "cost_center")
|
||||
if not cost_center:
|
||||
frappe.throw(_("Please set the Default Cost Center in {0} company").format(frappe.bold(self.company)))
|
||||
rate = flt(row.outstanding_amount) / row.qty
|
||||
frappe.throw(
|
||||
_("Please set the Default Cost Center in {0} company").format(frappe.bold(self.company))
|
||||
)
|
||||
rate = flt(row.outstanding_amount) / flt(row.qty)
|
||||
|
||||
return frappe._dict({
|
||||
"uom": default_uom,
|
||||
@ -143,8 +146,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",
|
||||
"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice",
|
||||
"currency": frappe.db.get_value("Company", self.company, "default_currency")
|
||||
})
|
||||
|
||||
|
@ -161,7 +161,7 @@
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -192,7 +192,7 @@
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -284,6 +284,66 @@
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "qty",
|
||||
"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": "Quantity",
|
||||
"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,
|
||||
@ -300,7 +360,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-15 14:19:00.433148",
|
||||
"modified": "2017-12-19 05:07:01.549918",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Opening Invoice Creation Tool Item",
|
||||
|
@ -266,6 +266,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
}
|
||||
},
|
||||
() => frm.set_value("party_balance", r.message.party_balance),
|
||||
() => frm.set_value("party_name", r.message.party_name),
|
||||
() => frm.events.get_outstanding_documents(frm),
|
||||
() => frm.events.hide_unhide_fields(frm),
|
||||
() => frm.events.set_dynamic_labels(frm),
|
||||
@ -408,7 +409,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
}
|
||||
|
||||
// Make read only if Accounts Settings doesn't allow stale rates
|
||||
frm.set_df_property("source_exchange_rate", "read_only", erpnext.stale_rate_allowed());
|
||||
frm.set_df_property("source_exchange_rate", "read_only", erpnext.stale_rate_allowed() ? 0 : 1);
|
||||
},
|
||||
|
||||
target_exchange_rate: function(frm) {
|
||||
@ -429,7 +430,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
frm.set_paid_amount_based_on_received_amount = false;
|
||||
|
||||
// Make read only if Accounts Settings doesn't allow stale rates
|
||||
frm.set_df_property("target_exchange_rate", "read_only", erpnext.stale_rate_allowed());
|
||||
frm.set_df_property("target_exchange_rate", "read_only", erpnext.stale_rate_allowed() ? 0 : 1);
|
||||
},
|
||||
|
||||
paid_amount: function(frm) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
import frappe, erpnext, json
|
||||
from frappe import _, scrub, ValidationError
|
||||
from frappe.utils import flt, comma_or, nowdate
|
||||
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on
|
||||
@ -71,9 +71,10 @@ class PaymentEntry(AccountsController):
|
||||
def validate_duplicate_entry(self):
|
||||
reference_names = []
|
||||
for d in self.get("references"):
|
||||
if (d.reference_doctype, d.reference_name, d.due_date) in reference_names:
|
||||
frappe.throw(_("Row #{0}: Duplicate entry in References {1} {2}").format(d.idx, d.reference_doctype, d.reference_name))
|
||||
reference_names.append((d.reference_doctype, d.reference_name, d.due_date))
|
||||
if (d.reference_doctype, d.reference_name) in reference_names:
|
||||
frappe.throw(_("Row #{0}: Duplicate entry in References {1} {2}")
|
||||
.format(d.idx, d.reference_doctype, d.reference_name))
|
||||
reference_names.append((d.reference_doctype, d.reference_name))
|
||||
|
||||
def validate_allocated_amount(self):
|
||||
for d in self.get("references"):
|
||||
@ -147,7 +148,7 @@ class PaymentEntry(AccountsController):
|
||||
if not frappe.db.exists(self.party_type, self.party):
|
||||
frappe.throw(_("Invalid {0}: {1}").format(self.party_type, self.party))
|
||||
|
||||
if self.party_account:
|
||||
if self.party_account and self.party_type != "Employee":
|
||||
party_account_type = "Receivable" if self.party_type in ("Customer", "Student") else "Payable"
|
||||
self.validate_account_type(self.party_account, [party_account_type])
|
||||
|
||||
@ -188,7 +189,7 @@ class PaymentEntry(AccountsController):
|
||||
elif self.party_type == "Supplier":
|
||||
valid_reference_doctypes = ("Purchase Order", "Purchase Invoice", "Journal Entry")
|
||||
elif self.party_type == "Employee":
|
||||
valid_reference_doctypes = ("Expense Claim", "Journal Entry")
|
||||
valid_reference_doctypes = ("Expense Claim", "Journal Entry", "Employee Advance")
|
||||
|
||||
for d in self.get("references"):
|
||||
if not d.allocated_amount:
|
||||
@ -205,7 +206,7 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
if d.reference_doctype != "Journal Entry":
|
||||
if self.party != ref_doc.get(scrub(self.party_type)):
|
||||
frappe.throw(_("{0} {1} does not associated with {2} {3}")
|
||||
frappe.throw(_("{0} {1} is not associated with {2} {3}")
|
||||
.format(d.reference_doctype, d.reference_name, self.party_type, self.party))
|
||||
else:
|
||||
self.validate_journal_entry()
|
||||
@ -413,8 +414,7 @@ class PaymentEntry(AccountsController):
|
||||
gle = party_gl_dict.copy()
|
||||
gle.update({
|
||||
"against_voucher_type": d.reference_doctype,
|
||||
"against_voucher": d.reference_name,
|
||||
"due_date": d.due_date
|
||||
"against_voucher": d.reference_name
|
||||
})
|
||||
|
||||
allocated_amount_in_company_currency = flt(flt(d.allocated_amount) * flt(d.exchange_rate),
|
||||
@ -483,8 +483,9 @@ class PaymentEntry(AccountsController):
|
||||
def update_advance_paid(self):
|
||||
if self.payment_type in ("Receive", "Pay") and self.party:
|
||||
for d in self.get("references"):
|
||||
if d.allocated_amount and d.reference_doctype in ("Sales Order", "Purchase Order"):
|
||||
frappe.get_doc(d.reference_doctype, d.reference_name).set_total_advance_paid()
|
||||
if d.allocated_amount \
|
||||
and d.reference_doctype in ("Sales Order", "Purchase Order", "Employee Advance"):
|
||||
frappe.get_doc(d.reference_doctype, d.reference_name).set_total_advance_paid()
|
||||
|
||||
def update_expense_claim(self):
|
||||
if self.payment_type in ("Pay") and self.party:
|
||||
@ -507,13 +508,18 @@ def get_outstanding_reference_documents(args):
|
||||
|
||||
# Get negative outstanding sales /purchase invoices
|
||||
negative_outstanding_invoices = []
|
||||
if args.get("party_type") not in ["Student", "Employee"]:
|
||||
if args.get("party_type") not in ["Student", "Employee"] and not args.get("voucher_no"):
|
||||
negative_outstanding_invoices = get_negative_outstanding_invoices(args.get("party_type"),
|
||||
args.get("party"), args.get("party_account"), party_account_currency, company_currency)
|
||||
|
||||
# Get positive outstanding sales /purchase invoices/ Fees
|
||||
condition = ""
|
||||
if args.get("voucher_type") and args.get("voucher_no"):
|
||||
condition = " and voucher_type='{0}' and voucher_no='{1}'"\
|
||||
.format(frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"]))
|
||||
|
||||
outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"),
|
||||
args.get("party_account"))
|
||||
args.get("party_account"), condition=condition)
|
||||
|
||||
for d in outstanding_invoices:
|
||||
d["exchange_rate"] = 1
|
||||
@ -535,6 +541,7 @@ def get_outstanding_reference_documents(args):
|
||||
|
||||
return negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed
|
||||
|
||||
|
||||
def get_orders_to_be_billed(posting_date, party_type, party, party_account_currency, company_currency):
|
||||
if party_type == "Customer":
|
||||
voucher_type = 'Sales Order'
|
||||
@ -563,18 +570,17 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre
|
||||
and abs(100 - per_billed) > 0.01
|
||||
order by
|
||||
transaction_date, name
|
||||
""".format(**{
|
||||
"ref_field": ref_field,
|
||||
"voucher_type": voucher_type,
|
||||
"party_type": scrub(party_type)
|
||||
}), party, as_dict = True)
|
||||
""".format(**{
|
||||
"ref_field": ref_field,
|
||||
"voucher_type": voucher_type,
|
||||
"party_type": scrub(party_type)
|
||||
}), party, as_dict=True)
|
||||
|
||||
order_list = []
|
||||
for d in orders:
|
||||
d["voucher_type"] = voucher_type
|
||||
# This assumes that the exchange rate required is the one in the SO
|
||||
d["exchange_rate"] = get_exchange_rate(party_account_currency,
|
||||
company_currency, posting_date)
|
||||
d["exchange_rate"] = get_exchange_rate(party_account_currency, company_currency, posting_date)
|
||||
order_list.append(d)
|
||||
|
||||
return order_list
|
||||
@ -608,6 +614,7 @@ def get_negative_outstanding_invoices(party_type, party, party_account, party_ac
|
||||
"party_account": "debit_to" if party_type == "Customer" else "credit_to"
|
||||
}), (party, party_account), as_dict=True)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_party_details(company, party_type, party, date):
|
||||
if not frappe.db.exists(party_type, party):
|
||||
@ -617,15 +624,19 @@ def get_party_details(company, party_type, party, date):
|
||||
|
||||
account_currency = get_account_currency(party_account)
|
||||
account_balance = get_balance_on(party_account, date)
|
||||
_party_name = "title" if party_type == "Student" else party_type.lower() + "_name"
|
||||
party_name = frappe.db.get_value(party_type, party, _party_name)
|
||||
party_balance = get_balance_on(party_type=party_type, party=party)
|
||||
|
||||
return {
|
||||
"party_account": party_account,
|
||||
"party_name": party_name,
|
||||
"party_account_currency": account_currency,
|
||||
"party_balance": party_balance,
|
||||
"account_balance": account_balance
|
||||
}
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_account_details(account, date):
|
||||
frappe.has_permission('Payment Entry', throw=True)
|
||||
@ -635,6 +646,7 @@ def get_account_details(account, date):
|
||||
"account_type": frappe.db.get_value("Account", account, "account_type")
|
||||
})
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_company_defaults(company):
|
||||
fields = ["write_off_account", "exchange_gain_loss_account", "cost_center"]
|
||||
@ -647,19 +659,23 @@ def get_company_defaults(company):
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_reference_details(reference_doctype, reference_name, party_account_currency):
|
||||
total_amount = outstanding_amount = exchange_rate = None
|
||||
ref_doc = frappe.get_doc(reference_doctype, reference_name)
|
||||
company_currency = ref_doc.get("company_currency") or erpnext.get_company_currency(ref_doc.company)
|
||||
|
||||
if reference_doctype == "Fees":
|
||||
total_amount = ref_doc.get("grand_total")
|
||||
exchange_rate = 1
|
||||
outstanding_amount = ref_doc.get("outstanding_amount")
|
||||
elif reference_doctype != "Journal Entry":
|
||||
if party_account_currency == ref_doc.company_currency:
|
||||
if party_account_currency == company_currency:
|
||||
if ref_doc.doctype == "Expense Claim":
|
||||
total_amount = ref_doc.total_sanctioned_amount
|
||||
elif ref_doc.doctype == "Employee Advance":
|
||||
total_amount = ref_doc.advance_amount
|
||||
else:
|
||||
total_amount = ref_doc.base_grand_total
|
||||
exchange_rate = 1
|
||||
@ -669,15 +685,18 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
|
||||
# Get the exchange rate from the original ref doc
|
||||
# or get it based on the posting date of the ref doc
|
||||
exchange_rate = ref_doc.get("conversion_rate") or \
|
||||
get_exchange_rate(party_account_currency, ref_doc.company_currency, ref_doc.posting_date)
|
||||
get_exchange_rate(party_account_currency, company_currency, ref_doc.posting_date)
|
||||
|
||||
outstanding_amount = ref_doc.get("outstanding_amount") \
|
||||
if reference_doctype in ("Sales Invoice", "Purchase Invoice", "Expense Claim") \
|
||||
else flt(total_amount) - flt(ref_doc.advance_paid)
|
||||
if reference_doctype in ("Sales Invoice", "Purchase Invoice", "Expense Claim"):
|
||||
outstanding_amount = ref_doc.get("outstanding_amount")
|
||||
elif reference_doctype == "Employee Advance":
|
||||
outstanding_amount = ref_doc.advance_amount - flt(ref_doc.paid_amount)
|
||||
else:
|
||||
outstanding_amount = flt(total_amount) - flt(ref_doc.advance_paid)
|
||||
else:
|
||||
# Get the exchange rate based on the posting date of the ref doc
|
||||
exchange_rate = get_exchange_rate(party_account_currency,
|
||||
ref_doc.company_currency, ref_doc.posting_date)
|
||||
company_currency, ref_doc.posting_date)
|
||||
|
||||
return frappe._dict({
|
||||
"due_date": ref_doc.get("due_date"),
|
||||
@ -686,6 +705,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
|
||||
"exchange_rate": exchange_rate
|
||||
})
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=None):
|
||||
doc = frappe.get_doc(dt, dn)
|
||||
@ -697,7 +717,7 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
||||
party_type = "Customer"
|
||||
elif dt in ("Purchase Invoice", "Purchase Order"):
|
||||
party_type = "Supplier"
|
||||
elif dt in ("Expense Claim"):
|
||||
elif dt in ("Expense Claim", "Employee Advance"):
|
||||
party_type = "Employee"
|
||||
elif dt in ("Fees"):
|
||||
party_type = "Student"
|
||||
@ -709,6 +729,8 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
||||
party_account = doc.credit_to
|
||||
elif dt == "Fees":
|
||||
party_account = doc.receivable_account
|
||||
elif dt == "Employee Advance":
|
||||
party_account = doc.advance_account
|
||||
else:
|
||||
party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company)
|
||||
|
||||
@ -733,7 +755,11 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
||||
outstanding_amount = doc.outstanding_amount
|
||||
elif dt in ("Expense Claim"):
|
||||
grand_total = doc.total_sanctioned_amount
|
||||
outstanding_amount = doc.total_sanctioned_amount - doc.total_amount_reimbursed
|
||||
outstanding_amount = doc.total_sanctioned_amount \
|
||||
- doc.total_amount_reimbursed - flt(doc.total_advance_amount)
|
||||
elif dt == "Employee Advance":
|
||||
grand_total = doc.advance_amount
|
||||
outstanding_amount = flt(doc.advance_amount) - flt(doc.paid_amount)
|
||||
elif dt == "Fees":
|
||||
grand_total = doc.grand_total
|
||||
outstanding_amount = doc.outstanding_amount
|
||||
@ -776,26 +802,16 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
||||
pe.received_amount = received_amount
|
||||
pe.allocate_payment_amount = 1
|
||||
pe.letter_head = doc.get("letter_head")
|
||||
args = {
|
||||
'party_account': party_account, 'company': pe.company, 'party_type': pe.party_type,
|
||||
'party': pe.party, 'posting_date': pe.posting_date
|
||||
}
|
||||
references = get_outstanding_reference_documents(args=args)
|
||||
|
||||
for reference in references:
|
||||
if reference.voucher_no == dn:
|
||||
allocated_amount = min(paid_amount, reference.outstanding_amount)
|
||||
pe.append("references", {
|
||||
'reference_doctype': reference.voucher_type,
|
||||
'reference_name': reference.voucher_no,
|
||||
'due_date': reference.due_date,
|
||||
'total_amount': reference.invoice_amount,
|
||||
'outstanding_amount': reference.outstanding_amount,
|
||||
'allocated_amount': allocated_amount,
|
||||
"bill_no": reference.get("bill_no")
|
||||
})
|
||||
if paid_amount:
|
||||
paid_amount -= allocated_amount
|
||||
pe.append("references", {
|
||||
'reference_doctype': dt,
|
||||
'reference_name': dn,
|
||||
"bill_no": doc.get("bill_no"),
|
||||
"due_date": doc.get("due_date"),
|
||||
'total_amount': grand_total,
|
||||
'outstanding_amount': outstanding_amount,
|
||||
'allocated_amount': outstanding_amount
|
||||
})
|
||||
|
||||
pe.setup_party_account_field()
|
||||
pe.set_missing_values()
|
||||
|
@ -66,18 +66,6 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
|
||||
self.assertEqual(outstanding_amount, 100)
|
||||
|
||||
def test_payment_entry_against_si_multi_due_dates(self):
|
||||
si = create_sales_invoice(do_not_save=1)
|
||||
si.payment_terms_template = '_Test Payment Term Template'
|
||||
si.insert()
|
||||
si.submit()
|
||||
|
||||
pe = get_payment_entry(si.doctype, si.name)
|
||||
pe.reference_no = "1"
|
||||
pe.reference_date = "2016-01-01"
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
def test_payment_entry_against_pi(self):
|
||||
pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC",
|
||||
currency="USD", conversion_rate=50)
|
||||
@ -106,6 +94,7 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
pe.reference_no = "1"
|
||||
pe.reference_date = "2016-01-01"
|
||||
pe.source_exchange_rate = 1
|
||||
pe.paid_to = payable
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
|
@ -67,7 +67,7 @@
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -98,7 +98,7 @@
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
@ -160,7 +160,7 @@
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
@ -179,8 +179,8 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-23 12:39:02.013040",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2017-12-19 16:20:33.546984",
|
||||
"modified_by": "nabinhait@gmail.com",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Schedule",
|
||||
"name_case": "",
|
||||
|
@ -106,11 +106,6 @@ cur_frm.fields_dict['select_print_heading'].get_query = function(doc, cdt, cdn)
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
cur_frm.fields_dict.user.get_query = function(doc,cdt,cdn) {
|
||||
return{ query:"frappe.core.doctype.user.user.user_query"};
|
||||
};
|
||||
|
||||
cur_frm.fields_dict.write_off_account.get_query = function(doc) {
|
||||
return{
|
||||
filters:{
|
||||
|
@ -101,38 +101,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "user",
|
||||
"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": "Applicable for User",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "user",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "User",
|
||||
"permlevel": 0,
|
||||
"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": 1,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -162,7 +130,7 @@
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 1,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -1508,7 +1476,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-24 14:08:09.184226",
|
||||
"modified": "2018-01-03 17:30:45.198147",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Profile",
|
||||
|
@ -31,8 +31,8 @@ class POSProfile(Document):
|
||||
msgprint(_("Already set default in pos profile {0} for user {1}, kindly disabled default")
|
||||
.format(res[0][0], row.user), raise_exception=1)
|
||||
elif not row.default and not res:
|
||||
msgprint(_("Row {0}: set atleast one default pos profile for user {1}")
|
||||
.format(row.idx, row.user), raise_exception=1)
|
||||
msgprint(_("User {0} doesn't have any default POS Profile. Check Default at Row {1} for this User.")
|
||||
.format(row.user, row.idx), raise_exception=1)
|
||||
|
||||
def validate_all_link_fields(self):
|
||||
accounts = {"Account": [self.income_account,
|
||||
@ -63,7 +63,11 @@ class POSProfile(Document):
|
||||
|
||||
if len(default_mode_of_payment) > 1:
|
||||
frappe.throw(_("Multiple default mode of payment is not allowed"))
|
||||
|
||||
def validate_customer_territory_group(self):
|
||||
if not frappe.db.get_single_value('POS Settings', 'use_pos_in_offline_mode'):
|
||||
return
|
||||
|
||||
if not self.territory:
|
||||
frappe.throw(_("Territory is Required in POS Profile"), title="Mandatory Field")
|
||||
|
||||
@ -83,12 +87,12 @@ class POSProfile(Document):
|
||||
frappe.defaults.clear_default("is_pos")
|
||||
|
||||
if not include_current_pos:
|
||||
condition = " where name != '%s'" % self.name.replace("'", "\'")
|
||||
condition = " where pfu.name != '%s' and pfu.default = 1 " % self.name.replace("'", "\'")
|
||||
else:
|
||||
condition = ""
|
||||
condition = " where pfu.default = 1 "
|
||||
|
||||
pos_view_users = frappe.db.sql_list("""select user
|
||||
from `tabPOS Profile` {0}""".format(condition))
|
||||
pos_view_users = frappe.db.sql_list("""select pfu.user
|
||||
from `tabPOS Profile User` as pfu {0}""".format(condition))
|
||||
|
||||
for user in pos_view_users:
|
||||
if user:
|
||||
@ -103,7 +107,7 @@ def get_item_groups(pos_profile):
|
||||
if pos_profile.get('item_groups'):
|
||||
# Get items based on the item groups defined in the POS profile
|
||||
for data in pos_profile.get('item_groups'):
|
||||
item_groups.extend(["'%s'"%d.name for d in get_child_nodes('Item Group', data.item_group)])
|
||||
item_groups.extend(["'%s'" % frappe.db.escape(d.name) for d in get_child_nodes('Item Group', data.item_group)])
|
||||
|
||||
return list(set(item_groups))
|
||||
|
||||
|
@ -140,6 +140,37 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "tax_id",
|
||||
"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": "Tax Id",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "supplier.tax_id",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -161,7 +192,7 @@
|
||||
"oldfieldname": "due_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@ -3086,7 +3117,7 @@
|
||||
"options": "Payment Schedule",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@ -3883,7 +3914,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2017-11-29 13:44:40.722157",
|
||||
"modified": "2017-12-20 17:49:51.230092",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
|
@ -277,6 +277,8 @@ class PurchaseInvoice(BuyingController):
|
||||
.format(item.purchase_receipt))
|
||||
|
||||
def on_submit(self):
|
||||
super(PurchaseInvoice, self).on_submit()
|
||||
|
||||
self.check_prev_docstatus()
|
||||
self.update_status_updater_args()
|
||||
|
||||
@ -348,7 +350,6 @@ class PurchaseInvoice(BuyingController):
|
||||
self.negative_expense_to_be_booked = 0.0
|
||||
gl_entries = []
|
||||
|
||||
|
||||
self.make_supplier_gl_entry(gl_entries)
|
||||
self.make_item_gl_entries(gl_entries)
|
||||
self.make_tax_gl_entries(gl_entries)
|
||||
@ -363,27 +364,7 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
def make_supplier_gl_entry(self, gl_entries):
|
||||
grand_total = self.rounded_total or self.grand_total
|
||||
if self.get("payment_schedule"):
|
||||
for d in self.get("payment_schedule"):
|
||||
payment_amount_in_company_currency = flt(d.payment_amount * self.conversion_rate,
|
||||
d.precision("payment_amount"))
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.credit_to,
|
||||
"party_type": "Supplier",
|
||||
"party": self.supplier,
|
||||
"due_date": d.due_date,
|
||||
"against": self.against_expense_account,
|
||||
"credit": payment_amount_in_company_currency,
|
||||
"credit_in_account_currency": payment_amount_in_company_currency \
|
||||
if self.party_account_currency==self.company_currency else d.payment_amount,
|
||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||
"against_voucher_type": self.doctype
|
||||
}, self.party_account_currency)
|
||||
)
|
||||
|
||||
elif grand_total:
|
||||
if grand_total:
|
||||
# Didnot use base_grand_total to book rounding loss gle
|
||||
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
||||
self.precision("grand_total"))
|
||||
@ -442,7 +423,10 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
# sub-contracting warehouse
|
||||
if flt(item.rm_supp_cost):
|
||||
supplier_warehouse_account = warehouse_account[self.supplier_warehouse]["name"]
|
||||
supplier_warehouse_account = warehouse_account[self.supplier_warehouse]["account"]
|
||||
if not supplier_warehouse_account:
|
||||
frappe.throw(_("Please set account in Warehouse {0}")
|
||||
.format(self.supplier_warehouse))
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": supplier_warehouse_account,
|
||||
"against": item.expense_account,
|
||||
@ -626,6 +610,8 @@ class PurchaseInvoice(BuyingController):
|
||||
))
|
||||
|
||||
def on_cancel(self):
|
||||
super(PurchaseInvoice, self).on_cancel()
|
||||
|
||||
self.check_for_closed_status()
|
||||
|
||||
self.update_status_updater_args()
|
||||
|
@ -1,7 +1,7 @@
|
||||
QUnit.module('Purchase Invoice');
|
||||
|
||||
QUnit.test("test purchase invoice", function(assert) {
|
||||
assert.expect(6);
|
||||
assert.expect(9);
|
||||
let done = assert.async();
|
||||
frappe.run_serially([
|
||||
() => {
|
||||
@ -18,7 +18,7 @@ QUnit.test("test purchase invoice", function(assert) {
|
||||
{update_stock:1},
|
||||
{supplier_address: 'Test1-Billing'},
|
||||
{contact_person: 'Contact 3-Test Supplier'},
|
||||
{taxes_and_charges: 'TEST In State GST'},
|
||||
{taxes_and_charges: 'TEST In State GST - FT'},
|
||||
{tc_name: 'Test Term 1'},
|
||||
{terms: 'This is Test'},
|
||||
{payment_terms_template: '_Test Payment Term Template UI'}
|
||||
@ -29,7 +29,7 @@ QUnit.test("test purchase invoice", function(assert) {
|
||||
// get_item_details
|
||||
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
|
||||
// get tax details
|
||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
|
||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
|
||||
// get tax account head details
|
||||
assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
|
||||
// grand_total Calculated
|
||||
@ -39,6 +39,33 @@ QUnit.test("test purchase invoice", function(assert) {
|
||||
assert.ok(cur_frm.doc.payment_schedule.length > 0, "Payment Term Schedule is not empty");
|
||||
|
||||
},
|
||||
() => {
|
||||
let date = cur_frm.doc.due_date;
|
||||
frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
|
||||
frappe.timeout(0.5);
|
||||
assert.ok(cur_dialog && cur_dialog.is_visible, 'Message is displayed to user');
|
||||
},
|
||||
() => frappe.timeout(1),
|
||||
() => frappe.tests.click_button('Close'),
|
||||
() => frappe.timeout(0.5),
|
||||
() => frappe.tests.set_form_values(cur_frm, [{'payment_terms_schedule': ''}]),
|
||||
() => {
|
||||
let date = cur_frm.doc.due_date;
|
||||
frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
|
||||
frappe.timeout(0.5);
|
||||
assert.ok(cur_dialog && cur_dialog.is_visible, 'Message is displayed to user');
|
||||
},
|
||||
() => frappe.timeout(1),
|
||||
() => frappe.tests.click_button('Close'),
|
||||
() => frappe.timeout(0.5),
|
||||
() => frappe.tests.set_form_values(cur_frm, [{'payment_schedule': []}]),
|
||||
() => {
|
||||
let date = cur_frm.doc.due_date;
|
||||
frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
|
||||
frappe.timeout(0.5);
|
||||
assert.ok(!cur_dialog, 'Message is not shown');
|
||||
},
|
||||
() => cur_frm.save(),
|
||||
() => frappe.tests.click_button('Submit'),
|
||||
() => frappe.tests.click_button('Yes'),
|
||||
() => frappe.timeout(1),
|
||||
|
@ -6,7 +6,7 @@ from __future__ import unicode_literals
|
||||
import unittest
|
||||
import frappe, erpnext
|
||||
import frappe.model
|
||||
from frappe.utils import cint, flt, today, nowdate, getdate, add_days
|
||||
from frappe.utils import cint, flt, today, nowdate, add_days
|
||||
import frappe.defaults
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
|
||||
test_records as pr_test_records
|
||||
@ -27,6 +27,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
unlink_payment_on_cancel_of_invoice(0)
|
||||
|
||||
def test_gl_entries_without_perpetual_inventory(self):
|
||||
frappe.db.set_value("Company", "_Test Company", "round_off_account", "Round Off - _TC")
|
||||
wrapper = frappe.copy_doc(test_records[0])
|
||||
set_perpetual_inventory(0, wrapper.company)
|
||||
self.assertTrue(not cint(erpnext.is_perpetual_inventory_enabled(wrapper.company)))
|
||||
@ -647,39 +648,6 @@ class TestPurchaseInvoice(unittest.TestCase):
|
||||
self.assertEquals(pi.total_taxes_and_charges, 462.3)
|
||||
self.assertEquals(pi.grand_total, 1712.3)
|
||||
|
||||
def test_gl_entry_based_on_payment_schedule(self):
|
||||
pi = make_purchase_invoice(do_not_save=True, supplier="_Test Supplier P")
|
||||
pi.append("payment_schedule", {
|
||||
"due_date": add_days(nowdate(), 15),
|
||||
"payment_amount": 100,
|
||||
"invoice_portion": 40.00
|
||||
})
|
||||
pi.append("payment_schedule", {
|
||||
"due_date": add_days(nowdate(), 25),
|
||||
"payment_amount": 150,
|
||||
"invoice_portion": 60.00
|
||||
})
|
||||
|
||||
pi.save()
|
||||
pi.submit()
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, debit, credit, due_date
|
||||
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
|
||||
order by account asc, debit asc""", pi.name, as_dict=1)
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
expected_gl_entries = sorted([
|
||||
[pi.credit_to, 0.0, 100.0, add_days(nowdate(), 15)],
|
||||
[pi.credit_to, 0.0, 150.0, add_days(nowdate(), 25)],
|
||||
["_Test Account Cost for Goods Sold - _TC", 250.0, 0.0, None]
|
||||
])
|
||||
|
||||
for i, gle in enumerate(sorted(gl_entries, key=lambda gle: gle.account)):
|
||||
self.assertEquals(expected_gl_entries[i][0], gle.account)
|
||||
self.assertEquals(expected_gl_entries[i][1], gle.debit)
|
||||
self.assertEquals(expected_gl_entries[i][2], gle.credit)
|
||||
self.assertEquals(getdate(expected_gl_entries[i][3]), getdate(gle.due_date))
|
||||
|
||||
def test_make_pi_without_terms(self):
|
||||
pi = make_purchase_invoice(do_not_save=1)
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from erpnext.accounts.doctype.sales_taxes_and_charges_template.sales_taxes_and_charges_template \
|
||||
import valdiate_taxes_and_charges_template
|
||||
@ -10,3 +11,8 @@ from erpnext.accounts.doctype.sales_taxes_and_charges_template.sales_taxes_and_c
|
||||
class PurchaseTaxesandChargesTemplate(Document):
|
||||
def validate(self):
|
||||
valdiate_taxes_and_charges_template(self)
|
||||
|
||||
def autoname(self):
|
||||
if self.company and self.title:
|
||||
abbr = frappe.db.get_value('Company', self.company, 'abbr')
|
||||
self.name = '{0} - {1}'.format(self.title, abbr)
|
||||
|
@ -1,7 +1,7 @@
|
||||
QUnit.module('Sales Taxes and Charges Template');
|
||||
|
||||
QUnit.test("test sales taxes and charges template", function(assert) {
|
||||
assert.expect(1);
|
||||
assert.expect(2);
|
||||
let done = assert.async();
|
||||
frappe.run_serially([
|
||||
() => {
|
||||
@ -19,7 +19,10 @@ QUnit.test("test sales taxes and charges template", function(assert) {
|
||||
]}
|
||||
]);
|
||||
},
|
||||
() => {assert.ok(cur_frm.doc.title=='TEST In State GST');},
|
||||
() => {
|
||||
assert.ok(cur_frm.doc.title=='TEST In State GST');
|
||||
assert.ok(cur_frm.doc.name=='TEST In State GST - FT');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
@ -503,7 +503,7 @@
|
||||
"oldfieldname": "due_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@ -2864,7 +2864,7 @@
|
||||
"options": "Payment Schedule",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@ -4563,7 +4563,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2017-11-29 17:36:05.216046",
|
||||
"modified": "2017-12-20 17:36:05.216046",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
@ -143,6 +143,7 @@ class SalesInvoice(SellingController):
|
||||
self.update_time_sheet(self.name)
|
||||
|
||||
self.update_current_month_sales()
|
||||
self.update_project()
|
||||
|
||||
def validate_pos_paid_amount(self):
|
||||
if len(self.payments) == 0 and self.is_pos:
|
||||
@ -181,6 +182,7 @@ class SalesInvoice(SellingController):
|
||||
frappe.db.set(self, 'status', 'Cancelled')
|
||||
|
||||
self.update_current_month_sales()
|
||||
self.update_project()
|
||||
|
||||
def update_current_month_sales(self):
|
||||
if frappe.flags.in_test:
|
||||
@ -635,27 +637,7 @@ class SalesInvoice(SellingController):
|
||||
|
||||
def make_customer_gl_entry(self, gl_entries):
|
||||
grand_total = self.rounded_total or self.grand_total
|
||||
if self.get("payment_schedule"):
|
||||
for d in self.get("payment_schedule"):
|
||||
payment_amount_in_company_currency = flt(d.payment_amount * self.conversion_rate,
|
||||
d.precision("payment_amount"))
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.debit_to,
|
||||
"party_type": "Customer",
|
||||
"party": self.customer,
|
||||
"due_date": d.due_date,
|
||||
"against": self.against_income_account,
|
||||
"debit": payment_amount_in_company_currency,
|
||||
"debit_in_account_currency": payment_amount_in_company_currency \
|
||||
if self.party_account_currency==self.company_currency else d.payment_amount,
|
||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||
"against_voucher_type": self.doctype
|
||||
}, self.party_account_currency)
|
||||
)
|
||||
|
||||
elif grand_total:
|
||||
if grand_total:
|
||||
# Didnot use base_grand_total to book rounding loss gle
|
||||
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
||||
self.precision("grand_total"))
|
||||
@ -912,6 +894,13 @@ class SalesInvoice(SellingController):
|
||||
serial_no, sales_invoice
|
||||
)))
|
||||
|
||||
def update_project(self):
|
||||
if self.project:
|
||||
project = frappe.get_doc("Project", self.project)
|
||||
project.flags.dont_sync_tasks = True
|
||||
project.update_billed_amount()
|
||||
project.save()
|
||||
|
||||
def get_list_context(context=None):
|
||||
from erpnext.controllers.website_list_for_contact import get_list_context
|
||||
list_context = get_list_context(context)
|
||||
|
@ -1,7 +1,7 @@
|
||||
QUnit.module('Sales Invoice');
|
||||
|
||||
QUnit.test("test sales Invoice", function(assert) {
|
||||
assert.expect(6);
|
||||
assert.expect(9);
|
||||
let done = assert.async();
|
||||
frappe.run_serially([
|
||||
() => {
|
||||
@ -17,7 +17,7 @@ QUnit.test("test sales Invoice", function(assert) {
|
||||
{customer_address: 'Test1-Billing'},
|
||||
{shipping_address_name: 'Test1-Shipping'},
|
||||
{contact_person: 'Contact 1-Test Customer 1'},
|
||||
{taxes_and_charges: 'TEST In State GST'},
|
||||
{taxes_and_charges: 'TEST In State GST - FT'},
|
||||
{tc_name: 'Test Term 1'},
|
||||
{terms: 'This is Test'},
|
||||
{payment_terms_template: '_Test Payment Term Template UI'}
|
||||
@ -28,7 +28,7 @@ QUnit.test("test sales Invoice", function(assert) {
|
||||
// get_item_details
|
||||
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
|
||||
// get tax details
|
||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
|
||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
|
||||
// get tax account head details
|
||||
assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
|
||||
// grand_total Calculated
|
||||
@ -38,6 +38,33 @@ QUnit.test("test sales Invoice", function(assert) {
|
||||
assert.ok(cur_frm.doc.payment_schedule.length > 0, "Payment Term Schedule is not empty");
|
||||
|
||||
},
|
||||
() => {
|
||||
let date = cur_frm.doc.due_date;
|
||||
frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
|
||||
frappe.timeout(0.5);
|
||||
assert.ok(cur_dialog && cur_dialog.is_visible, 'Message is displayed to user');
|
||||
},
|
||||
() => frappe.timeout(1),
|
||||
() => frappe.tests.click_button('Close'),
|
||||
() => frappe.timeout(0.5),
|
||||
() => frappe.tests.set_form_values(cur_frm, [{'payment_terms_schedule': ''}]),
|
||||
() => {
|
||||
let date = cur_frm.doc.due_date;
|
||||
frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
|
||||
frappe.timeout(0.5);
|
||||
assert.ok(cur_dialog && cur_dialog.is_visible, 'Message is displayed to user');
|
||||
},
|
||||
() => frappe.timeout(1),
|
||||
() => frappe.tests.click_button('Close'),
|
||||
() => frappe.timeout(0.5),
|
||||
() => frappe.tests.set_form_values(cur_frm, [{'payment_schedule': []}]),
|
||||
() => {
|
||||
let date = cur_frm.doc.due_date;
|
||||
frappe.tests.set_control('due_date', frappe.datetime.add_days(date, 1));
|
||||
frappe.timeout(0.5);
|
||||
assert.ok(!cur_dialog, 'Message is not shown');
|
||||
},
|
||||
() => cur_frm.save(),
|
||||
() => frappe.tests.click_button('Submit'),
|
||||
() => frappe.tests.click_button('Yes'),
|
||||
() => frappe.timeout(0.3),
|
||||
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
import unittest, copy, time
|
||||
from frappe.utils import nowdate, add_days, flt, getdate, cint
|
||||
from frappe.utils import nowdate, flt, getdate, cint
|
||||
from frappe.model.dynamic_links import get_dynamic_link_map
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
|
||||
@ -1322,40 +1322,6 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
si.insert()
|
||||
return si
|
||||
|
||||
def test_gl_entry_based_on_payment_schedule(self):
|
||||
si = create_sales_invoice(do_not_save=True, customer="_Test Customer P")
|
||||
si.append("payment_schedule", {
|
||||
"due_date": add_days(nowdate(), 15),
|
||||
"payment_amount": 20,
|
||||
"invoice_portion": 20.00
|
||||
})
|
||||
si.append("payment_schedule", {
|
||||
"due_date": add_days(nowdate(), 45),
|
||||
"payment_amount": 80,
|
||||
"invoice_portion": 80.00
|
||||
})
|
||||
|
||||
si.save()
|
||||
si.submit()
|
||||
|
||||
gl_entries = frappe.db.sql("""select account, debit, credit, due_date
|
||||
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
|
||||
order by account asc, debit asc""", si.name, as_dict=1)
|
||||
self.assertTrue(gl_entries)
|
||||
|
||||
expected_gl_entries = sorted([
|
||||
[si.debit_to, 20.0, 0.0, add_days(nowdate(), 15)],
|
||||
[si.debit_to, 80.0, 0.0, add_days(nowdate(), 45)],
|
||||
["Sales - _TC", 0.0, 100.0, None]
|
||||
])
|
||||
|
||||
for i, gle in enumerate(sorted(gl_entries, key=lambda gle: gle.account)):
|
||||
self.assertEquals(expected_gl_entries[i][0], gle.account)
|
||||
self.assertEquals(expected_gl_entries[i][1], gle.debit)
|
||||
self.assertEquals(expected_gl_entries[i][2], gle.credit)
|
||||
self.assertEquals(getdate(expected_gl_entries[i][3]), getdate(gle.due_date))
|
||||
|
||||
|
||||
def test_company_monthly_sales(self):
|
||||
existing_current_month_sales = frappe.db.get_value("Company", "_Test Company", "total_monthly_sales")
|
||||
|
||||
|
@ -17,7 +17,7 @@ QUnit.test("test sales Invoice", function(assert) {
|
||||
{customer_address: 'Test1-Billing'},
|
||||
{shipping_address_name: 'Test1-Shipping'},
|
||||
{contact_person: 'Contact 1-Test Customer 1'},
|
||||
{taxes_and_charges: 'TEST In State GST'},
|
||||
{taxes_and_charges: 'TEST In State GST - FT'},
|
||||
{tc_name: 'Test Term 1'},
|
||||
{terms: 'This is Test'}
|
||||
]);
|
||||
@ -27,7 +27,7 @@ QUnit.test("test sales Invoice", function(assert) {
|
||||
// get_item_details
|
||||
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
|
||||
// get tax details
|
||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
|
||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
|
||||
// get tax account head details
|
||||
assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
|
||||
// grand_total Calculated
|
||||
|
@ -17,7 +17,7 @@ QUnit.test("test sales Invoice with payment", function(assert) {
|
||||
{customer_address: 'Test1-Billing'},
|
||||
{shipping_address_name: 'Test1-Shipping'},
|
||||
{contact_person: 'Contact 1-Test Customer 1'},
|
||||
{taxes_and_charges: 'TEST In State GST'},
|
||||
{taxes_and_charges: 'TEST In State GST - FT'},
|
||||
{tc_name: 'Test Term 1'},
|
||||
{terms: 'This is Test'},
|
||||
{payment_terms_template: '_Test Payment Term Template UI'}
|
||||
@ -28,7 +28,7 @@ QUnit.test("test sales Invoice with payment", function(assert) {
|
||||
// get_item_details
|
||||
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
|
||||
// get tax details
|
||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
|
||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
|
||||
// grand_total Calculated
|
||||
assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
|
||||
|
||||
|
@ -17,7 +17,7 @@ QUnit.test("test sales Invoice with payment request", function(assert) {
|
||||
{customer_address: 'Test1-Billing'},
|
||||
{shipping_address_name: 'Test1-Shipping'},
|
||||
{contact_person: 'Contact 1-Test Customer 1'},
|
||||
{taxes_and_charges: 'TEST In State GST'},
|
||||
{taxes_and_charges: 'TEST In State GST - FT'},
|
||||
{tc_name: 'Test Term 1'},
|
||||
{terms: 'This is Test'}
|
||||
]);
|
||||
@ -27,7 +27,7 @@ QUnit.test("test sales Invoice with payment request", function(assert) {
|
||||
// get_item_details
|
||||
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 1', "Item name correct");
|
||||
// get tax details
|
||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
|
||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
|
||||
// grand_total Calculated
|
||||
assert.ok(cur_frm.doc.grand_total==590, "Grad Total correct");
|
||||
|
||||
|
@ -17,7 +17,7 @@ QUnit.test("test sales Invoice with serialize item", function(assert) {
|
||||
{customer_address: 'Test1-Billing'},
|
||||
{shipping_address_name: 'Test1-Shipping'},
|
||||
{contact_person: 'Contact 1-Test Customer 1'},
|
||||
{taxes_and_charges: 'TEST In State GST'},
|
||||
{taxes_and_charges: 'TEST In State GST - FT'},
|
||||
{tc_name: 'Test Term 1'},
|
||||
{terms: 'This is Test'}
|
||||
]);
|
||||
@ -27,7 +27,7 @@ QUnit.test("test sales Invoice with serialize item", function(assert) {
|
||||
// get_item_details
|
||||
assert.ok(cur_frm.doc.items[0].item_name=='Test Product 4', "Item name correct");
|
||||
// get tax details
|
||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST', "Tax details correct");
|
||||
assert.ok(cur_frm.doc.taxes_and_charges=='TEST In State GST - FT', "Tax details correct");
|
||||
// get tax account head details
|
||||
assert.ok(cur_frm.doc.taxes[0].account_head=='CGST - '+frappe.get_abbr(frappe.defaults.get_default('Company')), " Account Head abbr correct");
|
||||
// get batch number
|
||||
|
@ -12,6 +12,11 @@ class SalesTaxesandChargesTemplate(Document):
|
||||
def validate(self):
|
||||
valdiate_taxes_and_charges_template(self)
|
||||
|
||||
def autoname(self):
|
||||
if self.company and self.title:
|
||||
abbr = frappe.db.get_value('Company', self.company, 'abbr')
|
||||
self.name = '{0} - {1}'.format(self.title, abbr)
|
||||
|
||||
def set_missing_values(self):
|
||||
for data in self.taxes:
|
||||
if data.charge_type == 'On Net Total' and flt(data.rate) == 0.0:
|
||||
|
@ -1,7 +1,7 @@
|
||||
QUnit.module('Sales Taxes and Charges Template');
|
||||
|
||||
QUnit.test("test sales taxes and charges template", function(assert) {
|
||||
assert.expect(1);
|
||||
assert.expect(2);
|
||||
let done = assert.async();
|
||||
frappe.run_serially([
|
||||
() => {
|
||||
@ -19,7 +19,10 @@ QUnit.test("test sales taxes and charges template", function(assert) {
|
||||
]}
|
||||
]);
|
||||
},
|
||||
() => {assert.ok(cur_frm.doc.title=='TEST In State GST');},
|
||||
() => {
|
||||
assert.ok(cur_frm.doc.title=='TEST In State GST');
|
||||
assert.ok(cur_frm.doc.name=='TEST In State GST - FT');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"doctype": "Tax Rule",
|
||||
"tax_type" : "Sales",
|
||||
"sales_tax_template": "_Test Tax 1",
|
||||
"sales_tax_template": "_Test Tax 1 - _TC",
|
||||
"use_for_shopping_cart": 1,
|
||||
"billing_city": "_Test City",
|
||||
"billing_state": "Test State",
|
||||
@ -15,7 +15,7 @@
|
||||
{
|
||||
"doctype": "Tax Rule",
|
||||
"tax_type" : "Sales",
|
||||
"sales_tax_template": "_Test Tax 2",
|
||||
"sales_tax_template": "_Test Tax 2 - _TC",
|
||||
"use_for_shopping_cart": 0,
|
||||
"billing_city": "_Test City",
|
||||
"billing_country": "India",
|
||||
|
@ -18,40 +18,40 @@ class TestTaxRule(unittest.TestCase):
|
||||
|
||||
def test_conflict(self):
|
||||
tax_rule1 = make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1)
|
||||
tax_rule1.save()
|
||||
|
||||
tax_rule2 = make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1)
|
||||
|
||||
self.assertRaises(ConflictingTaxRule, tax_rule2.save)
|
||||
|
||||
def test_conflict_with_non_overlapping_dates(self):
|
||||
tax_rule1 = make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01")
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1, from_date = "2015-01-01")
|
||||
tax_rule1.save()
|
||||
|
||||
tax_rule2 = make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, to_date = "2013-01-01")
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1, to_date = "2013-01-01")
|
||||
|
||||
tax_rule2.save()
|
||||
self.assertTrue(tax_rule2.name)
|
||||
|
||||
def test_for_parent_customer_group(self):
|
||||
tax_rule1 = make_tax_rule(customer_group= "All Customer Groups",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01")
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1, from_date = "2015-01-01")
|
||||
tax_rule1.save()
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer_group" : "Commercial", "use_for_shopping_cart":0}),
|
||||
"_Test Sales Taxes and Charges Template")
|
||||
"_Test Sales Taxes and Charges Template - _TC")
|
||||
|
||||
def test_conflict_with_overlapping_dates(self):
|
||||
tax_rule1 = make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01", to_date = "2015-01-05")
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1, from_date = "2015-01-01", to_date = "2015-01-05")
|
||||
tax_rule1.save()
|
||||
|
||||
tax_rule2 = make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-03", to_date = "2015-01-09")
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority = 1, from_date = "2015-01-03", to_date = "2015-01-09")
|
||||
|
||||
self.assertRaises(ConflictingTaxRule, tax_rule2.save)
|
||||
|
||||
@ -62,66 +62,66 @@ class TestTaxRule(unittest.TestCase):
|
||||
|
||||
def test_select_tax_rule_based_on_customer(self):
|
||||
make_tax_rule(customer= "_Test Customer",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)
|
||||
|
||||
make_tax_rule(customer= "_Test Customer 1",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1 - _TC", save=1)
|
||||
|
||||
make_tax_rule(customer= "_Test Customer 2",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 2", save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 2 - _TC", save=1)
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer 2"}),
|
||||
"_Test Sales Taxes and Charges Template 2")
|
||||
"_Test Sales Taxes and Charges Template 2 - _TC")
|
||||
|
||||
def test_select_tax_rule_based_on_better_match(self):
|
||||
make_tax_rule(customer= "_Test Customer", billing_city = "Test City", billing_state = "Test State",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)
|
||||
|
||||
make_tax_rule(customer= "_Test Customer", billing_city = "Test City1", billing_state = "Test State",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1 - _TC", save=1)
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City", "billing_state": "Test State"}),
|
||||
"_Test Sales Taxes and Charges Template")
|
||||
"_Test Sales Taxes and Charges Template - _TC")
|
||||
|
||||
def test_select_tax_rule_based_on_state_match(self):
|
||||
make_tax_rule(customer= "_Test Customer", shipping_state = "Test State",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)
|
||||
|
||||
make_tax_rule(customer= "_Test Customer", shipping_state = "Test State12",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1 - _TC", priority=2, save=1)
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "shipping_state": "Test State"}),
|
||||
"_Test Sales Taxes and Charges Template")
|
||||
"_Test Sales Taxes and Charges Template - _TC")
|
||||
|
||||
def test_select_tax_rule_based_on_better_priority(self):
|
||||
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", priority=1, save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", priority=1, save=1)
|
||||
|
||||
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1 - _TC", priority=2, save=1)
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City"}),
|
||||
"_Test Sales Taxes and Charges Template 1")
|
||||
"_Test Sales Taxes and Charges Template 1 - _TC")
|
||||
|
||||
def test_select_tax_rule_based_cross_matching_keys(self):
|
||||
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)
|
||||
|
||||
make_tax_rule(customer= "_Test Customer 1", billing_city = "Test City 1",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1 - _TC", save=1)
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
|
||||
None)
|
||||
|
||||
def test_select_tax_rule_based_cross_partially_keys(self):
|
||||
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template - _TC", save=1)
|
||||
|
||||
make_tax_rule(billing_city = "Test City 1",
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
|
||||
sales_tax_template = "_Test Sales Taxes and Charges Template 1 - _TC", save=1)
|
||||
|
||||
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
|
||||
"_Test Sales Taxes and Charges Template 1")
|
||||
"_Test Sales Taxes and Charges Template 1 - _TC")
|
||||
|
||||
|
||||
def make_tax_rule(**args):
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
from frappe.utils import flt, cstr, cint, getdate
|
||||
from frappe.utils import flt, cstr, cint
|
||||
from frappe import _
|
||||
from frappe.model.meta import get_field_precision
|
||||
from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
|
||||
@ -75,8 +75,7 @@ def check_if_in_list(gle, gl_map):
|
||||
and cstr(e.get('against_voucher'))==cstr(gle.get('against_voucher')) \
|
||||
and cstr(e.get('against_voucher_type')) == cstr(gle.get('against_voucher_type')) \
|
||||
and cstr(e.get('cost_center')) == cstr(gle.get('cost_center')) \
|
||||
and cstr(e.get('project')) == cstr(gle.get('project')) \
|
||||
and getdate(e.get('due_date')) == getdate(gle.get('due_date')):
|
||||
and cstr(e.get('project')) == cstr(gle.get('project')):
|
||||
return e
|
||||
|
||||
def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False):
|
||||
|
@ -2,15 +2,15 @@
|
||||
"align_labels_right": 0,
|
||||
"creation": "2017-08-08 12:33:04.773099",
|
||||
"custom_format": 1,
|
||||
"disabled": 0,
|
||||
"disabled": 1,
|
||||
"doc_type": "Sales Invoice",
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Format",
|
||||
"font": "Default",
|
||||
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t<b>{{ _(\"GSTIN\") }}:</b>{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"<br>GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t<br>\n\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t<b>{{ _(\"Customer\") }}:</b><br>\n\t\t{{ doc.customer_name }}<br>\n\t\t{{ customer_address }}\n\t{% endif %}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"40%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t<br><b>{{ _(\"HSN/SAC\") }}:</b> {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"Serial No\") }}:</b> {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.rate }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ _(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"net_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t{%- if not row.included_in_print_rate -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n<p><b>Tax Breakup:</b></p>\n<div style=\"font-size: 8px\">\n\t{{ doc.other_charges_calculation }}\n</div>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
|
||||
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t<b>{{ _(\"GSTIN\") }}:</b>{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"<br>GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t<br>\n\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t<b>{{ _(\"Customer\") }}:</b><br>\n\t\t{{ doc.customer_name }}<br>\n\t\t{{ customer_address }}\n\t{% endif %}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"40%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t<br><b>{{ _(\"HSN/SAC\") }}:</b> {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"Serial No\") }}:</b> {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.rate }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t {%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n<p><b>Tax Breakup:</b></p>\n<div style=\"font-size: 8px\">\n\t{{ doc.other_charges_calculation }}\n</div>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
|
||||
"idx": 0,
|
||||
"line_breaks": 0,
|
||||
"modified": "2017-09-14 15:54:19.467642",
|
||||
"modified": "2018-01-05 17:25:59.181985",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "GST POS Invoice",
|
||||
|
@ -1,15 +1,21 @@
|
||||
{
|
||||
"align_labels_right": 0,
|
||||
"creation": "2011-12-21 11:08:55",
|
||||
"custom_format": 1,
|
||||
"disabled": 0,
|
||||
"doc_type": "Sales Invoice",
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Format",
|
||||
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.get_formatted(\"rate\") }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ _(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"net_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t{%- if not row.included_in_print_rate -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n{% if doc.get(\"taxes\", filters={\"included_in_print_rate\": 1}) %}\n<hr>\n<p><b>Taxes Included:</b></p>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t{%- for row in doc.taxes -%}\n\t\t{%- if row.included_in_print_rate -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ row.get_formatted(\"tax_amount_after_discount_amount\", doc) }}\n\t\t\t</td>\n\t\t<tr>\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n{%- endif -%}\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
|
||||
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.get_formatted(\"rate\") }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t {%- endif -%}\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
|
||||
"idx": 1,
|
||||
"modified": "2015-04-21 05:06:29.380856",
|
||||
"line_breaks": 0,
|
||||
"modified": "2018-01-05 17:23:40.403289",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Invoice",
|
||||
"owner": "Administrator",
|
||||
"print_format_builder": 0,
|
||||
"print_format_type": "Server",
|
||||
"show_section_headings": 0,
|
||||
"standard": "Yes"
|
||||
}
|
@ -113,7 +113,7 @@ class ReceivablePayableReport(object):
|
||||
row += [self.get_party_name(gle.party_type, gle.party)]
|
||||
|
||||
# get due date
|
||||
due_date = gle.due_date or voucher_details.get(gle.voucher_no, {}).get("due_date", "")
|
||||
due_date = voucher_details.get(gle.voucher_no, {}).get("due_date", "")
|
||||
|
||||
row += [gle.voucher_type, gle.voucher_no, due_date]
|
||||
|
||||
@ -188,8 +188,7 @@ class ReceivablePayableReport(object):
|
||||
reverse_dr_or_cr = "credit" if dr_or_cr=="debit" else "debit"
|
||||
|
||||
for e in self.get_gl_entries_for(gle.party, gle.party_type, gle.voucher_type, gle.voucher_no):
|
||||
if getdate(e.posting_date) <= report_date and e.name!=gle.name \
|
||||
and (not gle.due_date or getdate(e.due_date) == getdate(gle.due_date)):
|
||||
if getdate(e.posting_date) <= report_date and e.name!=gle.name:
|
||||
amount = flt(e.get(reverse_dr_or_cr)) - flt(e.get(dr_or_cr))
|
||||
if e.voucher_no not in return_entries:
|
||||
payment_amount += amount
|
||||
@ -251,11 +250,11 @@ class ReceivablePayableReport(object):
|
||||
select_fields = "sum(debit) as debit, sum(credit) as credit"
|
||||
|
||||
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party,
|
||||
voucher_type, voucher_no, against_voucher_type, against_voucher, due_date,
|
||||
voucher_type, voucher_no, against_voucher_type, against_voucher,
|
||||
account_currency, remarks, {0}
|
||||
from `tabGL Entry`
|
||||
where docstatus < 2 and party_type=%s and (party is not null and party != '') {1}
|
||||
group by voucher_type, voucher_no, against_voucher_type, against_voucher, party, due_date
|
||||
group by voucher_type, voucher_no, against_voucher_type, against_voucher, party
|
||||
order by posting_date, party"""
|
||||
.format(select_fields, conditions), values, as_dict=True)
|
||||
|
||||
|
@ -193,6 +193,24 @@ def get_data_with_opening_closing(filters, account_details, gl_entries):
|
||||
# closing
|
||||
data.append(totals.closing)
|
||||
|
||||
#total closing
|
||||
total_closing = totals.total_closing
|
||||
total_debit = totals.closing.get('debit', 0)
|
||||
total_credit = totals.closing.get('credit', 0)
|
||||
debit_in_account_currency = totals.closing.get('debit_in_account_currency', 0)
|
||||
credit_in_account_currency = totals.closing.get('credit_in_account_currency', 0)
|
||||
|
||||
total_amount = total_debit - total_credit
|
||||
|
||||
if total_amount > 0:
|
||||
total_closing['debit'] = total_amount
|
||||
total_closing['debit_in_account_currency'] = debit_in_account_currency - credit_in_account_currency
|
||||
else:
|
||||
total_closing['credit'] = abs(total_amount)
|
||||
total_closing['credit_in_account_currency'] = abs(debit_in_account_currency - credit_in_account_currency)
|
||||
|
||||
data.append(totals.total_closing)
|
||||
|
||||
return data
|
||||
|
||||
def get_totals_dict():
|
||||
@ -207,7 +225,8 @@ def get_totals_dict():
|
||||
return _dict(
|
||||
opening = _get_debit_credit_dict(_('Opening')),
|
||||
total = _get_debit_credit_dict(_('Total')),
|
||||
closing = _get_debit_credit_dict(_('Closing (Opening + Total)'))
|
||||
closing = _get_debit_credit_dict(_('Closing (Opening + Total)')),
|
||||
total_closing = _get_debit_credit_dict(_('Closing Balance (Dr - Cr)'))
|
||||
)
|
||||
|
||||
def initialize_gle_map(gl_entries):
|
||||
@ -234,6 +253,9 @@ def get_accountwise_gle(filters, gl_entries, gle_map):
|
||||
update_value_in_dict(gle_map[gle.account].totals, 'opening', gle)
|
||||
update_value_in_dict(totals, 'opening', gle)
|
||||
|
||||
update_value_in_dict(gle_map[gle.account].totals, 'closing', gle)
|
||||
update_value_in_dict(totals, 'closing', gle)
|
||||
|
||||
elif gle.posting_date <= to_date:
|
||||
update_value_in_dict(gle_map[gle.account].totals, 'total', gle)
|
||||
update_value_in_dict(totals, 'total', gle)
|
||||
@ -242,8 +264,8 @@ def get_accountwise_gle(filters, gl_entries, gle_map):
|
||||
else:
|
||||
entries.append(gle)
|
||||
|
||||
update_value_in_dict(gle_map[gle.account].totals, 'closing', gle)
|
||||
update_value_in_dict(totals, 'closing', gle)
|
||||
update_value_in_dict(gle_map[gle.account].totals, 'closing', gle)
|
||||
update_value_in_dict(totals, 'closing', gle)
|
||||
|
||||
return totals, entries
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.query_reports["Item-wise Sales Register"] = frappe.query_reports["Sales Register"] = {
|
||||
frappe.query_reports["Item-wise Sales Register"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname":"from_date",
|
||||
|
@ -6,6 +6,7 @@ import frappe, erpnext
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
from frappe.model.meta import get_field_precision
|
||||
from frappe.utils.xlsxutils import handle_html
|
||||
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
|
||||
|
||||
def execute(filters=None):
|
||||
@ -188,10 +189,10 @@ def get_tax_accounts(item_list, columns, company_currency,
|
||||
tuple([doctype] + invoice_item_row.keys()))
|
||||
|
||||
for parent, description, item_wise_tax_detail, charge_type, tax_amount in tax_details:
|
||||
description = handle_html(description)
|
||||
if description not in tax_columns and tax_amount:
|
||||
# as description is text editor earlier and markup can break the column convention in reports
|
||||
from frappe.utils.xlsxutils import handle_html
|
||||
tax_columns.append(handle_html(description))
|
||||
tax_columns.append(description)
|
||||
|
||||
if item_wise_tax_detail:
|
||||
try:
|
||||
|
@ -15,7 +15,7 @@ def execute(filters=None):
|
||||
def get_column():
|
||||
return [
|
||||
_("Purchase Receipt") + ":Link/Purchase Receipt:120", _("Date") + ":Date:100",
|
||||
_("Suplier") + ":Link/Supplier:120", _("Suplier Name") + "::120",
|
||||
_("Supplier") + ":Link/Supplier:120", _("Supplier Name") + "::120",
|
||||
_("Project") + ":Link/Project:120", _("Item Code") + ":Link/Item:120",
|
||||
_("Amount") + ":Currency:100", _("Billed Amount") + ":Currency:100", _("Amount to Bill") + ":Currency:100",
|
||||
_("Item Name") + "::120", _("Description") + "::120", _("Company") + ":Link/Company:120",
|
||||
|
@ -12,7 +12,7 @@
|
||||
"module": "Accounts",
|
||||
"name": "Sales Partners Commission",
|
||||
"owner": "Administrator",
|
||||
"query": "SELECT\n sales_partner as \"Sales Partner:Link/Sales Partner:150\",\n\tsum(base_net_total) as \"Invoiced Amount (Exculsive Tax):Currency:210\",\n\tsum(total_commission) as \"Total Commission:Currency:150\",\n\tsum(total_commission)*100/sum(base_net_total) as \"Average Commission Rate:Currency:170\"\nFROM\n\t`tabSales Invoice`\nWHERE\n\tdocstatus = 1 and ifnull(base_net_total, 0) > 0 and ifnull(total_commission, 0) > 0\nGROUP BY\n\tsales_partner\nORDER BY\n\t\"Total Commission:Currency:120\"",
|
||||
"query": "SELECT\n sales_partner as \"Sales Partner:Link/Sales Partner:150\",\n\tsum(base_net_total) as \"Invoiced Amount (Exclusive Tax):Currency:210\",\n\tsum(total_commission) as \"Total Commission:Currency:150\",\n\tsum(total_commission)*100/sum(base_net_total) as \"Average Commission Rate:Currency:170\"\nFROM\n\t`tabSales Invoice`\nWHERE\n\tdocstatus = 1 and ifnull(base_net_total, 0) > 0 and ifnull(total_commission, 0) > 0\nGROUP BY\n\tsales_partner\nORDER BY\n\t\"Total Commission:Currency:120\"",
|
||||
"ref_doctype": "Sales Invoice",
|
||||
"report_name": "Sales Partners Commission",
|
||||
"report_type": "Query Report",
|
||||
|
@ -1,6 +1,5 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.query_reports["Sales Payment Summary"] = {
|
||||
"filters": [
|
||||
{
|
||||
@ -8,12 +7,14 @@ frappe.query_reports["Sales Payment Summary"] = {
|
||||
"label": __("From Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today(),
|
||||
"reqd": 1,
|
||||
"width": "80"
|
||||
},
|
||||
{
|
||||
"fieldname":"to_date",
|
||||
"label": __("To Date"),
|
||||
"fieldtype": "Date",
|
||||
"reqd": 1,
|
||||
"default": frappe.datetime.get_today()
|
||||
},
|
||||
{
|
||||
@ -23,12 +24,6 @@ frappe.query_reports["Sales Payment Summary"] = {
|
||||
"options": "Company",
|
||||
"default": frappe.defaults.get_user_default("Company")
|
||||
},
|
||||
{
|
||||
"fieldname":"mode_of_payment",
|
||||
"label": __("Mode of Payment"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Mode of Payment"
|
||||
},
|
||||
{
|
||||
"fieldname":"owner",
|
||||
"label": __("Owner"),
|
||||
@ -36,22 +31,15 @@ frappe.query_reports["Sales Payment Summary"] = {
|
||||
"options": "User",
|
||||
"defaults": user
|
||||
},
|
||||
{
|
||||
"fieldname":"cost_center",
|
||||
"label": __("Cost Center"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Cost Center"
|
||||
},
|
||||
{
|
||||
"fieldname":"warehouse",
|
||||
"label": __("Warehouse"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Warehouse"
|
||||
},
|
||||
{
|
||||
"fieldname":"is_pos",
|
||||
"label": __("POS?"),
|
||||
"label": __("Show only POS"),
|
||||
"fieldtype": "Check"
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname":"payment_detail",
|
||||
"label": __("Show Payment Details"),
|
||||
"fieldtype": "Check"
|
||||
},
|
||||
]
|
||||
};
|
@ -1,9 +1,9 @@
|
||||
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import cstr
|
||||
|
||||
def execute(filters=None):
|
||||
columns, data = [], []
|
||||
@ -14,53 +14,133 @@ def execute(filters=None):
|
||||
def get_columns():
|
||||
return [
|
||||
_("Date") + ":Date:80",
|
||||
_("Owner") + "::150",
|
||||
_("Payment Mode") + "::120",
|
||||
_("Warehouse") + ":Link/Cost Center:100",
|
||||
_("Cost Center") + ":Link/Warehouse:100",
|
||||
_("Owner") + ":Data:200",
|
||||
_("Payment Mode") + ":Data:240",
|
||||
_("Sales and Returns") + ":Currency/currency:120",
|
||||
_("Taxes") + ":Currency/currency:120",
|
||||
_("Payments") + ":Currency/currency:120",
|
||||
_("Reconciliation") + ":Currency/currency:120"
|
||||
_("Payments") + ":Currency/currency:120"
|
||||
]
|
||||
|
||||
def get_sales_payment_data(filters, columns):
|
||||
sales_invoice_data = get_sales_invoice_data(filters)
|
||||
data = []
|
||||
show_payment_detail = False
|
||||
|
||||
sales_invoice_data = get_sales_invoice_data(filters)
|
||||
mode_of_payments = get_mode_of_payments(filters)
|
||||
mode_of_payment_details = get_mode_of_payment_details(filters)
|
||||
|
||||
if filters.get("payment_detail"):
|
||||
show_payment_detail = True
|
||||
else:
|
||||
show_payment_detail = False
|
||||
|
||||
for inv in sales_invoice_data:
|
||||
row = [inv.posting_date, inv.owner, inv.mode_of_payment,inv.warehouse,
|
||||
inv.cost_center,inv.net_total, inv.total_taxes, inv.paid_amount,
|
||||
(inv.net_total + inv.total_taxes - inv.paid_amount)]
|
||||
data.append(row)
|
||||
owner_posting_date = inv["owner"]+cstr(inv["posting_date"])
|
||||
if show_payment_detail:
|
||||
row = [inv.posting_date, inv.owner," ",inv.net_total,inv.total_taxes, 0]
|
||||
data.append(row)
|
||||
for mop_detail in mode_of_payment_details.get(owner_posting_date,[]):
|
||||
row = [inv.posting_date, inv.owner,mop_detail[0],0,0,mop_detail[1],0]
|
||||
data.append(row)
|
||||
else:
|
||||
total_payment = 0
|
||||
for mop_detail in mode_of_payment_details.get(owner_posting_date,[]):
|
||||
total_payment = total_payment + mop_detail[1]
|
||||
row = [inv.posting_date, inv.owner,", ".join(mode_of_payments.get(owner_posting_date, [])),
|
||||
inv.net_total,inv.total_taxes,total_payment]
|
||||
data.append(row)
|
||||
return data
|
||||
|
||||
def get_conditions(filters):
|
||||
conditions = ""
|
||||
if filters.get("company"): conditions += " a.company=%(company)s"
|
||||
if filters.get("from_date"): conditions += "a.posting_date >= %(from_date)s"
|
||||
if filters.get("to_date"): conditions += " and a.posting_date <= %(to_date)s"
|
||||
if filters.get("company"): conditions += " and a.company=%(company)s"
|
||||
if filters.get("customer"): conditions += " and a.customer = %(customer)s"
|
||||
if filters.get("owner"): conditions += " and a.owner = %(owner)s"
|
||||
if filters.get("from_date"): conditions += " and a.posting_date >= %(from_date)s"
|
||||
if filters.get("to_date"): conditions += " and a.posting_date <= %(to_date)s"
|
||||
if filters.get("mode_of_payment"): conditions += " and c.mode_of_payment >= %(mode_of_payment)s"
|
||||
if filters.get("warehouse"): conditions += " and b.warehouse <= %(warehouse)s"
|
||||
if filters.get("cost_center"): conditions += " and b.cost_center <= %(cost_center)s"
|
||||
if filters.get("is_pos"): conditions += " and a.is_pos = %(is_pos)s"
|
||||
|
||||
return conditions
|
||||
|
||||
def get_sales_invoice_data(filters):
|
||||
conditions = get_conditions(filters)
|
||||
return frappe.db.sql("""
|
||||
select
|
||||
a.owner, a.posting_date, c.mode_of_payment, b.warehouse, b.cost_center,
|
||||
a.posting_date, a.owner,
|
||||
sum(a.net_total) as "net_total",
|
||||
sum(a.total_taxes_and_charges) as "total_taxes",
|
||||
sum(a.base_paid_amount) as "paid_amount"
|
||||
from `tabSales Invoice` a, `tabSales Invoice Item` b, `tabSales Invoice Payment` c
|
||||
where
|
||||
a.name = b.parent
|
||||
and a.name = c.parent
|
||||
sum(a.base_paid_amount) as "paid_amount",
|
||||
sum(a.outstanding_amount) as "outstanding_amount"
|
||||
from `tabSales Invoice` a
|
||||
where a.docstatus = 1
|
||||
and {conditions}
|
||||
group by
|
||||
a.owner, a.posting_date, c.mode_of_payment, b.warehouse, b.cost_center
|
||||
a.owner, a.posting_date
|
||||
""".format(conditions=conditions), filters, as_dict=1)
|
||||
|
||||
def get_mode_of_payments(filters):
|
||||
mode_of_payments = {}
|
||||
invoice_list = get_invoices(filters)
|
||||
invoice_list_names = ",".join(['"' + invoice['name'] + '"' for invoice in invoice_list])
|
||||
if invoice_list:
|
||||
inv_mop = frappe.db.sql("""select a.owner,a.posting_date, ifnull(b.mode_of_payment, '') as mode_of_payment
|
||||
from `tabSales Invoice` a, `tabSales Invoice Payment` b
|
||||
where a.name = b.parent
|
||||
and a.name in ({invoice_list_names})
|
||||
union
|
||||
select a.owner,a.posting_date, ifnull(b.mode_of_payment, '') as mode_of_payment
|
||||
from `tabSales Invoice` a, `tabPayment Entry` b,`tabPayment Entry Reference` c
|
||||
where a.name = c.reference_name
|
||||
and b.name = c.parent
|
||||
and a.name in ({invoice_list_names})
|
||||
union
|
||||
select a.owner, a.posting_date,
|
||||
ifnull(a.voucher_type,'') as mode_of_payment
|
||||
from `tabJournal Entry` a, `tabJournal Entry Account` b
|
||||
where a.name = b.parent
|
||||
and a.docstatus = 1
|
||||
and b.reference_type = "Sales Invoice"
|
||||
and b.reference_name in ({invoice_list_names})
|
||||
""".format(invoice_list_names=invoice_list_names), as_dict=1)
|
||||
for d in inv_mop:
|
||||
mode_of_payments.setdefault(d["owner"]+cstr(d["posting_date"]), []).append(d.mode_of_payment)
|
||||
return mode_of_payments
|
||||
|
||||
def get_invoices(filters):
|
||||
conditions = get_conditions(filters)
|
||||
return frappe.db.sql("""select a.name
|
||||
from `tabSales Invoice` a
|
||||
where a.docstatus = 1 and {conditions}""".format(conditions=conditions),
|
||||
filters, as_dict=1)
|
||||
|
||||
def get_mode_of_payment_details(filters):
|
||||
mode_of_payment_details = {}
|
||||
invoice_list = get_invoices(filters)
|
||||
invoice_list_names = ",".join(['"' + invoice['name'] + '"' for invoice in invoice_list])
|
||||
if invoice_list:
|
||||
inv_mop_detail = frappe.db.sql("""select a.owner, a.posting_date,
|
||||
ifnull(b.mode_of_payment, '') as mode_of_payment, sum(b.base_amount) as paid_amount
|
||||
from `tabSales Invoice` a, `tabSales Invoice Payment` b
|
||||
where a.name = b.parent
|
||||
and a.name in ({invoice_list_names})
|
||||
group by a.owner, a.posting_date, mode_of_payment
|
||||
union
|
||||
select a.owner,a.posting_date,
|
||||
ifnull(b.mode_of_payment, '') as mode_of_payment, sum(b.base_paid_amount) as paid_amount
|
||||
from `tabSales Invoice` a, `tabPayment Entry` b,`tabPayment Entry Reference` c
|
||||
where a.name = c.reference_name
|
||||
and b.name = c.parent
|
||||
and a.name in ({invoice_list_names})
|
||||
group by a.owner, a.posting_date, mode_of_payment
|
||||
union
|
||||
select a.owner, a.posting_date,
|
||||
ifnull(a.voucher_type,'') as mode_of_payment, sum(b.credit)
|
||||
from `tabJournal Entry` a, `tabJournal Entry Account` b
|
||||
where a.name = b.parent
|
||||
and a.docstatus = 1
|
||||
and b.reference_type = "Sales Invoice"
|
||||
and b.reference_name in ({invoice_list_names})
|
||||
group by a.owner, a.posting_date, mode_of_payment
|
||||
""".format(invoice_list_names=invoice_list_names), as_dict=1)
|
||||
for d in inv_mop_detail:
|
||||
mode_of_payment_details.setdefault(d["owner"]+cstr(d["posting_date"]), []).append((d.mode_of_payment,d.paid_amount))
|
||||
return mode_of_payment_details
|
@ -252,6 +252,9 @@ def add_ac(args=None):
|
||||
if not ac.parent_account:
|
||||
ac.parent_account = args.get("parent")
|
||||
|
||||
if ac.is_root:
|
||||
ac.parent_account=''
|
||||
|
||||
ac.old_parent = ""
|
||||
ac.freeze_account = "No"
|
||||
if cint(ac.get("is_root")):
|
||||
@ -576,16 +579,17 @@ def get_outstanding_invoices(party_type, party, account, condition=None):
|
||||
outstanding_invoices = []
|
||||
precision = frappe.get_precision("Sales Invoice", "outstanding_amount")
|
||||
|
||||
if party_type == "Customer" or party_type == "Student":
|
||||
if party_type in ("Customer", "Student"):
|
||||
dr_or_cr = "debit_in_account_currency - credit_in_account_currency"
|
||||
payment_dr_or_cr = "payment_gl_entry.credit_in_account_currency - payment_gl_entry.debit_in_account_currency"
|
||||
else:
|
||||
dr_or_cr = "credit_in_account_currency - debit_in_account_currency"
|
||||
payment_dr_or_cr = "payment_gl_entry.debit_in_account_currency - payment_gl_entry.credit_in_account_currency"
|
||||
|
||||
invoice = 'Sales Invoice' if party_type == 'Customer' else 'Purchase Invoice'
|
||||
invoice_list = frappe.db.sql("""
|
||||
select
|
||||
voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount, due_date,
|
||||
voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount,
|
||||
(
|
||||
select ifnull(sum({payment_dr_or_cr}), 0)
|
||||
from `tabGL Entry` payment_gl_entry
|
||||
@ -596,7 +600,6 @@ def get_outstanding_invoices(party_type, party, account, condition=None):
|
||||
and payment_gl_entry.party_type = invoice_gl_entry.party_type
|
||||
and payment_gl_entry.party = invoice_gl_entry.party
|
||||
and payment_gl_entry.account = invoice_gl_entry.account
|
||||
and payment_gl_entry.due_date = invoice_gl_entry.due_date
|
||||
and {payment_dr_or_cr} > 0
|
||||
) as payment_amount
|
||||
from
|
||||
@ -608,10 +611,11 @@ def get_outstanding_invoices(party_type, party, account, condition=None):
|
||||
and ((voucher_type = 'Journal Entry'
|
||||
and (against_voucher = '' or against_voucher is null))
|
||||
or (voucher_type not in ('Journal Entry', 'Payment Entry')))
|
||||
group by voucher_type, voucher_no, due_date
|
||||
group by voucher_type, voucher_no
|
||||
having (invoice_amount - payment_amount) > 0.005
|
||||
order by posting_date, name, due_date""".format(
|
||||
order by posting_date, name""".format(
|
||||
dr_or_cr=dr_or_cr,
|
||||
invoice = invoice,
|
||||
payment_dr_or_cr=payment_dr_or_cr,
|
||||
condition=condition or ""
|
||||
), {
|
||||
@ -621,12 +625,8 @@ def get_outstanding_invoices(party_type, party, account, condition=None):
|
||||
}, as_dict=True)
|
||||
|
||||
for d in invoice_list:
|
||||
due_date = d.due_date or (
|
||||
frappe.db.get_value(
|
||||
d.voucher_type, d.voucher_no,
|
||||
"posting_date" if party_type == "Employee" else "due_date"
|
||||
)
|
||||
)
|
||||
due_date = frappe.db.get_value(d.voucher_type, d.voucher_no,
|
||||
"posting_date" if party_type == "Employee" else "due_date")
|
||||
|
||||
outstanding_invoices.append(
|
||||
frappe._dict({
|
||||
@ -704,7 +704,7 @@ def get_children(doctype, parent, company, is_root=False):
|
||||
return acc
|
||||
|
||||
def create_payment_gateway_account(gateway):
|
||||
from erpnext.setup.setup_wizard.setup_wizard import create_bank_account
|
||||
from erpnext.setup.setup_wizard.operations.company_setup import create_bank_account
|
||||
|
||||
company = frappe.db.get_value("Global Defaults", None, "default_company")
|
||||
if not company:
|
||||
|
@ -1,7 +1,55 @@
|
||||
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.provide("erpnext.crop");
|
||||
|
||||
frappe.ui.form.on('Crop', {
|
||||
validate: (frm) => {
|
||||
refresh: (frm) => {
|
||||
frm.fields_dict.materials_required.grid.set_column_disp('bom_no', false);
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on("BOM Item", {
|
||||
item_code: (frm, cdt, cdn) => {
|
||||
erpnext.crop.update_item_rate_uom(frm, cdt, cdn);
|
||||
},
|
||||
qty: (frm, cdt, cdn) => {
|
||||
erpnext.crop.update_item_qty_amount(frm, cdt, cdn);
|
||||
},
|
||||
rate: (frm, cdt, cdn) => {
|
||||
erpnext.crop.update_item_qty_amount(frm, cdt, cdn);
|
||||
}
|
||||
});
|
||||
|
||||
erpnext.crop.update_item_rate_uom = function(frm, cdt, cdn) {
|
||||
let material_list = ['materials_required', 'produce', 'byproducts'];
|
||||
material_list.forEach((material) => {
|
||||
frm.doc[material].forEach((item, index) => {
|
||||
if (item.name == cdn && item.item_code){
|
||||
frappe.call({
|
||||
method:'erpnext.agriculture.doctype.crop.crop.get_item_details',
|
||||
args: {
|
||||
item_code: item.item_code
|
||||
},
|
||||
callback: (r) => {
|
||||
frappe.model.set_value('BOM Item', item.name, 'uom', r.message.uom);
|
||||
frappe.model.set_value('BOM Item', item.name, 'rate', r.message.rate);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
erpnext.crop.update_item_qty_amount = function(frm, cdt, cdn) {
|
||||
let material_list = ['materials_required', 'produce', 'byproducts'];
|
||||
material_list.forEach((material) => {
|
||||
frm.doc[material].forEach((item, index) => {
|
||||
if (item.name == cdn){
|
||||
if (!frappe.model.get_value('BOM Item', item.name, 'qty'))
|
||||
frappe.model.set_value('BOM Item', item.name, 'qty', 1);
|
||||
frappe.model.set_value('BOM Item', item.name, 'amount', item.qty * item.rate);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
@ -16,3 +16,8 @@ class Crop(Document):
|
||||
# to calculate the period of the Crop Cycle
|
||||
if task.end_day > max_period: max_period = task.end_day
|
||||
if max_period > self.period: self.period = max_period
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_item_details(item_code):
|
||||
item = frappe.get_doc('Item', item_code)
|
||||
return { "uom": item.stock_uom, "rate": item.valuation_rate }
|
@ -15,7 +15,7 @@ frappe.ui.form.on('Crop Cycle', {
|
||||
output[doctype].forEach( (analysis_doc) => {
|
||||
let point_to_be_tested = JSON.parse(analysis_doc.location).features[0].geometry.coordinates;
|
||||
let poly_of_land = JSON.parse(land_doc.location).features[0].geometry.coordinates[0];
|
||||
if (test_analysis_position(point_to_be_tested, poly_of_land)){
|
||||
if (is_in_land_unit(point_to_be_tested, poly_of_land)){
|
||||
obj_to_append[analysis_doctypes_docs[analysis_doctypes.indexOf(doctype)]].push(analysis_doc.name);
|
||||
}
|
||||
});
|
||||
@ -28,7 +28,7 @@ frappe.ui.form.on('Crop Cycle', {
|
||||
}
|
||||
});
|
||||
|
||||
function test_analysis_position(point, vs) {
|
||||
function is_in_land_unit(point, vs) {
|
||||
// ray-casting algorithm based on
|
||||
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
||||
|
||||
|
@ -599,6 +599,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"description": "List of diseases detected on the field. When selected it'll automatically add a list of tasks to deal with the disease ",
|
||||
"fieldname": "section_break_14",
|
||||
"fieldtype": "Section Break",
|
||||
@ -790,7 +791,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-06 01:47:26.656870",
|
||||
"modified": "2017-12-18 12:54:29.071743",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Agriculture",
|
||||
"name": "Crop Cycle",
|
||||
|
@ -12,11 +12,37 @@ class CropCycle(Document):
|
||||
if self.is_new():
|
||||
crop = frappe.get_doc('Crop', self.crop)
|
||||
self.create_project(crop.period, crop.agriculture_task)
|
||||
if not self.project:
|
||||
self.project = self.name
|
||||
for detected_disease in self.detected_disease:
|
||||
disease = frappe.get_doc('Disease', detected_disease.disease)
|
||||
self.create_task(disease.treatment_task, self.name, detected_disease.start_date)
|
||||
if not self.crop_spacing_uom:
|
||||
self.crop_spacing_uom = crop.crop_spacing_uom
|
||||
if not self.row_spacing_uom:
|
||||
self.row_spacing_uom = crop.row_spacing_uom
|
||||
if not self.project:
|
||||
self.project = self.name
|
||||
disease = []
|
||||
for detected_disease in self.detected_disease:
|
||||
disease.append(detected_disease.name)
|
||||
if disease != []:
|
||||
self.update_disease(disease)
|
||||
else:
|
||||
old_disease, new_disease = [], []
|
||||
for detected_disease in self.detected_disease:
|
||||
new_disease.append(detected_disease.name)
|
||||
for detected_disease in self.get_doc_before_save().get('detected_disease'):
|
||||
old_disease.append(detected_disease.name)
|
||||
if list(set(new_disease)-set(old_disease)) != []:
|
||||
self.update_disease(list(set(new_disease)-set(old_disease)))
|
||||
frappe.msgprint("All tasks for the detected diseases were imported")
|
||||
|
||||
def update_disease(self, disease_hashes):
|
||||
new_disease = []
|
||||
for disease in self.detected_disease:
|
||||
for disease_hash in disease_hashes:
|
||||
if disease.name == disease_hash:
|
||||
self.import_disease_tasks(disease.disease, disease.start_date)
|
||||
|
||||
def import_disease_tasks(self, disease, start_date):
|
||||
disease_doc = frappe.get_doc('Disease', disease)
|
||||
self.create_task(disease_doc.treatment_task, self.name, start_date)
|
||||
|
||||
def create_project(self, period, crop_tasks):
|
||||
project = frappe.new_doc("Project")
|
||||
@ -60,3 +86,18 @@ class CropCycle(Document):
|
||||
|
||||
def get_geometry_type(self, doc):
|
||||
return ast.literal_eval(doc.location).get('features')[0].get('geometry').get('type')
|
||||
|
||||
def is_in_land_unit(self, point, vs):
|
||||
x, y = point
|
||||
inside = False
|
||||
j = len(vs)-1
|
||||
i = 0
|
||||
while i < len(vs):
|
||||
xi, yi = vs[i]
|
||||
xj, yj = vs[j]
|
||||
intersect = ((yi > y) != (yj > y)) and (x < (xj - xi) * (y - yi) / (yj - yi) + xi)
|
||||
if intersect:
|
||||
inside = not inside
|
||||
i = j
|
||||
j += 1
|
||||
return inside
|
@ -102,66 +102,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Long Text",
|
||||
"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": "Description",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_2",
|
||||
"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": "Treatment Task",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -222,6 +162,66 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_2",
|
||||
"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": "Treatment Task",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Long Text",
|
||||
"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": "Description",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
@ -234,7 +234,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-04 19:20:19.352479",
|
||||
"modified": "2017-12-07 16:24:22.923154",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Agriculture",
|
||||
"name": "Disease",
|
||||
|
@ -9,6 +9,13 @@ frappe.ui.form.on('Land Unit', {
|
||||
setup: function(frm) {
|
||||
frm.add_fetch("parent_land_unit", "latitude", "latitude");
|
||||
frm.add_fetch("parent_land_unit", "longitude", "longitude");
|
||||
frm.set_query("parent_land_unit", function() {
|
||||
return {
|
||||
"filters": {
|
||||
"is_group": 1
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
onload_post_render(frm){
|
||||
@ -20,12 +27,4 @@ frappe.ui.form.on('Land Unit', {
|
||||
frm.doc.longitude = frm.fields_dict.location.map.getCenter()['lng'];
|
||||
}
|
||||
},
|
||||
refresh: function(frm) {
|
||||
if(!frm.doc.parent_land_unit) {
|
||||
frm.set_read_only();
|
||||
frm.set_intro(__("This is a root land unit and cannot be edited."));
|
||||
} else {
|
||||
frm.set_intro(null);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -431,7 +431,7 @@
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -502,7 +502,7 @@
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_17",
|
||||
"fieldtype": "Section Break",
|
||||
@ -513,6 +513,7 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Linked Analysis",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@ -631,7 +632,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-05 10:57:33.108504",
|
||||
"modified": "2017-12-14 18:16:15.124188",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Agriculture",
|
||||
"name": "Land Unit",
|
||||
@ -679,7 +680,7 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 1,
|
||||
|
@ -10,6 +10,7 @@ import math
|
||||
from frappe import _
|
||||
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
from frappe.utils import flt
|
||||
# from frappe.model.document import Document
|
||||
|
||||
RADIUS = 6378137
|
||||
@ -31,6 +32,7 @@ class LandUnit(NestedSet):
|
||||
ancestor_features[index] = json.loads(feature)
|
||||
ancestor_doc.set_location_value(features = ancestor_features)
|
||||
ancestor_doc.db_set(fieldname='area', value=ancestor_doc.get('area')-self.get('area'),commit=True)
|
||||
super(LandUnit, self).on_update()
|
||||
|
||||
def validate(self):
|
||||
if not self.is_new():
|
||||
@ -39,10 +41,10 @@ class LandUnit(NestedSet):
|
||||
else:
|
||||
features = json.loads(self.get('location')).get('features')
|
||||
new_area = compute_area(features)
|
||||
self.area_difference = new_area - self.area
|
||||
self.area_difference = new_area - flt(self.area)
|
||||
self.area = new_area
|
||||
|
||||
if self.get('parent'):
|
||||
if self.get('parent_land_unit'):
|
||||
ancestors = self.get_ancestors()
|
||||
self_features = self.add_child_property()
|
||||
self_features = set(self_features)
|
||||
@ -78,7 +80,6 @@ class LandUnit(NestedSet):
|
||||
|
||||
def on_update(self):
|
||||
super(LandUnit, self).on_update()
|
||||
self.validate_one_root()
|
||||
|
||||
def add_child_property(self):
|
||||
location = self.get('location')
|
||||
@ -118,7 +119,7 @@ def compute_area(features):
|
||||
layer_area += polygon_area(coords = feature.get('geometry').get('coordinates'))
|
||||
elif feature.get('geometry').get('type') == 'Point' and feature.get('properties').get('point_type') == 'circle':
|
||||
layer_area += math.pi * math.pow(feature.get('properties').get('radius'), 2)
|
||||
return layer_area
|
||||
return flt(layer_area)
|
||||
|
||||
def rad(angle_in_degrees):
|
||||
return angle_in_degrees*math.pi/180
|
||||
@ -163,3 +164,17 @@ def ring_area(coords):
|
||||
area = area * RADIUS * RADIUS / 2
|
||||
return area
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent, is_root=False):
|
||||
if is_root:
|
||||
parent = ''
|
||||
|
||||
land_units = frappe.db.sql("""select name as value,
|
||||
is_group as expandable
|
||||
from `tabLand Unit`
|
||||
where ifnull(`parent_land_unit`,'') = %s
|
||||
order by name""", (parent), as_dict=1)
|
||||
|
||||
# return nodes
|
||||
return land_units
|
||||
|
@ -1,15 +1,30 @@
|
||||
frappe.treeview_settings["Land Unit"] = {
|
||||
get_tree_nodes: "erpnext.agriculture.doctype.land_unit.land_unit.get_children",
|
||||
ignore_fields:["parent_land_unit"],
|
||||
get_tree_root: false,
|
||||
disable_add_node: true,
|
||||
root_label: "All Land Units",
|
||||
onload: function(me) {
|
||||
me.make_tree();
|
||||
},
|
||||
toolbar: [
|
||||
{ toggle_btn: true },
|
||||
{
|
||||
label:__("Add Child"),
|
||||
label:__("Edit"),
|
||||
condition: function(node) { return (node.label!='All Land Units'); },
|
||||
click: function(node) {
|
||||
frappe.set_route('Form', 'Land Unit', node.data.value);
|
||||
}
|
||||
},
|
||||
{
|
||||
label:__("Add Child"),
|
||||
condition: function(node) { return node.expandable; },
|
||||
click: function(node) {
|
||||
if(node.label=='All Land Units') node.label='';
|
||||
var lu = frappe.new_doc("Land Unit", {
|
||||
"parent_land_unit": node.label
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
};
|
@ -12,7 +12,6 @@ QUnit.test("test: Land Unit", function (assert) {
|
||||
// insert a new Land Unit
|
||||
() => frappe.tests.make('Land Unit', [
|
||||
// values to be set
|
||||
{parent_land_unit: 'All Land Units'},
|
||||
{land_unit_name: 'Basil Farm'}
|
||||
]),
|
||||
() => {
|
||||
|
@ -21,6 +21,6 @@ class TestLandUnit(unittest.TestCase):
|
||||
temp['features'][0]['properties']['feature_of'] = land_unit
|
||||
formatted_land_units.extend(temp['features'])
|
||||
formatted_land_unit_string = str(formatted_land_units)
|
||||
all_land_units = frappe.get_doc('Land Unit', 'All Land Units')
|
||||
self.assertEquals(formatted_land_unit_string, str(json.loads(all_land_units.get('location'))['features']))
|
||||
self.assertEquals(area, all_land_units.get('area'))
|
||||
test_land = frappe.get_doc('Land Unit', 'Test Land')
|
||||
self.assertEquals(formatted_land_unit_string, str(json.loads(test_land.get('location'))['features']))
|
||||
self.assertEquals(area, test_land.get('area'))
|
||||
|
@ -1,10 +1,16 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Land Unit",
|
||||
"land_unit_name": "Test Land",
|
||||
"is_group": 1,
|
||||
"is_container": 1
|
||||
},
|
||||
{
|
||||
"doctype": "Land Unit",
|
||||
"land_unit_name": "Basil Farm",
|
||||
"location": "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"properties\":{\"point_type\":\"circle\",\"radius\":884.5625420736483},\"geometry\":{\"type\":\"Point\",\"coordinates\":[72.875834,19.100566]}}]}",
|
||||
"parent_land_unit": "All Land Units",
|
||||
"parent": "All Land Units",
|
||||
"parent_land_unit": "Test Land",
|
||||
"parent": "Test Land",
|
||||
"is_group": 1,
|
||||
"is_container": 1
|
||||
},
|
||||
|
@ -4,12 +4,13 @@ from frappe import _
|
||||
from erpnext.setup.utils import insert_record
|
||||
|
||||
def setup_agriculture():
|
||||
if frappe.get_all('Agriculture Analysis Criteria'):
|
||||
# already setup
|
||||
return
|
||||
create_agriculture_data()
|
||||
|
||||
def create_agriculture_data():
|
||||
records = [
|
||||
dict(
|
||||
doctype="Land Unit",
|
||||
land_unit_name="All Land Units",
|
||||
is_group=1,
|
||||
is_container=1),
|
||||
dict(
|
||||
doctype='Item Group',
|
||||
item_group_name='Fertilizer',
|
||||
@ -182,7 +183,7 @@ def setup_agriculture():
|
||||
linked_doctype='Soil Analysis'),
|
||||
dict(
|
||||
doctype='Agriculture Analysis Criteria',
|
||||
title='pH',
|
||||
title='Soil pH',
|
||||
standard=1,
|
||||
linked_doctype='Soil Analysis'),
|
||||
dict(
|
||||
@ -272,7 +273,7 @@ def setup_agriculture():
|
||||
linked_doctype='Soil Analysis'),
|
||||
dict(
|
||||
doctype='Agriculture Analysis Criteria',
|
||||
title='pH',
|
||||
title='Water pH',
|
||||
standard=1,
|
||||
linked_doctype='Water Analysis'),
|
||||
dict(
|
||||
@ -424,11 +425,6 @@ def setup_agriculture():
|
||||
doctype='Agriculture Analysis Criteria',
|
||||
title='Degree Days',
|
||||
standard=1,
|
||||
linked_doctype='Weather'),
|
||||
dict(
|
||||
doctype='Agriculture Analysis Criteria',
|
||||
title='Degree Days',
|
||||
standard=1,
|
||||
linked_doctype='Water Analysis')
|
||||
linked_doctype='Weather')
|
||||
]
|
||||
insert_record(records)
|
||||
|
@ -175,7 +175,7 @@ frappe.ui.form.on('Asset', {
|
||||
"item_code": frm.doc.item_code,
|
||||
"company": frm.doc.company
|
||||
},
|
||||
method: "erpnext.accounts.doctype.asset.asset.make_sales_invoice",
|
||||
method: "erpnext.assets.doctype.asset.asset.make_sales_invoice",
|
||||
callback: function(r) {
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||
|
@ -154,7 +154,7 @@
|
||||
"label": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped\nIn Repair\nOut of Order",
|
||||
"options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped\nIn Maintenance\nOut of Order",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -193,7 +193,7 @@
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -1221,7 +1221,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-01 15:11:47.466859",
|
||||
"modified": "2017-12-19 12:58:44.137460",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset",
|
||||
|
@ -5,7 +5,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt, add_months, cint, nowdate, getdate
|
||||
from frappe.utils import flt, add_months, cint, nowdate, getdate, today
|
||||
from frappe.model.document import Document
|
||||
from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import get_fixed_asset_account
|
||||
from erpnext.assets.doctype.asset.depreciation \
|
||||
@ -193,6 +193,16 @@ class Asset(Document):
|
||||
status = "Cancelled"
|
||||
return status
|
||||
|
||||
def update_maintenance_status():
|
||||
assets = frappe.get_all('Asset', filters = {'docstatus': 1, 'maintenance_required': 1})
|
||||
|
||||
for asset in assets:
|
||||
asset = frappe.get_doc("Asset", asset.name)
|
||||
if frappe.db.exists('Asset Maintenance Task', {'parent': asset.name, 'next_due_date': today()}):
|
||||
asset.set_status('In Maintenance')
|
||||
if frappe.db.exists('Asset Repair', {'asset_name': asset.name, 'repair_status': 'Pending'}):
|
||||
asset.set_status('Out of Order')
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_purchase_invoice(asset, item_code, gross_purchase_amount, company, posting_date):
|
||||
pi = frappe.new_doc("Purchase Invoice")
|
||||
|
@ -225,7 +225,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"modified": "2015-08-25 04:55:06.052342",
|
||||
"modified": "2017-12-27 15:20:06.052342",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Buying Settings",
|
||||
|
@ -12,6 +12,15 @@ frappe.ui.form.on("Purchase Order", {
|
||||
'Purchase Invoice': 'Invoice',
|
||||
'Stock Entry': 'Material to Supplier'
|
||||
}
|
||||
|
||||
frm.set_query("reserve_warehouse", "supplied_items", function() {
|
||||
return {
|
||||
filters: {
|
||||
"company": frm.doc.company,
|
||||
"is_group": 0
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onload: function(frm) {
|
||||
@ -21,22 +30,17 @@ frappe.ui.form.on("Purchase Order", {
|
||||
return erpnext.queries.warehouse(frm.doc);
|
||||
});
|
||||
|
||||
frappe.db.get_value('Buying Settings', {name: 'Buying Settings'}, 'disable_fetch_last_purchase_rate', (r) => {
|
||||
value = r && cint(r.disable_fetch_last_purchase_rate);
|
||||
frm.toggle_display('get_last_purchase_rate', !value);
|
||||
});
|
||||
|
||||
frm.set_indicator_formatter('item_code',
|
||||
function(doc) { return (doc.qty<=doc.received_qty) ? "green" : "orange" })
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Purchase Order Item", {
|
||||
item_code: function(frm) {
|
||||
frappe.call({
|
||||
method: "get_last_purchase_rate",
|
||||
doc: frm.doc,
|
||||
callback: function(r, rt) {
|
||||
frm.trigger('calculate_taxes_and_totals');
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
schedule_date: function(frm, cdt, cdn) {
|
||||
var row = locals[cdt][cdn];
|
||||
if (row.schedule_date) {
|
||||
@ -289,7 +293,8 @@ cur_frm.fields_dict['items'].grid.get_field('bom').get_query = function(doc, cdt
|
||||
filters: [
|
||||
['BOM', 'item', '=', d.item_code],
|
||||
['BOM', 'is_active', '=', '1'],
|
||||
['BOM', 'docstatus', '=', '1']
|
||||
['BOM', 'docstatus', '=', '1'],
|
||||
['BOM', 'company', '=', doc.company]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1238,6 +1238,37 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.docstatus===0 && (doc.items && doc.items.length)",
|
||||
"fieldname": "get_last_purchase_rate",
|
||||
"fieldtype": "Button",
|
||||
"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": "Get last purchase rate",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -2552,7 +2583,7 @@
|
||||
"options": "Payment Schedule",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@ -3071,6 +3102,38 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.is_subcontracted",
|
||||
"fieldname": "supplied_items_section",
|
||||
"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": "Supplied Items",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "supplied_items",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@ -3261,7 +3324,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-29 14:06:33.636401",
|
||||
"modified": "2018-01-05 14:44:56.132189",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
@ -11,9 +11,8 @@ from erpnext.controllers.buying_controller import BuyingController
|
||||
from erpnext.stock.doctype.item.item import get_last_purchase_details
|
||||
from erpnext.stock.stock_balance import update_bin_qty, get_ordered_qty
|
||||
from frappe.desk.notifications import clear_doctype_notifications
|
||||
from erpnext.buying.utils import (validate_for_items, check_for_closed_status,
|
||||
update_last_purchase_rate)
|
||||
|
||||
from erpnext.buying.utils import validate_for_items, check_for_closed_status
|
||||
from erpnext.stock.utils import get_bin
|
||||
|
||||
form_grid_templates = {
|
||||
"items": "templates/form_grid/item_grid.html"
|
||||
@ -72,8 +71,10 @@ class PurchaseOrder(BuyingController):
|
||||
def validate_supplier(self):
|
||||
prevent_po = frappe.db.get_value("Supplier", self.supplier, 'prevent_pos')
|
||||
if prevent_po:
|
||||
standing = frappe.db.get_value("Supplier Scorecard",self.supplier, 'status')
|
||||
frappe.throw(_("Purchase Orders are not allowed for {0} due to a scorecard standing of {1}.").format(self.supplier, standing))
|
||||
standing = frappe.db.get_value("Supplier Scorecard", self.supplier, 'status')
|
||||
if standing:
|
||||
frappe.throw(_("Purchase Orders are not allowed for {0} due to a scorecard standing of {1}.")
|
||||
.format(self.supplier, standing))
|
||||
|
||||
warn_po = frappe.db.get_value("Supplier", self.supplier, 'warn_pos')
|
||||
if warn_po:
|
||||
@ -112,27 +113,26 @@ class PurchaseOrder(BuyingController):
|
||||
|
||||
def get_last_purchase_rate(self):
|
||||
"""get last purchase rates for all items"""
|
||||
if cint(frappe.db.get_single_value("Buying Settings", "disable_fetch_last_purchase_rate")): return
|
||||
|
||||
if not cint(frappe.db.get_single_value("Buying Settings", "disable_fetch_last_purchase_rate")):
|
||||
conversion_rate = flt(self.get('conversion_rate')) or 1.0
|
||||
conversion_rate = flt(self.get('conversion_rate')) or 1.0
|
||||
for d in self.get("items"):
|
||||
if d.item_code:
|
||||
last_purchase_details = get_last_purchase_details(d.item_code, self.name)
|
||||
if last_purchase_details:
|
||||
d.base_price_list_rate = (last_purchase_details['base_price_list_rate'] *
|
||||
(flt(d.conversion_factor) or 1.0))
|
||||
d.discount_percentage = last_purchase_details['discount_percentage']
|
||||
d.base_rate = last_purchase_details['base_rate'] * (flt(d.conversion_factor) or 1.0)
|
||||
d.price_list_rate = d.base_price_list_rate / conversion_rate
|
||||
d.rate = d.base_rate / conversion_rate
|
||||
d.last_purchase_rate = d.rate
|
||||
else:
|
||||
|
||||
for d in self.get("items"):
|
||||
if d.item_code:
|
||||
last_purchase_details = get_last_purchase_details(d.item_code, self.name)
|
||||
|
||||
if last_purchase_details:
|
||||
d.base_price_list_rate = (last_purchase_details['base_price_list_rate'] *
|
||||
(flt(d.conversion_factor) or 1.0))
|
||||
d.discount_percentage = last_purchase_details['discount_percentage']
|
||||
d.base_rate = last_purchase_details['base_rate'] * (flt(d.conversion_factor) or 1.0)
|
||||
d.price_list_rate = d.base_price_list_rate / conversion_rate
|
||||
d.last_purchase_rate = d.base_rate / conversion_rate
|
||||
else:
|
||||
|
||||
item_last_purchase_rate = frappe.db.get_value("Item", d.item_code, "last_purchase_rate")
|
||||
if item_last_purchase_rate:
|
||||
d.base_price_list_rate = d.base_rate = d.price_list_rate \
|
||||
= d.last_purchase_rate = item_last_purchase_rate
|
||||
item_last_purchase_rate = frappe.db.get_value("Item", d.item_code, "last_purchase_rate")
|
||||
if item_last_purchase_rate:
|
||||
d.base_price_list_rate = d.base_rate = d.price_list_rate \
|
||||
= d.rate = d.last_purchase_rate = item_last_purchase_rate
|
||||
|
||||
# Check for Closed status
|
||||
def check_for_closed_status(self):
|
||||
@ -185,29 +185,39 @@ class PurchaseOrder(BuyingController):
|
||||
self.set_status(update=True, status=status)
|
||||
self.update_requested_qty()
|
||||
self.update_ordered_qty()
|
||||
if self.is_subcontracted == "Yes":
|
||||
self.update_reserved_qty_for_subcontract()
|
||||
|
||||
self.notify_update()
|
||||
clear_doctype_notifications(self)
|
||||
|
||||
def on_submit(self):
|
||||
super(PurchaseOrder, self).on_submit()
|
||||
|
||||
if self.is_against_so():
|
||||
self.update_status_updater()
|
||||
|
||||
self.update_prevdoc_status()
|
||||
self.update_requested_qty()
|
||||
self.update_ordered_qty()
|
||||
if self.is_subcontracted == "Yes":
|
||||
self.update_reserved_qty_for_subcontract()
|
||||
|
||||
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
|
||||
self.company, self.base_grand_total)
|
||||
|
||||
update_last_purchase_rate(self, is_submit = 1)
|
||||
|
||||
def on_cancel(self):
|
||||
super(PurchaseOrder, self).on_cancel()
|
||||
|
||||
if self.is_against_so():
|
||||
self.update_status_updater()
|
||||
|
||||
if self.has_drop_ship_item():
|
||||
self.update_delivered_qty_in_sales_order()
|
||||
|
||||
if self.is_subcontracted == "Yes":
|
||||
self.update_reserved_qty_for_subcontract()
|
||||
|
||||
self.check_for_closed_status()
|
||||
|
||||
frappe.db.set(self,'status','Cancelled')
|
||||
@ -218,8 +228,6 @@ class PurchaseOrder(BuyingController):
|
||||
self.update_requested_qty()
|
||||
self.update_ordered_qty()
|
||||
|
||||
update_last_purchase_rate(self, is_submit = 0)
|
||||
|
||||
def on_update(self):
|
||||
pass
|
||||
|
||||
@ -257,6 +265,27 @@ class PurchaseOrder(BuyingController):
|
||||
if item.delivered_by_supplier == 1:
|
||||
item.received_qty = item.qty
|
||||
|
||||
def update_reserved_qty_for_subcontract(self):
|
||||
for d in self.supplied_items:
|
||||
if d.rm_item_code:
|
||||
stock_bin = get_bin(d.rm_item_code, d.reserve_warehouse)
|
||||
stock_bin.update_reserved_qty_for_sub_contracting()
|
||||
|
||||
def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor= 1.0):
|
||||
"""get last purchase rate for an item"""
|
||||
if cint(frappe.db.get_single_value("Buying Settings", "disable_fetch_last_purchase_rate")): return
|
||||
|
||||
conversion_rate = flt(conversion_rate) or 1.0
|
||||
|
||||
last_purchase_details = get_last_purchase_details(item_code, name)
|
||||
if last_purchase_details:
|
||||
last_purchase_rate = (last_purchase_details['base_rate'] * (flt(conversion_factor) or 1.0)) / conversion_rate
|
||||
return last_purchase_rate
|
||||
else:
|
||||
item_last_purchase_rate = frappe.db.get_value("Item", item_code, "last_purchase_rate")
|
||||
if item_last_purchase_rate:
|
||||
return item_last_purchase_rate
|
||||
|
||||
@frappe.whitelist()
|
||||
def close_or_unclose_purchase_orders(names, status):
|
||||
if not frappe.has_permission("Purchase Order", "write"):
|
||||
|
@ -6,8 +6,8 @@ import unittest
|
||||
import frappe
|
||||
import frappe.defaults
|
||||
from frappe.utils import flt, add_days, nowdate
|
||||
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt, make_purchase_invoice
|
||||
|
||||
from erpnext.buying.doctype.purchase_order.purchase_order import (make_purchase_receipt, make_purchase_invoice, make_stock_entry as make_subcontract_transfer_entry)
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||
|
||||
class TestPurchaseOrder(unittest.TestCase):
|
||||
def test_make_purchase_receipt(self):
|
||||
@ -182,24 +182,129 @@ class TestPurchaseOrder(unittest.TestCase):
|
||||
pi.insert()
|
||||
self.assertTrue(pi.get('payment_schedule'))
|
||||
|
||||
def test_reserved_qty_subcontract_po(self):
|
||||
# Make stock available for raw materials
|
||||
make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100)
|
||||
make_stock_entry(target="_Test Warehouse - _TC", item_code="_Test Item Home Desktop 100",
|
||||
qty=20, basic_rate=100)
|
||||
|
||||
bin1 = frappe.db.get_value("Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname=["reserved_qty_for_sub_contract", "projected_qty"], as_dict=1)
|
||||
|
||||
# Submit PO
|
||||
po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes")
|
||||
|
||||
bin2 = frappe.db.get_value("Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname=["reserved_qty_for_sub_contract", "projected_qty"], as_dict=1)
|
||||
self.assertEquals(bin2.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10)
|
||||
self.assertEquals(bin2.projected_qty, bin1.projected_qty - 10)
|
||||
|
||||
# Create stock transfer
|
||||
se = frappe.get_doc(make_subcontract_transfer_entry(po.name, "_Test FG Item"))
|
||||
se.to_warehouse = "_Test Warehouse 1 - _TC"
|
||||
for d in se.get("items"):
|
||||
if d.item_code == "_Test Item":
|
||||
d.qty = 6
|
||||
se.save()
|
||||
se.submit()
|
||||
|
||||
bin3 = frappe.db.get_value("Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract", as_dict=1)
|
||||
|
||||
self.assertEquals(bin3.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
|
||||
|
||||
# close PO
|
||||
po.update_status("Closed")
|
||||
bin4 = frappe.db.get_value("Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract", as_dict=1)
|
||||
|
||||
self.assertEquals(bin4.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
|
||||
|
||||
# Re-open PO
|
||||
po.update_status("Submitted")
|
||||
bin5 = frappe.db.get_value("Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract", as_dict=1)
|
||||
|
||||
self.assertEquals(bin5.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
|
||||
|
||||
# make Purchase Receipt against PO
|
||||
pr = make_purchase_receipt(po.name)
|
||||
pr.supplier_warehouse = "_Test Warehouse 1 - _TC"
|
||||
pr.save()
|
||||
pr.submit()
|
||||
|
||||
bin6 = frappe.db.get_value("Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract", as_dict=1)
|
||||
|
||||
self.assertEquals(bin6.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
|
||||
|
||||
# Cancel PR
|
||||
pr.cancel()
|
||||
bin7 = frappe.db.get_value("Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract", as_dict=1)
|
||||
|
||||
self.assertEquals(bin7.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
|
||||
|
||||
# Make Purchase Invoice
|
||||
pi = make_purchase_invoice(po.name)
|
||||
pi.update_stock = 1
|
||||
pi.supplier_warehouse = "_Test Warehouse 1 - _TC"
|
||||
pi.insert()
|
||||
pi.submit()
|
||||
bin8 = frappe.db.get_value("Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract", as_dict=1)
|
||||
|
||||
self.assertEquals(bin8.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
|
||||
|
||||
# Cancel PR
|
||||
pi.cancel()
|
||||
bin9 = frappe.db.get_value("Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract", as_dict=1)
|
||||
|
||||
self.assertEquals(bin9.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
|
||||
|
||||
# Cancel Stock Entry
|
||||
se.cancel()
|
||||
bin10 = frappe.db.get_value("Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract", as_dict=1)
|
||||
self.assertEquals(bin10.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10)
|
||||
|
||||
# Cancel PO
|
||||
po.reload()
|
||||
po.cancel()
|
||||
bin11 = frappe.db.get_value("Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract", as_dict=1)
|
||||
|
||||
self.assertEquals(bin11.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
|
||||
|
||||
def get_same_items():
|
||||
return [
|
||||
{
|
||||
"item_code": "_Test FG Item",
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"qty": 1,
|
||||
"rate": 500,
|
||||
"schedule_date": add_days(nowdate(), 1)
|
||||
},
|
||||
{
|
||||
"item_code": "_Test FG Item",
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"qty": 4,
|
||||
"rate": 500,
|
||||
"schedule_date": add_days(nowdate(), 1)
|
||||
}
|
||||
]
|
||||
{
|
||||
"item_code": "_Test FG Item",
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"qty": 1,
|
||||
"rate": 500,
|
||||
"schedule_date": add_days(nowdate(), 1)
|
||||
},
|
||||
{
|
||||
"item_code": "_Test FG Item",
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"qty": 4,
|
||||
"rate": 500,
|
||||
"schedule_date": add_days(nowdate(), 1)
|
||||
}
|
||||
]
|
||||
|
||||
def create_purchase_order(**args):
|
||||
po = frappe.new_doc("Purchase Order")
|
||||
@ -224,6 +329,10 @@ def create_purchase_order(**args):
|
||||
if not args.do_not_save:
|
||||
po.insert()
|
||||
if not args.do_not_submit:
|
||||
if po.is_subcontracted == "Yes":
|
||||
supp_items = po.get("supplied_items")
|
||||
for d in supp_items:
|
||||
d.reserve_warehouse = args.warehouse or "_Test Warehouse - _TC"
|
||||
po.submit()
|
||||
|
||||
return po
|
||||
|
@ -24,7 +24,7 @@ QUnit.test("test: purchase order with taxes and charges", function(assert) {
|
||||
]
|
||||
]},
|
||||
|
||||
{taxes_and_charges: 'TEST In State GST'}
|
||||
{taxes_and_charges: 'TEST In State GST - FT'}
|
||||
]);
|
||||
},
|
||||
|
||||
|
@ -1169,7 +1169,7 @@
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -1259,7 +1259,7 @@
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -1897,7 +1897,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-30 14:17:15.817754",
|
||||
"modified": "2017-12-14 09:36:40.837027",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order Item",
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
@ -10,16 +11,20 @@
|
||||
"editable_grid": 1,
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "main_item_code",
|
||||
"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": "Item Code",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@ -29,6 +34,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@ -36,16 +42,20 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "rm_item_code",
|
||||
"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": "Raw Material Item Code",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@ -55,6 +65,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@ -62,16 +73,20 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "required_qty",
|
||||
"fieldtype": "Float",
|
||||
"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": "Supplied Qty",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@ -81,6 +96,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@ -88,16 +104,20 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "rate",
|
||||
"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": "Rate",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@ -108,6 +128,7 @@
|
||||
"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,
|
||||
@ -115,16 +136,20 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 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": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@ -135,6 +160,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@ -142,16 +168,49 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_6",
|
||||
"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
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "bom_detail_no",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "BOM Detail No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@ -161,6 +220,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@ -168,16 +228,20 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "reference_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Reference Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@ -187,6 +251,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@ -194,16 +259,20 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "conversion_factor",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Conversion Factor",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@ -213,6 +282,7 @@
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@ -220,16 +290,20 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "stock_uom",
|
||||
"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": "Stock Uom",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
@ -240,6 +314,38 @@
|
||||
"print_hide": 0,
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "reserve_warehouse",
|
||||
"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": "Reserve Warehouse",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Warehouse",
|
||||
"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,
|
||||
@ -247,17 +353,17 @@
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 1,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-11 03:28:05.533063",
|
||||
"modified": "2018-01-05 14:47:15.400785",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order Item Supplied",
|
||||
@ -266,5 +372,7 @@
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
}
|
@ -941,8 +941,8 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-08-31 16:10:44.049915",
|
||||
"modified_by": "tundebabzy@gmail.com",
|
||||
"modified": "2017-12-26 04:50:15.317590",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier",
|
||||
"name_case": "Title Case",
|
||||
|
@ -17,7 +17,7 @@ QUnit.test("test: supplier quotation with taxes and charges", function(assert) {
|
||||
{"warehouse": 'Stores - '+frappe.get_abbr(frappe.defaults.get_default('Company'))},
|
||||
]
|
||||
]},
|
||||
{taxes_and_charges:'TEST In State GST'},
|
||||
{taxes_and_charges:'TEST In State GST - FT'},
|
||||
]);
|
||||
},
|
||||
() => {supplier_quotation_name = cur_frm.doc.name;},
|
||||
|
@ -1072,7 +1072,7 @@
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -1162,7 +1162,7 @@
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -1614,7 +1614,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-30 14:22:10.542868",
|
||||
"modified": "2017-12-14 09:37:47.427897",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation Item",
|
||||
|
61
erpnext/change_log/v10/v10_0_0.md
Normal file
61
erpnext/change_log/v10/v10_0_0.md
Normal file
@ -0,0 +1,61 @@
|
||||
- Account Numbers
|
||||
- Default Chart of accounts with account number
|
||||
- Set account number for your existing chart of accounts
|
||||
|
||||
- Payment Terms
|
||||
- Create Sales Invoice with multiple due dates and payment slab
|
||||
|
||||
- Agriculture (New Domain)
|
||||
- Manage Crop, Crop Cycle, Land Unit, Disease and Fertilizer records
|
||||
- Maintain records of Plant / Soil / Water Analysis
|
||||
|
||||
- Non Profits (New Domain)
|
||||
- Manage records of Members, Donors, Volunteers and Chapters
|
||||
- Portal for Grant Application
|
||||
|
||||
- Delivery Trip
|
||||
- Track each of your delivery trips with their associated stops and timing
|
||||
|
||||
- Item Variants Update
|
||||
- Create variants from Quick Entry dialog
|
||||
- Create multiple variants from a single screen
|
||||
|
||||
- Shipping Rule
|
||||
- Now available in Buying cycle
|
||||
- Apply based on Net Weight / Fixed Amount / Net Total
|
||||
|
||||
- Updated POS
|
||||
- Single POS Profile for multiple Users
|
||||
- Sales Payment Summary (X & Z) report
|
||||
- Fixed multiple bugs
|
||||
|
||||
- Employee Advance
|
||||
- Manage Advances given to your employee and adjust with Expense Claim
|
||||
|
||||
- Payroll Entry
|
||||
- Maintain records of each payroll processing
|
||||
- Deprecated Process Payroll tool
|
||||
|
||||
- Schools to Education
|
||||
- School module is renamed to Education
|
||||
|
||||
- Opening Invoice Tool
|
||||
- A new tool to create opening invoices
|
||||
|
||||
- Asset Maintenance
|
||||
- Maintain records of Asset Maintenance and Asset Repair
|
||||
|
||||
- Employee Tree
|
||||
- Employee document now has a tree view, so you can create your organisation chart based on it
|
||||
|
||||
- Task Tree
|
||||
- Task also has a Tree view now
|
||||
|
||||
- Education module update
|
||||
- Course Scheduling Tool
|
||||
|
||||
- Batch selection based on earlier expiry date of the batch
|
||||
|
||||
- Invoice GL Entry based on rounded total (instead of grand total)
|
||||
|
||||
- Multiple UOM in Material Request
|
@ -134,6 +134,14 @@ def get_data():
|
||||
"link": "pos",
|
||||
"label": _("POS")
|
||||
},
|
||||
{
|
||||
"module_name": "Leaderboard",
|
||||
"color": "#589494",
|
||||
"icon": "octicon octicon-graph",
|
||||
"type": "page",
|
||||
"link": "leaderboard",
|
||||
"label": _("Leaderboard")
|
||||
},
|
||||
{
|
||||
"module_name": "Projects",
|
||||
"color": "#8e44ad",
|
||||
@ -292,18 +300,21 @@ def get_data():
|
||||
"label": _("Hub")
|
||||
},
|
||||
{
|
||||
"module_name": "Data Import Tool",
|
||||
"color": "#7f8c8d",
|
||||
"icon": "octicon octicon-circuit-board",
|
||||
"type": "page",
|
||||
"link": "data-import-tool",
|
||||
"label": _("Data Import Tool")
|
||||
"module_name": "Data Import",
|
||||
"color": "#FFF168",
|
||||
"reverse": 1,
|
||||
"doctype": "Data Import",
|
||||
"icon": "octicon octicon-cloud-upload",
|
||||
"label": _("Data Import"),
|
||||
"link": "List/Data Import",
|
||||
"type": "list"
|
||||
},
|
||||
{
|
||||
"module_name": "Restaurant",
|
||||
"color": "#EA81E8",
|
||||
"icon": "🍔",
|
||||
"_doctype": "Restaurant",
|
||||
"type": "list",
|
||||
"link": "List/Restaurant",
|
||||
"label": _("Restaurant"),
|
||||
"hidden": 1
|
||||
@ -322,7 +333,7 @@ def get_data():
|
||||
"label": _("Crop"),
|
||||
"color": "#8BC34A",
|
||||
"icon": "fa fa-tree",
|
||||
"type": "link",
|
||||
"type": "list",
|
||||
"link": "List/Crop",
|
||||
"hidden": 1
|
||||
},
|
||||
@ -332,7 +343,7 @@ def get_data():
|
||||
"label": _("Crop Cycle"),
|
||||
"color": "#8BC34A",
|
||||
"icon": "fa fa-circle-o-notch",
|
||||
"type": "link",
|
||||
"type": "list",
|
||||
"link": "List/Crop Cycle",
|
||||
"hidden": 1
|
||||
},
|
||||
@ -342,7 +353,7 @@ def get_data():
|
||||
"label": _("Fertilizer"),
|
||||
"color": "#8BC34A",
|
||||
"icon": "fa fa-leaf",
|
||||
"type": "link",
|
||||
"type": "list",
|
||||
"link": "List/Fertilizer",
|
||||
"hidden": 1
|
||||
},
|
||||
@ -352,7 +363,7 @@ def get_data():
|
||||
"label": _("Land Unit"),
|
||||
"color": "#8BC34A",
|
||||
"icon": "fa fa-map",
|
||||
"type": "link",
|
||||
"type": "list",
|
||||
"link": "List/Land Unit",
|
||||
"hidden": 1
|
||||
},
|
||||
@ -362,7 +373,7 @@ def get_data():
|
||||
"label": _("Disease"),
|
||||
"color": "#8BC34A",
|
||||
"icon": "octicon octicon-bug",
|
||||
"type": "link",
|
||||
"type": "list",
|
||||
"link": "List/Disease",
|
||||
"hidden": 1
|
||||
},
|
||||
@ -372,7 +383,7 @@ def get_data():
|
||||
"label": _("Plant Analysis"),
|
||||
"color": "#8BC34A",
|
||||
"icon": "fa fa-pagelines",
|
||||
"type": "link",
|
||||
"type": "list",
|
||||
"link": "List/Plant Analysis",
|
||||
"hidden": 1
|
||||
},
|
||||
@ -382,7 +393,7 @@ def get_data():
|
||||
"label": _("Soil Analysis"),
|
||||
"color": "#8BC34A",
|
||||
"icon": "fa fa-flask",
|
||||
"type": "link",
|
||||
"type": "list",
|
||||
"link": "List/Soil Analysis",
|
||||
"hidden": 1
|
||||
},
|
||||
@ -392,7 +403,7 @@ def get_data():
|
||||
"label": _("Soil Texture"),
|
||||
"color": "#8BC34A",
|
||||
"icon": "octicon octicon-beaker",
|
||||
"type": "link",
|
||||
"type": "list",
|
||||
"link": "List/Soil Texture",
|
||||
"hidden": 1
|
||||
},
|
||||
@ -402,7 +413,7 @@ def get_data():
|
||||
"label": _("Water Analysis"),
|
||||
"color": "#8BC34A",
|
||||
"icon": "fa fa-tint",
|
||||
"type": "link",
|
||||
"type": "list",
|
||||
"link": "List/Water Analysis",
|
||||
"hidden": 1
|
||||
},
|
||||
@ -412,7 +423,7 @@ def get_data():
|
||||
"label": _("Weather"),
|
||||
"color": "#8BC34A",
|
||||
"icon": "fa fa-sun-o",
|
||||
"type": "link",
|
||||
"type": "list",
|
||||
"link": "List/Weather",
|
||||
"hidden": 1
|
||||
},
|
||||
@ -429,6 +440,7 @@ def get_data():
|
||||
"color": "#E9AB17",
|
||||
"icon": "fa fa-gift",
|
||||
"_doctype": "Grant Application",
|
||||
"type": "list",
|
||||
"link": "List/Grant Application",
|
||||
"label": _("Grant Application"),
|
||||
"hidden": 1
|
||||
@ -439,6 +451,7 @@ def get_data():
|
||||
"color": "#7F5A58",
|
||||
"icon": "fa fa-tint",
|
||||
"_doctype": "Donor",
|
||||
"type": "list",
|
||||
"link": "List/Donor",
|
||||
"label": _("Donor"),
|
||||
"hidden": 1
|
||||
@ -448,6 +461,7 @@ def get_data():
|
||||
"color": "#7E587E",
|
||||
"icon": "fa fa-angellist",
|
||||
"_doctype": "Volunteer",
|
||||
"type": "list",
|
||||
"link": "List/Volunteer",
|
||||
"label": _("Volunteer"),
|
||||
"hidden": 1
|
||||
@ -457,6 +471,7 @@ def get_data():
|
||||
"color": "#79BAEC",
|
||||
"icon": "fa fa-users",
|
||||
"_doctype": "Member",
|
||||
"type": "list",
|
||||
"link": "List/Member",
|
||||
"label": _("Member"),
|
||||
"hidden": 1
|
||||
@ -466,6 +481,7 @@ def get_data():
|
||||
"color": "#3B9C9C",
|
||||
"icon": "fa fa-handshake-o",
|
||||
"_doctype": "Chapter",
|
||||
"type": "list",
|
||||
"link": "List/Chapter",
|
||||
"label": _("Chapter"),
|
||||
"hidden": 1
|
||||
|
@ -11,7 +11,7 @@ def get_data():
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Patient Appointment",
|
||||
"description": _("Patient Appointment"),
|
||||
"label": _("Patient Appointment"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
@ -43,7 +43,7 @@ def get_data():
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Lab Test",
|
||||
"description": _("Results"),
|
||||
"label": _("Lab Test"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
@ -53,7 +53,8 @@ def get_data():
|
||||
{
|
||||
"type": "report",
|
||||
"name": "Lab Test Report",
|
||||
"is_query_report": True
|
||||
"is_query_report": True,
|
||||
"label": _("Lab Test Report"),
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -69,7 +70,7 @@ def get_data():
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Physician",
|
||||
"label": "Physician",
|
||||
"label": _("Physician"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
@ -100,57 +101,57 @@ def get_data():
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Medical Department",
|
||||
"label": "Medical Department"
|
||||
"label": _("Medical Department"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Appointment Type",
|
||||
"description": _("Appointment Type Master"),
|
||||
"label": _("Appointment Type"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Prescription Dosage",
|
||||
"description": _("Prescription Dosage")
|
||||
"label": _("Prescription Dosage")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Prescription Duration",
|
||||
"description": _("Prescription Period")
|
||||
"label": _("Prescription Duration")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Complaint",
|
||||
"description": _("Complaint")
|
||||
"label": _("Complaint")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Diagnosis",
|
||||
"description": _("Diagnosis")
|
||||
"label": _("Diagnosis")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Lab Test Sample",
|
||||
"description": _("Test Sample Master."),
|
||||
"label": _("Test Sample."),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Lab Test UOM",
|
||||
"description": _("Lab Test UOM.")
|
||||
"label": _("Lab Test UOM.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Antibiotic",
|
||||
"description": _("Antibiotic.")
|
||||
"label": _("Antibiotic.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Sensitivity",
|
||||
"description": _("Sensitivity Naming.")
|
||||
"label": _("Sensitivity Naming.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Lab Test Template",
|
||||
"description": _("Lab Test Configurations.")
|
||||
"label": _("Lab Test Template.")
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -121,6 +121,11 @@ def get_data():
|
||||
{
|
||||
"label": _("Expense Claims"),
|
||||
"items": [
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Employee Advance",
|
||||
"description": _("Manage advance amount given to the Employee"),
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Expense Claim",
|
||||
|
@ -24,7 +24,7 @@ def get_data():
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Report Builder"),
|
||||
"youtube_id": "y0o5iYZOioU"
|
||||
"youtube_id": "TxJGUNarcQs"
|
||||
},
|
||||
]
|
||||
|
||||
@ -40,7 +40,7 @@ def get_data():
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Opening Stock Balance"),
|
||||
"youtube_id": "0yPgrtfeCTs"
|
||||
"youtube_id": "nlHX0ZZ84Lw"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
@ -55,7 +55,7 @@ def get_data():
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Users and Permissions"),
|
||||
"youtube_id": "fnBoRhBrwR4"
|
||||
"youtube_id": "8Slw1hsTmUI"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
@ -120,7 +120,7 @@ def get_data():
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Sales Order to Payment"),
|
||||
"youtube_id": "7AMq4lqkN4A"
|
||||
"youtube_id": "1eP90MWoDQM"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
@ -195,12 +195,12 @@ def get_data():
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Material Request to Purchase Order"),
|
||||
"youtube_id": "4TN9kPyfIqM"
|
||||
"youtube_id": "55Gk2j7Q8Zw"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Purchase Order to Payment"),
|
||||
"youtube_id": "EK65tLdVUDk"
|
||||
"youtube_id": "efFajTTQBa8"
|
||||
},
|
||||
{
|
||||
"type": "help",
|
||||
@ -261,7 +261,7 @@ def get_data():
|
||||
{
|
||||
"type": "help",
|
||||
"label": _("Managing Projects"),
|
||||
"youtube_id": "egxIGwtoKI4"
|
||||
"youtube_id": "gCzShu9Niu4"
|
||||
},
|
||||
]
|
||||
},
|
||||
|
@ -56,7 +56,12 @@ def get_data():
|
||||
"name": "Stock Ageing",
|
||||
"doctype": "Item",
|
||||
},
|
||||
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Item Price Stock",
|
||||
"doctype": "Item",
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -64,15 +64,14 @@ class AccountsController(TransactionBase):
|
||||
def validate_invoice_documents_schedule(self):
|
||||
self.validate_payment_schedule_dates()
|
||||
self.set_due_date()
|
||||
self.validate_invoice_portion()
|
||||
self.set_payment_schedule()
|
||||
self.validate_payment_schedule_amount()
|
||||
self.validate_due_date()
|
||||
self.validate_advance_entries()
|
||||
|
||||
def validate_non_invoice_documents_schedule(self):
|
||||
self.validate_invoice_portion()
|
||||
self.set_payment_schedule()
|
||||
self.validate_payment_schedule_dates()
|
||||
self.validate_payment_schedule_amount()
|
||||
|
||||
def validate_all_documents_schedule(self):
|
||||
@ -233,9 +232,10 @@ class AccountsController(TransactionBase):
|
||||
tax_master_doctype = self.meta.get_field("taxes_and_charges").options
|
||||
|
||||
if self.is_new() and not self.get("taxes"):
|
||||
if not self.get("taxes_and_charges"):
|
||||
if self.company and not self.get("taxes_and_charges"):
|
||||
# get the default tax master
|
||||
self.taxes_and_charges = frappe.db.get_value(tax_master_doctype, {"is_default": 1})
|
||||
self.taxes_and_charges = frappe.db.get_value(tax_master_doctype,
|
||||
{"is_default": 1, 'company': self.company})
|
||||
|
||||
self.append_taxes_from_master(tax_master_doctype)
|
||||
|
||||
@ -375,6 +375,17 @@ class AccountsController(TransactionBase):
|
||||
|
||||
return res
|
||||
|
||||
def is_inclusive_tax(self):
|
||||
is_inclusive = cint(frappe.db.get_single_value("Accounts Settings",
|
||||
"show_inclusive_tax_in_print"))
|
||||
|
||||
if is_inclusive:
|
||||
is_inclusive = 0
|
||||
if self.get("taxes", filters={"included_in_print_rate": 1}):
|
||||
is_inclusive = 1
|
||||
|
||||
return is_inclusive
|
||||
|
||||
def validate_advance_entries(self):
|
||||
order_field = "sales_order" if self.doctype == "Sales Invoice" else "purchase_order"
|
||||
order_list = list(set([d.get(order_field)
|
||||
@ -650,6 +661,8 @@ class AccountsController(TransactionBase):
|
||||
date = self.get("due_date")
|
||||
due_date = date or posting_date
|
||||
grand_total = self.get("rounded_total") or self.grand_total
|
||||
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||
grand_total = grand_total - flt(self.write_off_amount)
|
||||
|
||||
if not self.get("payment_schedule"):
|
||||
if self.get("payment_terms_template"):
|
||||
@ -661,7 +674,8 @@ class AccountsController(TransactionBase):
|
||||
self.append("payment_schedule", data)
|
||||
else:
|
||||
for d in self.get("payment_schedule"):
|
||||
d.payment_amount = grand_total * flt(d.invoice_portion) / 100
|
||||
if d.invoice_portion:
|
||||
d.payment_amount = grand_total * flt(d.invoice_portion) / 100
|
||||
|
||||
def set_due_date(self):
|
||||
due_dates = [d.due_date for d in self.get("payment_schedule") if d.due_date]
|
||||
@ -671,15 +685,12 @@ class AccountsController(TransactionBase):
|
||||
def validate_payment_schedule_dates(self):
|
||||
dates = []
|
||||
li = []
|
||||
if self.due_date and getdate(self.due_date) < getdate(self.posting_date):
|
||||
frappe.throw(_("Due Date cannot be before posting date"))
|
||||
|
||||
for d in self.get("payment_schedule"):
|
||||
if getdate(d.due_date) < getdate(self.posting_date):
|
||||
if self.doctype == "Sales Order" and getdate(d.due_date) < getdate(self.transaction_date):
|
||||
frappe.throw(_("Row {0}: Due Date cannot be before posting date").format(d.idx))
|
||||
elif d.due_date in dates:
|
||||
li.append('{0} in row {1}'.format(d.due_date, d.idx))
|
||||
# frappe.throw(_("Row {0}: Duplicate due date found").format(d.idx))
|
||||
dates.append(d.due_date)
|
||||
|
||||
if li:
|
||||
@ -692,20 +703,14 @@ class AccountsController(TransactionBase):
|
||||
total = 0
|
||||
for d in self.get("payment_schedule"):
|
||||
total += flt(d.payment_amount)
|
||||
total = flt(total, self.precision("grand_total"))
|
||||
|
||||
grand_total = self.get("rounded_total") or self.grand_total
|
||||
grand_total = flt(self.get("rounded_total") or self.grand_total, self.precision('grand_total'))
|
||||
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||
grand_total = grand_total - flt(self.write_off_amount)
|
||||
if total != grand_total:
|
||||
frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total"))
|
||||
|
||||
def validate_invoice_portion(self):
|
||||
if self.get("payment_schedule"):
|
||||
total_portion = 0
|
||||
for term in self.payment_schedule:
|
||||
total_portion += flt(term.get('invoice_portion', 0))
|
||||
|
||||
if flt(total_portion, 2) != 100.00:
|
||||
frappe.throw(_('Combined invoice portion must equal 100%'), indicator='red')
|
||||
|
||||
def is_rounded_total_disabled(self):
|
||||
if self.meta.get_field("disable_rounded_total"):
|
||||
return self.disable_rounded_total
|
||||
@ -717,8 +722,12 @@ def get_tax_rate(account_head):
|
||||
return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_default_taxes_and_charges(master_doctype):
|
||||
default_tax = frappe.db.get_value(master_doctype, {"is_default": 1})
|
||||
def get_default_taxes_and_charges(master_doctype, company=None):
|
||||
if not company: return {}
|
||||
|
||||
default_tax = frappe.db.get_value(master_doctype,
|
||||
{"is_default": 1, "company": company})
|
||||
|
||||
return {
|
||||
'taxes_and_charges': default_tax,
|
||||
'taxes': get_taxes_and_charges(master_doctype, default_tax)
|
||||
|
@ -8,7 +8,7 @@ from frappe.utils import flt,cint, cstr, getdate
|
||||
|
||||
from erpnext.accounts.party import get_party_details
|
||||
from erpnext.stock.get_item_details import get_conversion_factor
|
||||
from erpnext.buying.utils import validate_for_items
|
||||
from erpnext.buying.utils import validate_for_items, update_last_purchase_rate
|
||||
from erpnext.stock.stock_ledger import get_valuation_rate
|
||||
|
||||
from erpnext.controllers.stock_controller import StockController
|
||||
@ -18,7 +18,10 @@ class BuyingController(StockController):
|
||||
if hasattr(self, "taxes"):
|
||||
self.flags.print_taxes_with_zero_amount = cint(frappe.db.get_single_value("Print Settings",
|
||||
"print_taxes_with_zero_amount"))
|
||||
self.flags.show_inclusive_tax_in_print = self.is_inclusive_tax()
|
||||
|
||||
self.print_templates = {
|
||||
"total": "templates/print_formats/includes/total.html",
|
||||
"taxes": "templates/print_formats/includes/taxes.html"
|
||||
}
|
||||
|
||||
@ -160,6 +163,11 @@ class BuyingController(StockController):
|
||||
if item in self.sub_contracted_items and not item.bom:
|
||||
frappe.throw(_("Please select BOM in BOM field for Item {0}").format(item.item_code))
|
||||
|
||||
if self.doctype == "Purchase Order":
|
||||
for supplied_item in self.get("supplied_items"):
|
||||
if not supplied_item.reserve_warehouse:
|
||||
frappe.throw(_("Reserved Warehouse is mandatory for Item {0} in Raw Materials supplied").format(frappe.bold(supplied_item.rm_item_code)))
|
||||
|
||||
else:
|
||||
for item in self.get("items"):
|
||||
if item.bom:
|
||||
@ -189,8 +197,16 @@ class BuyingController(StockController):
|
||||
def update_raw_materials_supplied(self, item, raw_material_table):
|
||||
bom_items = self.get_items_from_bom(item.item_code, item.bom)
|
||||
raw_materials_cost = 0
|
||||
items = list(set([d.item_code for d in bom_items]))
|
||||
item_wh = frappe._dict(frappe.db.sql("""select item_code, default_warehouse
|
||||
from `tabItem` where name in ({0})""".format(", ".join(["%s"] * len(items))), items))
|
||||
|
||||
for bom_item in bom_items:
|
||||
if self.doctype == "Purchase Order":
|
||||
reserve_warehouse = bom_item.source_warehouse or item_wh.get(bom_item.item_code)
|
||||
if frappe.db.get_value("Warehouse", reserve_warehouse, "company") != self.company:
|
||||
reserve_warehouse = None
|
||||
|
||||
# check if exists
|
||||
exists = 0
|
||||
for d in self.get(raw_material_table):
|
||||
@ -210,6 +226,8 @@ class BuyingController(StockController):
|
||||
rm.rm_item_code = bom_item.item_code
|
||||
rm.stock_uom = bom_item.stock_uom
|
||||
rm.required_qty = required_qty
|
||||
if self.doctype == "Purchase Order" and not rm.reserve_warehouse:
|
||||
rm.reserve_warehouse = reserve_warehouse
|
||||
|
||||
rm.conversion_factor = item.conversion_factor
|
||||
|
||||
@ -261,7 +279,7 @@ class BuyingController(StockController):
|
||||
def get_items_from_bom(self, item_code, bom):
|
||||
bom_items = frappe.db.sql("""select t2.item_code,
|
||||
t2.stock_qty / ifnull(t1.quantity, 1) as qty_consumed_per_unit,
|
||||
t2.rate, t2.stock_uom, t2.name, t2.description
|
||||
t2.rate, t2.stock_uom, t2.name, t2.description, t2.source_warehouse
|
||||
from `tabBOM` t1, `tabBOM Item` t2, tabItem t3
|
||||
where t2.parent = t1.name and t1.item = %s
|
||||
and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
|
||||
@ -336,7 +354,7 @@ class BuyingController(StockController):
|
||||
frappe.get_meta(item_row.doctype).get_label(fieldname), item_row['item_code'])))
|
||||
|
||||
def update_stock_ledger(self, allow_negative_stock=False, via_landed_cost_voucher=False):
|
||||
self.update_ordered_qty()
|
||||
self.update_ordered_and_reserved_qty()
|
||||
|
||||
sl_entries = []
|
||||
stock_items = self.get_stock_items()
|
||||
@ -378,7 +396,7 @@ class BuyingController(StockController):
|
||||
self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock,
|
||||
via_landed_cost_voucher=via_landed_cost_voucher)
|
||||
|
||||
def update_ordered_qty(self):
|
||||
def update_ordered_and_reserved_qty(self):
|
||||
po_map = {}
|
||||
for d in self.get("items"):
|
||||
if self.doctype=="Purchase Receipt" \
|
||||
@ -397,6 +415,8 @@ class BuyingController(StockController):
|
||||
frappe.InvalidStatusError)
|
||||
|
||||
po_obj.update_ordered_qty(po_item_rows)
|
||||
if self.is_subcontracted:
|
||||
po_obj.update_reserved_qty_for_subcontract()
|
||||
|
||||
def make_sl_entries_for_supplier_warehouse(self, sl_entries):
|
||||
if hasattr(self, 'supplied_items'):
|
||||
@ -409,6 +429,18 @@ class BuyingController(StockController):
|
||||
"actual_qty": -1*flt(d.consumed_qty),
|
||||
}))
|
||||
|
||||
def on_submit(self):
|
||||
if self.get('is_return'):
|
||||
return
|
||||
|
||||
update_last_purchase_rate(self, is_submit = 1)
|
||||
|
||||
def on_cancel(self):
|
||||
if self.get('is_return'):
|
||||
return
|
||||
|
||||
update_last_purchase_rate(self, is_submit = 0)
|
||||
|
||||
def validate_schedule_date(self):
|
||||
if not self.schedule_date:
|
||||
self.schedule_date = min([d.schedule_date for d in self.get("items")])
|
||||
@ -418,8 +450,9 @@ class BuyingController(StockController):
|
||||
if not d.schedule_date:
|
||||
d.schedule_date = self.schedule_date
|
||||
|
||||
if d.schedule_date and getdate(d.schedule_date) < getdate(self.transaction_date):
|
||||
frappe.throw(_("Expected Date cannot be before Transaction Date"))
|
||||
if (d.schedule_date and self.transaction_date and
|
||||
getdate(d.schedule_date) < getdate(self.transaction_date)):
|
||||
frappe.throw(_("Row #{0}: Reqd by Date cannot be before Transaction Date").format(d.idx))
|
||||
else:
|
||||
frappe.throw(_("Please enter Schedule Date"))
|
||||
frappe.throw(_("Please enter Reqd by Date"))
|
||||
|
||||
|
@ -56,7 +56,7 @@ def validate_item_variant_attributes(item, args=None):
|
||||
if not args:
|
||||
args = {d.attribute.lower():d.attribute_value for d in item.attributes}
|
||||
|
||||
attribute_values, numeric_values = get_attribute_values()
|
||||
attribute_values, numeric_values = get_attribute_values(item)
|
||||
|
||||
for attribute, value in args.items():
|
||||
if not value:
|
||||
@ -96,16 +96,17 @@ def validate_item_attribute_value(attributes_list, attribute, attribute_value, i
|
||||
frappe.throw(_("Value {0} for Attribute {1} does not exist in the list of valid Item Attribute Values for Item {2}").format(
|
||||
attribute_value, attribute, item), InvalidItemAttributeValueError, title=_('Invalid Attribute'))
|
||||
|
||||
def get_attribute_values():
|
||||
def get_attribute_values(item):
|
||||
if not frappe.flags.attribute_values:
|
||||
attribute_values = {}
|
||||
numeric_values = {}
|
||||
for t in frappe.get_all("Item Attribute Value", fields=["parent", "attribute_value"]):
|
||||
attribute_values.setdefault(t.parent.lower(), []).append(t.attribute_value)
|
||||
|
||||
for t in frappe.get_all('Item Attribute',
|
||||
fields=["name", "from_range", "to_range", "increment"], filters={'numeric_values': 1}):
|
||||
numeric_values[t.name.lower()] = t
|
||||
for t in frappe.get_all('Item Variant Attribute',
|
||||
fields=["attribute", "from_range", "to_range", "increment"],
|
||||
filters={'numeric_values': 1, 'parent': item.variant_of}):
|
||||
numeric_values[t.attribute.lower()] = t
|
||||
|
||||
frappe.flags.attribute_values = attribute_values
|
||||
frappe.flags.numeric_values = numeric_values
|
||||
|
@ -418,6 +418,6 @@ def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters):
|
||||
'where (`tabBatch`.expiry_date >= CURDATE() or `tabBatch`.expiry_date IS NULL)'
|
||||
|
||||
if filters and filters.get('item_code'):
|
||||
query += 'where item = %(item_code)s' % filters
|
||||
query += 'and item = %(item_code)s'
|
||||
|
||||
return frappe.db.sql(query)
|
||||
return frappe.db.sql(query, filters)
|
||||
|
@ -16,7 +16,10 @@ class SellingController(StockController):
|
||||
if hasattr(self, "taxes"):
|
||||
self.flags.print_taxes_with_zero_amount = cint(frappe.db.get_single_value("Print Settings",
|
||||
"print_taxes_with_zero_amount"))
|
||||
self.flags.show_inclusive_tax_in_print = self.is_inclusive_tax()
|
||||
|
||||
self.print_templates = {
|
||||
"total": "templates/print_formats/includes/total.html",
|
||||
"taxes": "templates/print_formats/includes/taxes.html"
|
||||
}
|
||||
|
||||
@ -185,7 +188,10 @@ class SellingController(StockController):
|
||||
'batch_no': cstr(p.batch_no).strip(),
|
||||
'serial_no': cstr(p.serial_no).strip(),
|
||||
'name': d.name,
|
||||
'target_warehouse': p.target_warehouse
|
||||
'target_warehouse': p.target_warehouse,
|
||||
'company': self.company,
|
||||
'voucher_type': self.doctype,
|
||||
'allow_zero_valuation': d.allow_zero_valuation_rate
|
||||
}))
|
||||
else:
|
||||
il.append(frappe._dict({
|
||||
@ -198,7 +204,10 @@ class SellingController(StockController):
|
||||
'batch_no': cstr(d.get("batch_no")).strip(),
|
||||
'serial_no': cstr(d.get("serial_no")).strip(),
|
||||
'name': d.name,
|
||||
'target_warehouse': d.target_warehouse
|
||||
'target_warehouse': d.target_warehouse,
|
||||
'company': self.company,
|
||||
'voucher_type': self.doctype,
|
||||
'allow_zero_valuation': d.allow_zero_valuation_rate
|
||||
}))
|
||||
return il
|
||||
|
||||
@ -293,7 +302,11 @@ class SellingController(StockController):
|
||||
"posting_date": self.posting_date,
|
||||
"posting_time": self.posting_time,
|
||||
"qty": -1*flt(d.qty),
|
||||
"serial_no": d.serial_no
|
||||
"serial_no": d.serial_no,
|
||||
"company": d.company,
|
||||
"voucher_type": d.voucher_type,
|
||||
"voucher_no": d.name,
|
||||
"allow_zero_valuation": d.allow_zero_valuation
|
||||
})
|
||||
target_warehouse_sle.update({
|
||||
"incoming_rate": get_incoming_rate(args)
|
||||
|
@ -70,7 +70,6 @@ class calculate_taxes_and_totals(object):
|
||||
item.net_rate = item.rate
|
||||
item.amount = flt(item.rate * item.qty, item.precision("amount"))
|
||||
item.net_amount = item.amount
|
||||
item.total_weight = flt(item.weight_per_unit * item.qty)
|
||||
|
||||
self._set_in_company_currency(item, ["price_list_rate", "rate", "net_rate", "amount", "net_amount"])
|
||||
|
||||
@ -164,13 +163,12 @@ class calculate_taxes_and_totals(object):
|
||||
return tax.rate
|
||||
|
||||
def calculate_net_total(self):
|
||||
self.doc.total = self.doc.base_total = self.doc.net_total = self.doc.base_net_total = self.doc.total_net_weight= 0.0
|
||||
self.doc.total = self.doc.base_total = self.doc.net_total = self.doc.base_net_total = 0.0
|
||||
for item in self.doc.get("items"):
|
||||
self.doc.total += item.amount
|
||||
self.doc.base_total += item.base_amount
|
||||
self.doc.net_total += item.net_amount
|
||||
self.doc.base_net_total += item.base_net_amount
|
||||
self.doc.total_net_weight += item.total_weight
|
||||
|
||||
self.doc.round_floats_in(self.doc, ["total", "base_total", "net_total", "base_net_total"])
|
||||
|
||||
@ -400,7 +398,8 @@ class calculate_taxes_and_totals(object):
|
||||
|
||||
for tax in self.doc.get("taxes"):
|
||||
if tax.charge_type == "Actual":
|
||||
actual_taxes_dict.setdefault(tax.idx, tax.tax_amount)
|
||||
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:
|
||||
actual_tax_amount = flt(actual_taxes_dict.get(tax.row_id, 0)) * flt(tax.rate) / 100
|
||||
actual_taxes_dict.setdefault(tax.idx, actual_tax_amount)
|
||||
@ -535,7 +534,7 @@ def get_itemised_tax_breakup_html(doc):
|
||||
for tax in doc.taxes:
|
||||
if getattr(tax, "category", None) and tax.category=="Valuation":
|
||||
continue
|
||||
if tax.description not in tax_accounts and tax.tax_amount_after_discount_amount:
|
||||
if tax.description not in tax_accounts:
|
||||
tax_accounts.append(tax.description)
|
||||
|
||||
headers = get_itemised_tax_breakup_header(doc.doctype + " Item", tax_accounts)
|
||||
@ -545,6 +544,7 @@ def get_itemised_tax_breakup_html(doc):
|
||||
|
||||
get_rounded_tax_amount(itemised_tax, doc.precision("tax_amount", "taxes"))
|
||||
|
||||
update_itemised_tax_data(doc)
|
||||
frappe.flags.company = None
|
||||
|
||||
return frappe.render_template(
|
||||
@ -557,6 +557,12 @@ def get_itemised_tax_breakup_html(doc):
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@erpnext.allow_regional
|
||||
def update_itemised_tax_data(doc):
|
||||
#Don't delete this method, used for localization
|
||||
pass
|
||||
|
||||
@erpnext.allow_regional
|
||||
def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
|
||||
return [_("Item"), _("Taxable Amount")] + tax_accounts
|
||||
|
@ -101,7 +101,7 @@ class Lead(SellingController):
|
||||
|
||||
def set_lead_name(self):
|
||||
if not self.lead_name:
|
||||
frappe.db.set_value("Lead", self.name, "lead_name", self.organization_name)
|
||||
frappe.db.set_value("Lead", self.name, "lead_name", self.company_name)
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_customer(source_name, target_doc=None):
|
||||
@ -129,7 +129,6 @@ def _make_customer(source_name, target_doc=None, ignore_permissions=False):
|
||||
}
|
||||
}}, target_doc, set_missing_values, ignore_permissions=ignore_permissions)
|
||||
|
||||
print(doclist)
|
||||
return doclist
|
||||
|
||||
@frappe.whitelist()
|
||||
|
@ -29,7 +29,7 @@
|
||||
"email_id": "test_lead4@example.com",
|
||||
"organization_lead": 1,
|
||||
"lead_name": "_Test Lead 4",
|
||||
"organization_name": "_Test Lead 4",
|
||||
"company_name": "_Test Lead 4",
|
||||
"status": "Open"
|
||||
}
|
||||
]
|
||||
|
@ -232,7 +232,7 @@ def make_quotation(source_name, target_doc=None):
|
||||
quotation.conversion_rate = exchange_rate
|
||||
|
||||
# get default taxes
|
||||
taxes = get_default_taxes_and_charges("Sales Taxes and Charges Template")
|
||||
taxes = get_default_taxes_and_charges("Sales Taxes and Charges Template", quotation.company)
|
||||
if taxes.get('taxes'):
|
||||
quotation.update(taxes)
|
||||
|
||||
|
@ -2,36 +2,43 @@
|
||||
{
|
||||
"asset_name": "Macbook Pro - 1",
|
||||
"item_code": "Computer",
|
||||
"gross_purchase_amount": 100000
|
||||
"gross_purchase_amount": 100000,
|
||||
"asset_owner": "Company"
|
||||
},
|
||||
{
|
||||
"asset_name": "Macbook Air - 1",
|
||||
"item_code": "Computer",
|
||||
"gross_purchase_amount": 60000
|
||||
"gross_purchase_amount": 60000,
|
||||
"asset_owner": "Company"
|
||||
},
|
||||
{
|
||||
"asset_name": "Conferrence Table",
|
||||
"item_code": "Table",
|
||||
"gross_purchase_amount": 30000
|
||||
"gross_purchase_amount": 30000,
|
||||
"asset_owner": "Company"
|
||||
},
|
||||
{
|
||||
"asset_name": "Lunch Table",
|
||||
"item_code": "Table",
|
||||
"gross_purchase_amount": 20000
|
||||
"gross_purchase_amount": 20000,
|
||||
"asset_owner": "Company"
|
||||
},
|
||||
{
|
||||
"asset_name": "ERPNext",
|
||||
"item_code": "ERP",
|
||||
"gross_purchase_amount": 100000
|
||||
"gross_purchase_amount": 100000,
|
||||
"asset_owner": "Company"
|
||||
},
|
||||
{
|
||||
"asset_name": "Chair 1",
|
||||
"item_code": "Chair",
|
||||
"gross_purchase_amount": 10000
|
||||
"gross_purchase_amount": 10000,
|
||||
"asset_owner": "Company"
|
||||
},
|
||||
{
|
||||
"asset_name": "Chair 2",
|
||||
"item_code": "Chair",
|
||||
"gross_purchase_amount": 10000
|
||||
"gross_purchase_amount": 10000,
|
||||
"asset_owner": "Company"
|
||||
}
|
||||
]
|
@ -55,7 +55,7 @@ def complete_setup(domain='Manufacturing'):
|
||||
"fy_start_date": "2015-01-01",
|
||||
"fy_end_date": "2015-12-31",
|
||||
"bank_account": "National Bank",
|
||||
"domain": domain,
|
||||
"domains": [domain],
|
||||
"company_name": data.get(domain).get('company_name'),
|
||||
"chart_of_accounts": "Standard",
|
||||
"company_abbr": ''.join([d[0] for d in data.get(domain).get('company_name').split()]).upper(),
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 377 KiB |
BIN
erpnext/docs/assets/img/human-resources/employee_advance.png
Normal file
BIN
erpnext/docs/assets/img/human-resources/employee_advance.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 172 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user