Compare commits
178 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f92f04bffc | ||
|
|
6592899741 | ||
|
|
06b27757ab | ||
|
|
e21e1ebae2 | ||
|
|
a26bb96d2d | ||
|
|
fbe1563101 | ||
|
|
47a3f639ed | ||
|
|
efb5bf2cfc | ||
|
|
385311c8a2 | ||
|
|
0788ee62c1 | ||
|
|
ec6267e82a | ||
|
|
db05ac2414 | ||
|
|
f862505bf9 | ||
|
|
ea6d7e9b09 | ||
|
|
8f782e71af | ||
|
|
dac204b1e3 | ||
|
|
9c786948d5 | ||
|
|
6f1795cb3d | ||
|
|
01b555edc7 | ||
|
|
20b01873ab | ||
|
|
43accf4c07 | ||
|
|
9239ed5c44 | ||
|
|
713e2b7b62 | ||
|
|
3b6dc141c6 | ||
|
|
e4fb7b1b2f | ||
|
|
9a1bcac576 | ||
|
|
e68b089187 | ||
|
|
d8a372587d | ||
|
|
f04ce3c5a6 | ||
|
|
50f8262ac7 | ||
|
|
e30fadc661 | ||
|
|
f0937bf722 | ||
|
|
4810831678 | ||
|
|
7cdc6fd789 | ||
|
|
03e5ea3a0d | ||
|
|
9d5a07d101 | ||
|
|
b7bc6bd75d | ||
|
|
23a6d05622 | ||
|
|
b969c2cb60 | ||
|
|
c4e71fcc51 | ||
|
|
b8a8fb5877 | ||
|
|
734cf70b43 | ||
|
|
6fe3ac49cf | ||
|
|
e4e69ec027 | ||
|
|
386d9e1613 | ||
|
|
40c60b6182 | ||
|
|
95c998109d | ||
|
|
33bcaa8a07 | ||
|
|
4da2c81641 | ||
|
|
c2595aa902 | ||
|
|
613ef344f3 | ||
|
|
0c1be8df35 | ||
|
|
815ebafa7b | ||
|
|
8f7708ed5b | ||
|
|
1bd9f22add | ||
|
|
f369b5951e | ||
|
|
81995389ac | ||
|
|
fe913c9969 | ||
|
|
18d6162935 | ||
|
|
91d6544958 | ||
|
|
f640ad4389 | ||
|
|
39bc4b2a4c | ||
|
|
d973c1606a | ||
|
|
df9cf2ef8e | ||
|
|
528ab53b3a | ||
|
|
9cd356c7f0 | ||
|
|
de08639d49 | ||
|
|
987009bf35 | ||
|
|
c833cc8432 | ||
|
|
3f22ec9536 | ||
|
|
d643f2b249 | ||
|
|
b739dd24b2 | ||
|
|
c917423b01 | ||
|
|
6a23016f90 | ||
|
|
730f3e7aba | ||
|
|
033ed00c56 | ||
|
|
6c0d9579d2 | ||
|
|
09fc241d59 | ||
|
|
e78ef5f8c8 | ||
|
|
315a5e1b4d | ||
|
|
7909a30008 | ||
|
|
cf80f850bd | ||
|
|
36f2d4f81e | ||
|
|
a7d92bc8f6 | ||
|
|
332729e99e | ||
|
|
18480bdc23 | ||
|
|
4b08f9ad1f | ||
|
|
ea5a32d304 | ||
|
|
c9501eb460 | ||
|
|
d908b99b00 | ||
|
|
6646960e31 | ||
|
|
185c247286 | ||
|
|
a56121a342 | ||
|
|
cc054a5bbc | ||
|
|
aa12d30d5a | ||
|
|
399a4bf201 | ||
|
|
70be24d6f0 | ||
|
|
6ddbb8820a | ||
|
|
6252e935a0 | ||
|
|
5bbc68df8b | ||
|
|
8bd2487533 | ||
|
|
08fb39f1ba | ||
|
|
baef2624a2 | ||
|
|
88fff46ab4 | ||
|
|
f44b5152d2 | ||
|
|
ec2d09c557 | ||
|
|
722b22a834 | ||
|
|
08e2105b09 | ||
|
|
11d565b07c | ||
|
|
a2c9d13f68 | ||
|
|
508542d4d9 | ||
|
|
50ff8471e0 | ||
|
|
78b8cdc3c1 | ||
|
|
2275cd15e6 | ||
|
|
d217387400 | ||
|
|
b9376641af | ||
|
|
ee018b5ae1 | ||
|
|
c41ab8d15b | ||
|
|
7127a8f522 | ||
|
|
acf85dffc5 | ||
|
|
660f3ed0d6 | ||
|
|
d5c83122f2 | ||
|
|
2777f23ace | ||
|
|
ae65172dca | ||
|
|
d261d40c7e | ||
|
|
4b231c2692 | ||
|
|
7e27e32e92 | ||
|
|
ed1b8cfe3f | ||
|
|
99d4ff4a29 | ||
|
|
595dbd6dea | ||
|
|
f979b18ddb | ||
|
|
3ef6e7847e | ||
|
|
2dba3b5e25 | ||
|
|
2cb8c6a867 | ||
|
|
be3aee973c | ||
|
|
c30c342bdf | ||
|
|
f02a0d4d24 | ||
|
|
44f85fed26 | ||
|
|
cd6c00d505 | ||
|
|
e6cd228288 | ||
|
|
ec14c81ebd | ||
|
|
8793b823af | ||
|
|
537301a210 | ||
|
|
f1d8fc3d51 | ||
|
|
20b4666e89 | ||
|
|
84969bdb2d | ||
|
|
705384d8fe | ||
|
|
2123e02eda | ||
|
|
b77a1057ce | ||
|
|
93b1f2ad72 | ||
|
|
9a433ffca1 | ||
|
|
c1162796c5 | ||
|
|
82446bf83e | ||
|
|
c72f8976aa | ||
|
|
c49a3425ef | ||
|
|
50b2278eda | ||
|
|
e1d85f2467 | ||
|
|
3962cded76 | ||
|
|
66360f694e | ||
|
|
5dba950afa | ||
|
|
6a3f51bee2 | ||
|
|
efe1ab742f | ||
|
|
4d32d5301a | ||
|
|
58bc00f954 | ||
|
|
155074479b | ||
|
|
fa1775b6a6 | ||
|
|
764e6ef210 | ||
|
|
f2d89987f5 | ||
|
|
06c92a782a | ||
|
|
f43e49f378 | ||
|
|
ea5ad84c5e | ||
|
|
46f328cbda | ||
|
|
1b9a01b6c3 | ||
|
|
e8ab7b8898 | ||
|
|
ae921ce2c8 | ||
|
|
590d2d524b | ||
|
|
fe11e71084 | ||
|
|
2c76aec119 |
@@ -2,7 +2,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
__version__ = '7.0.17'
|
||||
__version__ = '7.0.33'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
||||
@@ -47,7 +47,7 @@ cur_frm.cscript.account_type = function(doc, cdt, cdn) {
|
||||
|
||||
cur_frm.cscript.add_toolbar_buttons = function(doc) {
|
||||
cur_frm.add_custom_button(__('Chart of Accounts'),
|
||||
function() { frappe.set_route("Tree", "Account"); }, __("View"))
|
||||
function() { frappe.set_route("Tree", "Account"); });
|
||||
|
||||
if (doc.is_group == 1) {
|
||||
cur_frm.add_custom_button(__('Group to Non-Group'),
|
||||
@@ -61,7 +61,7 @@ cur_frm.cscript.add_toolbar_buttons = function(doc) {
|
||||
"company": doc.company
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, __("View"));
|
||||
});
|
||||
|
||||
cur_frm.add_custom_button(__('Non-Group to Group'),
|
||||
function() { cur_frm.cscript.convert_to_group(); }, 'icon-retweet', 'btn-default')
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@@ -65,24 +66,24 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "monthly_distribution",
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Monthly Distribution",
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Monthly Distribution",
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@@ -170,24 +171,25 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "company",
|
||||
"depends_on": "eval:in_list([\"Stop\", \"Warn\"], doc.action_if_accumulated_monthly_budget_exceeded)",
|
||||
"fieldname": "monthly_distribution",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Company",
|
||||
"label": "Monthly Distribution",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"options": "Monthly Distribution",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@@ -271,13 +273,14 @@
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-05-16 15:00:40.233685",
|
||||
"modified": "2016-08-18 14:46:02.653081",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Budget",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt, getdate, add_months, get_last_day
|
||||
from frappe.utils import flt, getdate, add_months, get_last_day, fmt_money
|
||||
from frappe.model.naming import make_autoname
|
||||
from frappe.model.document import Document
|
||||
|
||||
@@ -73,25 +73,30 @@ def validate_expense_against_budget(args):
|
||||
args.posting_date, args.fiscal_year, budget.budget_amount)
|
||||
|
||||
args["month_end_date"] = get_last_day(args.posting_date)
|
||||
|
||||
|
||||
compare_expense_with_budget(args, budget.cost_center,
|
||||
budget_amount, _("Accumulated Monthly"), monthly_action)
|
||||
|
||||
elif yearly_action in ["Stop", "Warn"]:
|
||||
compare_expense_with_budget(args, budget.cost_center,
|
||||
flt(budget.budget_amount), _("Annual"), yearly_action)
|
||||
if yearly_action in ("Stop", "Warn") and monthly_action != "Stop" \
|
||||
and yearly_action != monthly_action:
|
||||
compare_expense_with_budget(args, budget.cost_center,
|
||||
flt(budget.budget_amount), _("Annual"), yearly_action)
|
||||
|
||||
def compare_expense_with_budget(args, cost_center, budget_amount, action_for, action):
|
||||
actual_expense = get_actual_expense(args, cost_center)
|
||||
if actual_expense > budget_amount:
|
||||
diff = actual_expense - budget_amount
|
||||
currency = frappe.db.get_value('Company', frappe.db.get_value('Cost Center',
|
||||
cost_center, 'company'), 'default_currency')
|
||||
|
||||
msg = _("{0} Budget for Account {1} against Cost Center {2} is {3}. It will exceed by {4}").format(_(action_for), args.account, cost_center, budget_amount, diff)
|
||||
msg = _("{0} Budget for Account {1} against Cost Center {2} is {3}. It will exceed by {4}").format(_(action_for),
|
||||
frappe.bold(args.account), frappe.bold(cost_center),
|
||||
frappe.bold(fmt_money(budget_amount, currency=currency)), frappe.bold(fmt_money(diff, currency=currency)))
|
||||
|
||||
if action=="Stop":
|
||||
frappe.throw(msg, BudgetError)
|
||||
else:
|
||||
frappe.msgprint(msg)
|
||||
frappe.msgprint(msg, indicator='orange')
|
||||
|
||||
def get_accumulated_monthly_budget(monthly_distribution, posting_date, fiscal_year, annual_budget):
|
||||
distribution = {}
|
||||
|
||||
@@ -32,8 +32,13 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) {
|
||||
cur_frm.toggle_display('sb1', doc.is_group==0)
|
||||
cur_frm.set_intro(intro_txt);
|
||||
|
||||
cur_frm.add_custom_button(__('Chart of Cost Centers'),
|
||||
function() { frappe.set_route("Tree", "Cost Center"); }, __("View"))
|
||||
if(!cur_frm.doc.__islocal) {
|
||||
cur_frm.add_custom_button(__('Chart of Cost Centers'),
|
||||
function() { frappe.set_route("Tree", "Cost Center"); });
|
||||
|
||||
cur_frm.add_custom_button(__('Budget'),
|
||||
function() { frappe.set_route("List", "Budget", {'cost_center': cur_frm.doc.name}); });
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.parent_cost_center = function(doc, cdt, cdn) {
|
||||
|
||||
@@ -772,6 +772,9 @@ def get_account_balance_and_party_type(account, date, company, debit=None, credi
|
||||
company_currency = get_company_currency(company)
|
||||
account_details = frappe.db.get_value("Account", account, ["account_type", "account_currency"], as_dict=1)
|
||||
|
||||
if not account_details:
|
||||
return
|
||||
|
||||
if account_details.account_type == "Receivable":
|
||||
party_type = "Customer"
|
||||
elif account_details.account_type == "Payable":
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
{% include "erpnext/public/js/controllers/accounts.js" %}
|
||||
|
||||
frappe.ui.form.on('Payment Entry', {
|
||||
onload: function(frm) {
|
||||
@@ -95,13 +96,13 @@ frappe.ui.form.on('Payment Entry', {
|
||||
frm.doc.paid_to_account_currency != company_currency &&
|
||||
frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency));
|
||||
|
||||
frm.toggle_display("base_paid_amount", frm.doc.paid_from_account_currency != company_currency);
|
||||
frm.toggle_display("base_paid_amount", frm.doc.paid_from_account_currency != company_currency);
|
||||
|
||||
frm.toggle_display("base_received_amount", (frm.doc.paid_to_account_currency != company_currency &&
|
||||
frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency));
|
||||
|
||||
frm.toggle_display("received_amount",
|
||||
frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency)
|
||||
frm.toggle_display("received_amount", (frm.doc.payment_type=="Internal Transfer" ||
|
||||
frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency))
|
||||
|
||||
frm.toggle_display(["base_total_allocated_amount"],
|
||||
(frm.doc.paid_amount && frm.doc.received_amount && frm.doc.base_total_allocated_amount &&
|
||||
@@ -257,22 +258,6 @@ frappe.ui.form.on('Payment Entry', {
|
||||
}
|
||||
},
|
||||
|
||||
mode_of_payment: function(frm) {
|
||||
return frappe.call({
|
||||
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_bank_cash_account",
|
||||
args: {
|
||||
"mode_of_payment": frm.doc.mode_of_payment,
|
||||
"company": frm.doc.company
|
||||
},
|
||||
callback: function(r, rt) {
|
||||
if(r.message) {
|
||||
var payment_account_field = frm.doc.payment_type == "Receive" ? "paid_to" : "paid_from";
|
||||
frm.set_value(payment_account_field, r.message['account']);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
paid_from: function(frm) {
|
||||
if(frm.set_party_account_based_on_party) return;
|
||||
|
||||
@@ -414,10 +399,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
|
||||
paid_amount: function(frm) {
|
||||
frm.set_value("base_paid_amount", flt(frm.doc.paid_amount) * flt(frm.doc.source_exchange_rate));
|
||||
|
||||
frm.trigger("reset_received_amount");
|
||||
|
||||
frm.set_paid_amount_based_on_received_amount = false;
|
||||
},
|
||||
|
||||
received_amount: function(frm) {
|
||||
@@ -436,22 +418,19 @@ frappe.ui.form.on('Payment Entry', {
|
||||
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
|
||||
else
|
||||
frm.events.set_difference_amount(frm);
|
||||
|
||||
frm.set_paid_amount_based_on_received_amount = false;
|
||||
},
|
||||
|
||||
reset_received_amount: function(frm) {
|
||||
if(!frm.set_paid_amount_based_on_received_amount &&
|
||||
(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) {
|
||||
|
||||
// var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
|
||||
// function(d) { return d.amount}));
|
||||
//
|
||||
// var received_amount = frm.doc.paid_amount +
|
||||
// flt(total_deductions) / flt(frm.doc.source_exchange_rate);
|
||||
//
|
||||
frm.set_value("received_amount", frm.doc.paid_amount);
|
||||
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
|
||||
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
|
||||
}
|
||||
|
||||
if(frm.doc.payment_type == "Receive")
|
||||
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.paid_amount);
|
||||
else
|
||||
@@ -607,11 +586,18 @@ frappe.ui.form.on('Payment Entry', {
|
||||
if(frm.doc.party) {
|
||||
var party_amount = frm.doc.payment_type=="Receive" ?
|
||||
frm.doc.paid_amount : frm.doc.received_amount;
|
||||
|
||||
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
|
||||
function(d) { return flt(d.amount) }));
|
||||
|
||||
if(frm.doc.total_allocated_amount < party_amount)
|
||||
unallocated_amount = party_amount - frm.doc.total_allocated_amount;
|
||||
if(frm.doc.total_allocated_amount < party_amount) {
|
||||
if(frm.doc.payment_type == "Receive") {
|
||||
unallocated_amount = party_amount - (frm.doc.total_allocated_amount - total_deductions);
|
||||
} else {
|
||||
unallocated_amount = party_amount - (frm.doc.total_allocated_amount + total_deductions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frm.set_value("unallocated_amount", unallocated_amount);
|
||||
|
||||
var difference_amount = 0;
|
||||
|
||||
@@ -247,8 +247,13 @@ class PaymentEntry(AccountsController):
|
||||
if self.party:
|
||||
party_amount = self.paid_amount if self.payment_type=="Receive" else self.received_amount
|
||||
|
||||
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
|
||||
|
||||
if self.total_allocated_amount < party_amount:
|
||||
self.unallocated_amount = party_amount - self.total_allocated_amount
|
||||
if self.payment_type == "Receive":
|
||||
self.unallocated_amount = party_amount - (self.total_allocated_amount - total_deductions)
|
||||
else:
|
||||
self.unallocated_amount = party_amount - (self.total_allocated_amount + total_deductions)
|
||||
|
||||
def set_difference_amount(self):
|
||||
base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)
|
||||
|
||||
@@ -1,21 +1,37 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
//========================== On Load =================================================
|
||||
cur_frm.cscript.onload = function(doc, cdt, cdn) {
|
||||
if (!doc.transaction_date) doc.transaction_date = dateutil.obj_to_str(new Date());
|
||||
}
|
||||
|
||||
|
||||
// ***************** Get Account Head *****************
|
||||
cur_frm.fields_dict['closing_account_head'].get_query = function(doc, cdt, cdn) {
|
||||
return {
|
||||
filters: [
|
||||
['Account', 'company', '=', doc.company],
|
||||
['Account', 'is_group', '=', '0'],
|
||||
['Account', 'freeze_account', '=', 'No'],
|
||||
['Account', 'root_type', 'in', 'Liability, Equity']
|
||||
]
|
||||
frappe.ui.form.on('Period Closing Voucher', {
|
||||
onload: function(frm) {
|
||||
if (!frm.doc.transaction_date) frm.doc.transaction_date = dateutil.obj_to_str(new Date());
|
||||
},
|
||||
|
||||
setup: function(frm) {
|
||||
frm.set_query("closing_account_head", function() {
|
||||
return {
|
||||
filters: [
|
||||
['Account', 'company', '=', frm.doc.company],
|
||||
['Account', 'is_group', '=', '0'],
|
||||
['Account', 'freeze_account', '=', 'No'],
|
||||
['Account', 'root_type', 'in', 'Liability, Equity']
|
||||
]
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
if(frm.doc.docstatus==1) {
|
||||
frm.add_custom_button(__('Ledger'), function() {
|
||||
frappe.route_options = {
|
||||
"voucher_no": frm.doc.name,
|
||||
"from_date": frm.doc.posting_date,
|
||||
"to_date": frm.doc.posting_date,
|
||||
"company": frm.doc.company,
|
||||
group_by_voucher: 0
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
}, "icon-table");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
@@ -55,9 +55,8 @@ class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
if random_expense_account:
|
||||
# Check posted value for teh above random_expense_account
|
||||
gle_for_random_expense_account = frappe.db.sql("""
|
||||
select debit - credit as amount,
|
||||
debit_in_account_currency - credit_in_account_currency
|
||||
as amount_in_account_currency
|
||||
select sum(debit - credit) as amount,
|
||||
sum(debit_in_account_currency - credit_in_account_currency) as amount_in_account_currency
|
||||
from `tabGL Entry`
|
||||
where voucher_type='Period Closing Voucher' and voucher_no=%s and account =%s""",
|
||||
(pcv.name, random_expense_account[0].account), as_dict=True)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
{% include "erpnext/public/js/controllers/accounts.js" %}
|
||||
|
||||
frappe.ui.form.on("POS Profile", "onload", function(frm) {
|
||||
frm.set_query("selling_price_list", function() {
|
||||
return { filters: { selling: 1 } };
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@@ -117,6 +118,32 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "campaign",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Campaign",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Campaign",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -689,6 +716,32 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "account_for_change_amount",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Account for Change Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -832,7 +885,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-06-13 21:20:13.805101",
|
||||
"modified": "2016-08-17 15:12:56.713748",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Profile",
|
||||
@@ -879,7 +932,7 @@
|
||||
"write": 0
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
|
||||
@@ -232,7 +232,8 @@ cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) {
|
||||
|
||||
cur_frm.fields_dict['items'].grid.get_field("item_code").get_query = function(doc, cdt, cdn) {
|
||||
return {
|
||||
query: "erpnext.controllers.queries.item_query"
|
||||
query: "erpnext.controllers.queries.item_query",
|
||||
filters: {'is_purchase_item': 1}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
@@ -117,6 +118,33 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "",
|
||||
"fieldname": "bill_no",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Supplier Invoice No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "bill_no",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -142,6 +170,32 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "0",
|
||||
"fieldname": "is_return",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Is Return",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -198,19 +252,18 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"description": "",
|
||||
"fieldname": "bill_no",
|
||||
"fieldtype": "Data",
|
||||
"fieldname": "due_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Supplier Invoice No",
|
||||
"label": "Due Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "bill_no",
|
||||
"oldfieldtype": "Data",
|
||||
"oldfieldname": "due_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
@@ -299,32 +352,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"default": "0",
|
||||
"fieldname": "is_return",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Is Return",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -2497,32 +2524,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "due_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Due Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "due_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -3031,7 +3032,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2016-06-30 13:40:39.440648",
|
||||
"modified": "2016-08-24 12:50:15.777689",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
|
||||
@@ -301,7 +301,7 @@ class PurchaseInvoice(BuyingController):
|
||||
asset.flags.ignore_validate_update_after_submit = True
|
||||
asset.save()
|
||||
|
||||
def make_gl_entries(self, repost_future_gle=False):
|
||||
def make_gl_entries(self, repost_future_gle=True):
|
||||
self.auto_accounting_for_stock = \
|
||||
cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
|
||||
|
||||
@@ -497,6 +497,18 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
i += 1
|
||||
|
||||
if self.update_stock and valuation_tax:
|
||||
for cost_center, amount in valuation_tax.items():
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.expenses_included_in_valuation,
|
||||
"cost_center": cost_center,
|
||||
"against": self.supplier,
|
||||
"credit": amount,
|
||||
"remarks": self.remarks or "Accounting Entry for Stock"
|
||||
})
|
||||
)
|
||||
|
||||
def make_payment_gl_entries(self, gl_entries):
|
||||
# Make Cash GL Entries
|
||||
if cint(self.is_paid) and self.cash_bank_account and self.paid_amount:
|
||||
|
||||
@@ -18,3 +18,13 @@ frappe.ui.form.on("Purchase Taxes and Charges", "add_deduct_tax", function(doc,
|
||||
}
|
||||
refresh_field('add_deduct_tax', d.name, 'taxes');
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Purchase Taxes and Charges", "category", function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
|
||||
if (d.category != 'Total' && d.add_deduct_tax == 'Deduct') {
|
||||
msgprint(__("Cannot deduct when category is for 'Valuation' or 'Vaulation and Total'"));
|
||||
d.add_deduct_tax = '';
|
||||
}
|
||||
refresh_field('add_deduct_tax', d.name, 'taxes');
|
||||
});
|
||||
|
||||
@@ -13,9 +13,9 @@ from erpnext.controllers.accounts_controller import get_taxes_and_charges
|
||||
@frappe.whitelist()
|
||||
def get_pos_data():
|
||||
doc = frappe.new_doc('Sales Invoice')
|
||||
doc.update_stock = 1;
|
||||
doc.is_pos = 1;
|
||||
pos_profile = get_pos_profile(doc.company) or {}
|
||||
doc.update_stock = pos_profile.get('update_stock')
|
||||
|
||||
if pos_profile.get('name'):
|
||||
pos_profile = frappe.get_doc('POS Profile', pos_profile.get('name'))
|
||||
@@ -35,7 +35,6 @@ def get_pos_data():
|
||||
'customers': get_customers(pos_profile, doc),
|
||||
'pricing_rules': get_pricing_rules(doc),
|
||||
'print_template': print_template,
|
||||
'write_off_account': pos_profile.get('write_off_account'),
|
||||
'meta': {
|
||||
'invoice': frappe.get_meta('Sales Invoice'),
|
||||
'items': frappe.get_meta('Sales Invoice Item'),
|
||||
@@ -45,7 +44,12 @@ def get_pos_data():
|
||||
|
||||
def update_pos_profile_data(doc, pos_profile):
|
||||
company_data = frappe.db.get_value('Company', doc.company, '*', as_dict=1)
|
||||
doc.campaign = pos_profile.get('campaign')
|
||||
|
||||
doc.write_off_account = pos_profile.get('write_off_account') or \
|
||||
company_data.write_off_account
|
||||
doc.change_amount_account = pos_profile.get('change_amount_account') or \
|
||||
company_data.default_cash_account
|
||||
doc.taxes_and_charges = pos_profile.get('taxes_and_charges')
|
||||
if doc.taxes_and_charges:
|
||||
update_tax_table(doc)
|
||||
@@ -54,7 +58,8 @@ def update_pos_profile_data(doc, pos_profile):
|
||||
doc.conversion_rate = 1.0
|
||||
if doc.currency != company_data.default_currency:
|
||||
doc.conversion_rate = get_exchange_rate(doc.currency, company_data.default_currency)
|
||||
doc.selling_price_list = pos_profile.get('selling_price_list') or frappe.db.get_value('Selling Settings', None, 'selling_price_list')
|
||||
doc.selling_price_list = pos_profile.get('selling_price_list') or \
|
||||
frappe.db.get_value('Selling Settings', None, 'selling_price_list')
|
||||
doc.naming_series = pos_profile.get('naming_series') or 'SINV-'
|
||||
doc.letter_head = pos_profile.get('letter_head') or company_data.default_letter_head
|
||||
doc.ignore_pricing_rule = pos_profile.get('ignore_pricing_rule') or 0
|
||||
@@ -91,7 +96,7 @@ def update_multi_mode_option(doc, pos_profile):
|
||||
|
||||
def get_mode_of_payment(doc):
|
||||
return frappe.db.sql(""" select mpa.default_account, mpa.parent, mp.type as type from `tabMode of Payment Account` mpa,
|
||||
`tabMode of Payment` mp where mpa.parent = mp.name and company = %(company)s""", {'company': doc.company}, as_dict=1)
|
||||
`tabMode of Payment` mp where mpa.parent = mp.name and mpa.company = %(company)s""", {'company': doc.company}, as_dict=1)
|
||||
|
||||
def update_tax_table(doc):
|
||||
taxes = get_taxes_and_charges('Sales Taxes and Charges Template', doc.taxes_and_charges)
|
||||
@@ -100,7 +105,7 @@ def update_tax_table(doc):
|
||||
|
||||
def get_items(doc, pos_profile):
|
||||
item_list = []
|
||||
for item in frappe.get_all("Item", fields=["*"], filters={'disabled': 0, 'has_variants': 0}):
|
||||
for item in frappe.get_all("Item", fields=["*"], filters={'disabled': 0, 'has_variants': 0, 'is_sales_item': 1}):
|
||||
item_doc = frappe.get_doc('Item', item.name)
|
||||
if item_doc.taxes:
|
||||
item.taxes = json.dumps(dict(([d.tax_type, d.tax_rate] for d in
|
||||
@@ -108,13 +113,14 @@ def get_items(doc, pos_profile):
|
||||
|
||||
item.price_list_rate = frappe.db.get_value('Item Price', {'item_code': item.name,
|
||||
'price_list': doc.selling_price_list}, 'price_list_rate') or 0
|
||||
item.default_warehouse = pos_profile.get('warehouse') or item.default_warehouse or None
|
||||
item.default_warehouse = pos_profile.get('warehouse') or \
|
||||
get_item_warehouse_for_company(doc.company, item.default_warehouse) or None
|
||||
item.expense_account = pos_profile.get('expense_account') or item.expense_account
|
||||
item.income_account = pos_profile.get('income_account') or item_doc.income_account
|
||||
item.cost_center = pos_profile.get('cost_center') or item_doc.selling_cost_center
|
||||
item.actual_qty = frappe.db.get_value('Bin', {'item_code': item.name,
|
||||
'warehouse': item.default_warehouse}, 'actual_qty') or 0
|
||||
item.serial_nos = get_serial_nos(item, pos_profile)
|
||||
item.serial_nos = get_serial_nos(item, pos_profile, doc.company)
|
||||
item.batch_nos = frappe.db.sql_list("""select name from `tabBatch` where ifnull(expiry_date, '4000-10-10') > curdate()
|
||||
and item = %(item_code)s""", {'item_code': item.item_code})
|
||||
|
||||
@@ -122,13 +128,19 @@ def get_items(doc, pos_profile):
|
||||
|
||||
return item_list
|
||||
|
||||
def get_serial_nos(item, pos_profile):
|
||||
def get_item_warehouse_for_company(company, warehouse):
|
||||
if frappe.db.get_value('Warehouse', warehouse, 'company') != company:
|
||||
warehouse = None
|
||||
return warehouse
|
||||
|
||||
def get_serial_nos(item, pos_profile, company):
|
||||
cond = "1=1"
|
||||
if pos_profile.get('update_stock') and pos_profile.get('warehouse'):
|
||||
cond = "warehouse = '{0}'".format(pos_profile.get('warehouse'))
|
||||
|
||||
serial_nos = frappe.db.sql("""select name, warehouse from `tabSerial No` where {0}
|
||||
and item_code = %(item_code)s""".format(cond), {'item_code': item.item_code}, as_dict=1)
|
||||
and item_code = %(item_code)s and company = %(company)s
|
||||
""".format(cond), {'item_code': item.item_code, 'company': company}, as_dict=1)
|
||||
|
||||
serial_no_list = {}
|
||||
for serial_no in serial_nos:
|
||||
@@ -150,10 +162,11 @@ def get_customers(pos_profile, doc):
|
||||
def get_pricing_rules(doc):
|
||||
pricing_rules = ""
|
||||
if doc.ignore_pricing_rule == 0:
|
||||
pricing_rules = frappe.db.sql(""" Select * from `tabPricing Rule` where docstatus < 2 and disable = 0
|
||||
and selling = 1 and ifnull(company, '') in (%(company)s, '') and
|
||||
ifnull(for_price_list, '') in (%(price_list)s, '') and %(date)s between
|
||||
ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31') order by priority desc, name desc""",
|
||||
pricing_rules = frappe.db.sql(""" Select * from `tabPricing Rule` where docstatus < 2
|
||||
and ifnull(for_price_list, '') in (%(price_list)s, '') and selling = 1
|
||||
and ifnull(company, '') in (%(company)s, '') and disable = 0 and %(date)s
|
||||
between ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31')
|
||||
order by priority desc, name desc""",
|
||||
{'company': doc.company, 'price_list': doc.selling_price_list, 'date': nowdate()}, as_dict=1)
|
||||
return pricing_rules
|
||||
|
||||
@@ -166,17 +179,23 @@ def make_invoice(doc_list):
|
||||
|
||||
for docs in doc_list:
|
||||
for name, doc in docs.items():
|
||||
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
|
||||
validate_customer(doc)
|
||||
validate_item(doc)
|
||||
if not frappe.db.exists('Sales Invoice',
|
||||
{'offline_pos_name': name, 'docstatus': ("<", "2")}):
|
||||
validate_records(doc)
|
||||
si_doc = frappe.new_doc('Sales Invoice')
|
||||
si_doc.offline_pos_name = name
|
||||
si_doc.update(doc)
|
||||
submit_invoice(si_doc, name)
|
||||
name_list.append(name)
|
||||
else:
|
||||
name_list.append(name)
|
||||
|
||||
return name_list
|
||||
|
||||
def validate_records(doc):
|
||||
validate_customer(doc)
|
||||
validate_item(doc)
|
||||
|
||||
def validate_customer(doc):
|
||||
if not frappe.db.exists('Customer', doc.get('customer')):
|
||||
customer_doc = frappe.new_doc('Customer')
|
||||
@@ -188,8 +207,6 @@ def validate_customer(doc):
|
||||
frappe.db.commit()
|
||||
doc['customer'] = customer_doc.name
|
||||
|
||||
return doc
|
||||
|
||||
def validate_item(doc):
|
||||
for item in doc.get('items'):
|
||||
if not frappe.db.exists('Item', item.get('item_code')):
|
||||
@@ -214,9 +231,10 @@ def submit_invoice(si_doc, name):
|
||||
save_invoice(e, si_doc, name)
|
||||
|
||||
def save_invoice(e, si_doc, name):
|
||||
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
|
||||
si_doc.docstatus = 0
|
||||
si_doc.name = ''
|
||||
si_doc.save(ignore_permissions=True)
|
||||
si_doc.flags.ignore_mandatory = True
|
||||
si_doc.insert()
|
||||
make_scheduler_log(e, si_doc.name)
|
||||
|
||||
def make_scheduler_log(e, sales_invoice):
|
||||
|
||||
@@ -267,6 +267,16 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
|
||||
amount: function(){
|
||||
this.write_off_outstanding_amount_automatically()
|
||||
},
|
||||
|
||||
change_amount: function(){
|
||||
if(this.frm.doc.paid_amount > this.frm.doc.grand_total){
|
||||
this.calculate_write_off_amount()
|
||||
}else {
|
||||
this.frm.set_value("change_amount", 0.0)
|
||||
}
|
||||
|
||||
this.frm.refresh_fields();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -458,7 +468,7 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
frappe.ui.form.on('Sales Invoice Timesheet', {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@@ -1135,7 +1136,7 @@
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "2",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
@@ -2199,32 +2200,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "base_change_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Base Change Amount (Company Currency)",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -2277,6 +2252,80 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "section_break_88",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "base_change_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Base Change Amount (Company Currency)",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "column_break_90",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -2296,7 +2345,33 @@
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"fieldname": "account_for_change_amount",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Account for Change Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
@@ -3676,7 +3751,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2016-07-07 13:40:27.977803",
|
||||
"modified": "2016-08-17 15:12:39.357372",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
||||
@@ -61,11 +61,12 @@ class SalesInvoice(SellingController):
|
||||
self.clear_unallocated_advances("Sales Invoice Advance", "advances")
|
||||
self.add_remarks()
|
||||
self.validate_write_off_account()
|
||||
self.validate_account_for_change_amount()
|
||||
self.validate_fixed_asset()
|
||||
self.set_income_account_for_fixed_assets()
|
||||
|
||||
# if cint(self.is_pos):
|
||||
# self.validate_pos()
|
||||
if cint(self.is_pos):
|
||||
self.validate_pos()
|
||||
|
||||
if cint(self.update_stock):
|
||||
self.validate_dropship_item()
|
||||
@@ -218,6 +219,20 @@ class SalesInvoice(SellingController):
|
||||
timesheet.set_status()
|
||||
timesheet.save()
|
||||
|
||||
def on_update(self):
|
||||
self.set_paid_amount()
|
||||
|
||||
def set_paid_amount(self):
|
||||
paid_amount = 0.0
|
||||
base_paid_amount = 0.0
|
||||
for data in self.payments:
|
||||
data.base_amount = flt(data.amount*self.conversion_rate, self.precision("base_paid_amount"))
|
||||
paid_amount += data.amount
|
||||
base_paid_amount += data.base_amount
|
||||
|
||||
self.paid_amount = paid_amount
|
||||
self.base_paid_amount = base_paid_amount
|
||||
|
||||
def validate_time_sheets_are_submitted(self):
|
||||
for data in self.timesheets:
|
||||
if data.time_sheet:
|
||||
@@ -233,12 +248,22 @@ class SalesInvoice(SellingController):
|
||||
from erpnext.stock.get_item_details import get_pos_profile_item_details, get_pos_profile
|
||||
pos = get_pos_profile(self.company)
|
||||
|
||||
if not self.get('payments'):
|
||||
pos_profile = frappe.get_doc('POS Profile', pos.name) if pos else None
|
||||
update_multi_mode_option(self, pos_profile)
|
||||
|
||||
if not self.account_for_change_amount:
|
||||
self.account_for_change_amount = frappe.db.get_value('Company', self.company, 'default_cash_account')
|
||||
|
||||
if pos:
|
||||
if not for_validate and not self.customer:
|
||||
self.customer = pos.customer
|
||||
self.mode_of_payment = pos.mode_of_payment
|
||||
# self.set_customer_defaults()
|
||||
|
||||
if pos.get('account_for_change_amount'):
|
||||
self.account_for_change_amount = pos.get('account_for_change_amount')
|
||||
|
||||
for fieldname in ('territory', 'naming_series', 'currency', 'taxes_and_charges', 'letter_head', 'tc_name',
|
||||
'selling_price_list', 'company', 'select_print_heading', 'cash_bank_account',
|
||||
'write_off_account', 'write_off_cost_center'):
|
||||
@@ -265,10 +290,6 @@ class SalesInvoice(SellingController):
|
||||
if self.taxes_and_charges and not len(self.get("taxes")):
|
||||
self.set_taxes()
|
||||
|
||||
if not self.get('payments'):
|
||||
pos_profile = frappe.get_doc('POS Profile', pos.name)
|
||||
update_multi_mode_option(self, pos_profile)
|
||||
|
||||
return pos
|
||||
|
||||
def get_company_abbr(self):
|
||||
@@ -349,11 +370,8 @@ class SalesInvoice(SellingController):
|
||||
throw(_("Customer {0} does not belong to project {1}").format(self.customer,self.project))
|
||||
|
||||
def validate_pos(self):
|
||||
if not self.cash_bank_account and flt(self.paid_amount):
|
||||
frappe.throw(_("Cash or Bank Account is mandatory for making payment entry"))
|
||||
|
||||
if flt(self.paid_amount) + flt(self.write_off_amount) \
|
||||
- flt(self.grand_total) > 1/(10**(self.precision("grand_total") + 1)):
|
||||
- flt(self.grand_total) > 1/(10**(self.precision("grand_total") + 1)) and self.is_return:
|
||||
frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total"""))
|
||||
|
||||
|
||||
@@ -374,11 +392,16 @@ class SalesInvoice(SellingController):
|
||||
if d.delivery_note:
|
||||
msgprint(_("Stock cannot be updated against Delivery Note {0}").format(d.delivery_note), raise_exception=1)
|
||||
|
||||
|
||||
def validate_write_off_account(self):
|
||||
if flt(self.write_off_amount) and not self.write_off_account:
|
||||
self.write_off_account = frappe.db.get_value('Company', self.company, 'write_off_account')
|
||||
|
||||
if flt(self.write_off_amount) and not self.write_off_account:
|
||||
msgprint(_("Please enter Write Off Account"), raise_exception=1)
|
||||
|
||||
def validate_account_for_change_amount(self):
|
||||
if flt(self.change_amount) and not self.account_for_change_amount:
|
||||
msgprint(_("Please enter Account for Change Amount"), raise_exception=1)
|
||||
|
||||
def validate_c_form(self):
|
||||
""" Blank C-form no if C-form applicable marked as 'No'"""
|
||||
@@ -502,7 +525,7 @@ class SalesInvoice(SellingController):
|
||||
gl_entries = merge_similar_entries(gl_entries)
|
||||
|
||||
self.make_pos_gl_entries(gl_entries)
|
||||
self.make_gle_for_change(gl_entries)
|
||||
self.make_gle_for_change_amount(gl_entries)
|
||||
|
||||
self.make_write_off_gl_entry(gl_entries)
|
||||
|
||||
@@ -576,46 +599,44 @@ class SalesInvoice(SellingController):
|
||||
gl_entries += super(SalesInvoice, self).get_gl_entries()
|
||||
|
||||
def make_pos_gl_entries(self, gl_entries):
|
||||
if cint(self.is_pos) and self.paid_amount:
|
||||
if cint(self.is_pos):
|
||||
for payment_mode in self.payments:
|
||||
if payment_mode.base_amount > 0:
|
||||
# POS, make payment entries
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.debit_to,
|
||||
"party_type": "Customer",
|
||||
"party": self.customer,
|
||||
"against": payment_mode.account,
|
||||
"credit": payment_mode.base_amount,
|
||||
"credit_in_account_currency": payment_mode.base_amount \
|
||||
if self.party_account_currency==self.company_currency \
|
||||
else payment_mode.amount,
|
||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
}, self.party_account_currency)
|
||||
)
|
||||
|
||||
payment_mode_account_currency = get_account_currency(payment_mode.account)
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": payment_mode.account,
|
||||
"against": self.customer,
|
||||
"debit": payment_mode.base_amount,
|
||||
"debit_in_account_currency": payment_mode.base_amount \
|
||||
if payment_mode_account_currency==self.company_currency else payment_mode.amount
|
||||
}, payment_mode_account_currency)
|
||||
)
|
||||
|
||||
def make_gle_for_change(self, gl_entries):
|
||||
if cint(self.is_pos) and self.change_amount:
|
||||
cash_account = self.get_cash_account()
|
||||
if cash_account:
|
||||
# POS, make payment entries
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.debit_to,
|
||||
"party_type": "Customer",
|
||||
"party": self.customer,
|
||||
"against": cash_account,
|
||||
"against": payment_mode.account,
|
||||
"credit": payment_mode.base_amount,
|
||||
"credit_in_account_currency": payment_mode.base_amount \
|
||||
if self.party_account_currency==self.company_currency \
|
||||
else payment_mode.amount,
|
||||
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||
"against_voucher_type": self.doctype,
|
||||
}, self.party_account_currency)
|
||||
)
|
||||
|
||||
payment_mode_account_currency = get_account_currency(payment_mode.account)
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": payment_mode.account,
|
||||
"against": self.customer,
|
||||
"debit": payment_mode.base_amount,
|
||||
"debit_in_account_currency": payment_mode.base_amount \
|
||||
if payment_mode_account_currency==self.company_currency else payment_mode.amount
|
||||
}, payment_mode_account_currency)
|
||||
)
|
||||
|
||||
def make_gle_for_change_amount(self, gl_entries):
|
||||
if cint(self.is_pos) and self.change_amount:
|
||||
if self.account_for_change_amount:
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.debit_to,
|
||||
"party_type": "Customer",
|
||||
"party": self.customer,
|
||||
"against": self.account_for_change_amount,
|
||||
"debit": flt(self.base_change_amount),
|
||||
"debit_in_account_currency": flt(self.base_change_amount) \
|
||||
if self.party_account_currency==self.company_currency else flt(self.change_amount),
|
||||
@@ -626,22 +647,13 @@ class SalesInvoice(SellingController):
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": cash_account,
|
||||
"account": self.account_for_change_amount,
|
||||
"against": self.customer,
|
||||
"credit": self.base_change_amount
|
||||
})
|
||||
)
|
||||
|
||||
|
||||
def get_cash_account(self):
|
||||
cash_account = [d.account for d in self.payments if d.type=="Cash"]
|
||||
if cash_account:
|
||||
cash_account = cash_account[0]
|
||||
else:
|
||||
cash_account = frappe.db.get_value("Account",
|
||||
filters={"company": self.company, "account_type": "Cash", "is_group": 0})
|
||||
|
||||
return cash_account
|
||||
else:
|
||||
frappe.throw(_("Select change amount account"), title="Mandatory Field")
|
||||
|
||||
def make_write_off_gl_entry(self, gl_entries):
|
||||
# write off entries, applicable if only pos
|
||||
|
||||
@@ -455,6 +455,25 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
self.pos_gl_entry(si, pos, 300)
|
||||
|
||||
def test_pos_change_amount(self):
|
||||
set_perpetual_inventory()
|
||||
self.make_pos_profile()
|
||||
|
||||
self._insert_purchase_receipt()
|
||||
pos = copy.deepcopy(test_records[1])
|
||||
pos["is_pos"] = 1
|
||||
pos["update_stock"] = 1
|
||||
pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300},
|
||||
{'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 340}]
|
||||
|
||||
si = frappe.copy_doc(pos)
|
||||
si.change_amount = 5.0
|
||||
si.insert()
|
||||
si.submit()
|
||||
|
||||
self.assertEquals(si.grand_total, 630.0)
|
||||
self.assertEquals(si.write_off_amount, -5)
|
||||
|
||||
def test_make_pos_invoice(self):
|
||||
from erpnext.accounts.doctype.sales_invoice.pos import make_invoice
|
||||
|
||||
|
||||
@@ -177,11 +177,20 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
doc = JSON.parse(localStorage.getItem('doc'))
|
||||
if(this.frm.doc.payments.length == 0){
|
||||
this.frm.doc.payments = doc.payments;
|
||||
this.calculate_outstanding_amount();
|
||||
}
|
||||
|
||||
if(this.frm.doc.customer){
|
||||
this.party_field.$input.val(this.frm.doc.customer);
|
||||
}
|
||||
|
||||
if(!this.frm.doc.write_off_account){
|
||||
this.frm.doc.write_off_account = doc.write_off_account
|
||||
}
|
||||
|
||||
if(!this.frm.doc.account_for_change_amount){
|
||||
this.frm.doc.account_for_change_amount = doc.account_for_change_amount
|
||||
}
|
||||
},
|
||||
|
||||
get_invoice_doc: function(si_docs){
|
||||
@@ -208,7 +217,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
window.meta = r.message.meta;
|
||||
window.print_template = r.message.print_template;
|
||||
me.default_customer = r.message.default_customer || null;
|
||||
me.write_off_account = r.message.write_off_account;
|
||||
localStorage.setItem('doc', JSON.stringify(r.message.doc));
|
||||
if(callback){
|
||||
callback();
|
||||
@@ -420,19 +428,25 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
}
|
||||
|
||||
key = this.search.$input.val().toLowerCase();
|
||||
search_status = true
|
||||
|
||||
if(key){
|
||||
return $.grep(window.items, function(item){
|
||||
if(in_list(item.batch_nos, me.search.$input.val())){
|
||||
return me.item_batch_no[item.item_code] = me.search.$input.val()
|
||||
} else if((item.item_code.toLowerCase().match(key)) ||
|
||||
(item.item_name.toLowerCase().match(key)) || (item.item_group.toLowerCase().match(key))){
|
||||
return true
|
||||
}else if(item.barcode == me.search.$input.val()){
|
||||
return item.barcode == me.search.$input.val();
|
||||
} else if (in_list(Object.keys(item.serial_nos), me.search.$input.val())){
|
||||
me.item_serial_no[item.item_code] = [me.search.$input.val(), item.serial_nos[me.search.$input.val()]]
|
||||
return true
|
||||
if(search_status){
|
||||
if(in_list(item.batch_nos, me.search.$input.val())){
|
||||
search_status = false;
|
||||
return me.item_batch_no[item.item_code] = me.search.$input.val()
|
||||
} else if(in_list(Object.keys(item.serial_nos), me.search.$input.val())) {
|
||||
search_status = false;
|
||||
me.item_serial_no[item.item_code] = [me.search.$input.val(), item.serial_nos[me.search.$input.val()]]
|
||||
return true
|
||||
} else if(item.barcode == me.search.$input.val()) {
|
||||
search_status = false;
|
||||
return item.barcode == me.search.$input.val();
|
||||
} else if((item.item_code.toLowerCase().match(key)) ||
|
||||
(item.item_name.toLowerCase().match(key)) || (item.item_group.toLowerCase().match(key))) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
})
|
||||
}else{
|
||||
@@ -478,11 +492,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
|
||||
this.remove_item = []
|
||||
$.each(this.frm.doc["items"] || [], function(i, d) {
|
||||
if (d.item_code == item_code && d.serial_no
|
||||
&& field == 'qty' && cint(value) != value) {
|
||||
d.qty = 0.0;
|
||||
me.refresh();
|
||||
frappe.throw(__("Serial no item cannot be a fraction"))
|
||||
if(d.serial_no){
|
||||
me.validate_serial_no_qty(d, item_code, field, value)
|
||||
}
|
||||
|
||||
if (d.item_code == item_code) {
|
||||
@@ -498,7 +509,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
this.remove_zero_qty_item();
|
||||
}
|
||||
|
||||
this.refresh();
|
||||
this.update_paid_amount_status(false)
|
||||
},
|
||||
|
||||
remove_zero_qty_item: function(){
|
||||
@@ -580,7 +591,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
if (!caught)
|
||||
this.add_new_item_to_grid();
|
||||
|
||||
this.refresh();
|
||||
this.update_paid_amount_status(false)
|
||||
},
|
||||
|
||||
add_new_item_to_grid: function() {
|
||||
@@ -605,6 +616,14 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
? this.item_serial_no[this.child.item_code][0] : '');
|
||||
},
|
||||
|
||||
update_paid_amount_status: function(update_paid_amount){
|
||||
if(this.name){
|
||||
update_paid_amount = update_paid_amount ? false : true;
|
||||
}
|
||||
|
||||
this.refresh(update_paid_amount);
|
||||
},
|
||||
|
||||
refresh: function(update_paid_amount) {
|
||||
var me = this;
|
||||
this.refresh_fields(update_paid_amount);
|
||||
@@ -612,6 +631,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
this.update_rate();
|
||||
this.set_primary_action();
|
||||
},
|
||||
|
||||
refresh_fields: function(update_paid_amount) {
|
||||
this.apply_pricing_rule();
|
||||
this.discount_amount_applied = false;
|
||||
@@ -687,7 +707,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
|
||||
if (this.frm.doc.docstatus==0) {
|
||||
this.page.set_primary_action(__("Pay"), function() {
|
||||
me.validate()
|
||||
me.validate();
|
||||
me.update_paid_amount_status(true);
|
||||
me.create_invoice();
|
||||
me.make_payment();
|
||||
}, "octicon octicon-credit-card");
|
||||
@@ -716,49 +737,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
}, 1000)
|
||||
},
|
||||
|
||||
write_off_amount: function(){
|
||||
var me = this;
|
||||
var value = 0.0;
|
||||
|
||||
if(this.frm.doc.outstanding_amount > 0){
|
||||
dialog = new frappe.ui.Dialog({
|
||||
title: 'Write Off Amount',
|
||||
fields: [
|
||||
{fieldtype: "Check", fieldname: "write_off_amount", label: __("Write off Outstanding Amount")},
|
||||
{fieldtype: "Link", options:"Account", default:this.write_off_account, fieldname: "write_off_account",
|
||||
label: __("Write off Account"), get_query: function() {
|
||||
return {
|
||||
filters: {'is_group': 0, 'report_type': 'Profit and Loss'}
|
||||
}
|
||||
}}
|
||||
]
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
|
||||
dialog.fields_dict.write_off_amount.$input.change(function(){
|
||||
write_off_amount = dialog.get_values().write_off_amount;
|
||||
me.frm.doc.write_off_outstanding_amount_automatically = write_off_amount;
|
||||
me.frm.doc.base_write_off_amount = (write_off_amount==1) ? flt(me.frm.doc.grand_total - me.frm.doc.paid_amount, precision("outstanding_amount")) : 0;
|
||||
me.frm.doc.write_off_account = (write_off_amount==1) ? dialog.get_values().write_off_account : '';
|
||||
me.frm.doc.write_off_amount = flt(me.frm.doc.base_write_off_amount * me.frm.doc.conversion_rate, precision("write_off_amount"))
|
||||
me.calculate_outstanding_amount();
|
||||
me.set_primary_action();
|
||||
})
|
||||
|
||||
dialog.fields_dict.write_off_account.$input.change(function(){
|
||||
me.frm.doc.write_off_account = dialog.get_values().write_off_account;
|
||||
})
|
||||
|
||||
dialog.set_primary_action(__("Submit"), function(){
|
||||
dialog.hide()
|
||||
me.submit_invoice()
|
||||
})
|
||||
}else{
|
||||
this.submit_invoice()
|
||||
}
|
||||
},
|
||||
|
||||
submit_invoice: function(){
|
||||
var me = this;
|
||||
frappe.confirm(__("Do you really want to submit the invoice?"), function () {
|
||||
@@ -797,6 +775,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
this.update_invoice()
|
||||
}else{
|
||||
this.name = $.now();
|
||||
this.frm.doc.posting_date = frappe.datetime.get_today();
|
||||
this.frm.doc.posting_time = frappe.datetime.now_time();
|
||||
invoice_data[this.name] = this.frm.doc
|
||||
this.si_docs.push(invoice_data)
|
||||
this.update_localstorage();
|
||||
@@ -869,6 +849,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
for(key in data){
|
||||
if(data[key].docstatus == 1 && index < 50){
|
||||
index++
|
||||
data[key].docstatus = 0;
|
||||
return data
|
||||
}
|
||||
}
|
||||
@@ -941,6 +922,23 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
}
|
||||
},
|
||||
|
||||
validate_serial_no_qty: function(args, item_code, field, value){
|
||||
var me = this;
|
||||
if (args.item_code == item_code && args.serial_no
|
||||
&& field == 'qty' && cint(value) != value) {
|
||||
args.qty = 0.0;
|
||||
this.refresh();
|
||||
frappe.throw(__("Serial no item cannot be a fraction"))
|
||||
}
|
||||
|
||||
if(args.serial_no && args.serial_no.split('\n').length != cint(value)){
|
||||
args.qty = 0.0;
|
||||
args.serial_no = ''
|
||||
this.refresh();
|
||||
frappe.throw(__("Total nos of serial no is not equal to quantity."))
|
||||
}
|
||||
},
|
||||
|
||||
mandatory_batch_no: function(){
|
||||
var me = this;
|
||||
if(this.items[0].has_batch_no && !this.item_batch_no[this.items[0].item_code]){
|
||||
@@ -968,11 +966,13 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
get_pricing_rule: function(item){
|
||||
var me = this;
|
||||
return $.grep(this.pricing_rules, function(data){
|
||||
if(data.item_code == item.item_code || in_list(['All Item Groups', item.item_group], data.item_group)) {
|
||||
if(in_list(['Customer', 'Customer Group', 'Territory'], data.applicable_for)){
|
||||
return me.validate_condition(data)
|
||||
}else{
|
||||
return true
|
||||
if(item.qty >= data.min_qty && (item.qty <= (data.max_qty ? data.max_qty : item.qty)) ){
|
||||
if(data.item_code == item.item_code || in_list(['All Item Groups', item.item_group], data.item_group)) {
|
||||
if(in_list(['Customer', 'Customer Group', 'Territory', 'Campaign'], data.applicable_for)){
|
||||
return me.validate_condition(data)
|
||||
}else{
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -991,6 +991,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
'Customer': [data.customer, [this.frm.doc.customer]],
|
||||
'Customer Group': [data.customer_group, [this.frm.doc.customer_group, 'All Customer Groups']],
|
||||
'Territory': [data.territory, [this.frm.doc.territory, 'All Territories']],
|
||||
'Campaign': [data.campaign, [this.frm.doc.campaign]],
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
"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{{ company }}<br>\n\t{{ __(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ __(\"Date\") }}:</b> {{ dateutil.global_date_format(posting_date) }}<br>\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 items %}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_name }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ format_currency(item.rate, currency) }}</td>\n\t\t\t<td class=\"text-right\">{{ format_currency(item.amount, currency) }}</td>\n\t\t</tr>\n\t\t{% endfor %}\n\t</tbody>\n</table>\n\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{{ format_currency(total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% for row in 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{{ format_currency(row.tax_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if 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{{ format_currency(discount_amount, currency) }}\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{{ format_currency(grand_total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n\n\n<hr>\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{{ company }}<br>\n\t{{ __(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ __(\"Date\") }}:</b> {{ dateutil.global_date_format(posting_date) }}<br>\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 items %}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_name }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ format_number(item.qty, precision(\"difference\")) }}<br>@ {{ format_currency(item.rate, currency) }}</td>\n\t\t\t<td class=\"text-right\">{{ format_currency(item.amount, currency) }}</td>\n\t\t</tr>\n\t\t{% endfor %}\n\t</tbody>\n</table>\n\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{{ format_currency(total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% for row in 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{{ format_currency(row.tax_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if 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{{ format_currency(discount_amount, currency) }}\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{{ format_currency(grand_total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n\n\n<hr>\n<p class=\"text-center\">{{ __(\"Thank you, please visit again.\") }}</p>",
|
||||
"idx": 0,
|
||||
"modified": "2016-05-21 00:25:20.359074",
|
||||
"modified": "2016-08-11 07:23:04.530676",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Point of Sale",
|
||||
"owner": "Administrator",
|
||||
|
||||
@@ -52,10 +52,10 @@ class ReceivablePayableReport(object):
|
||||
if not "range3" in self.filters:
|
||||
self.filters["range3"] = "90"
|
||||
|
||||
for label in ("0-{range1}".format(**self.filters),
|
||||
"{range1}-{range2}".format(**self.filters),
|
||||
"{range2}-{range3}".format(**self.filters),
|
||||
"{range3}-{above}".format(range3=self.filters.range3, above=_("Above"))):
|
||||
for label in ("0-{range1}".format(range1=self.filters["range1"]),
|
||||
"{range1}-{range2}".format(range1=self.filters["range1"]+1, range2=self.filters["range2"]),
|
||||
"{range2}-{range3}".format(range2=self.filters["range2"]+1, range3=self.filters["range3"]),
|
||||
"{range3}-{above}".format(range3=self.filters["range3"] + 1, above=_("Above"))):
|
||||
columns.append({
|
||||
"label": label,
|
||||
"fieldtype": "Currency",
|
||||
@@ -66,7 +66,8 @@ class ReceivablePayableReport(object):
|
||||
columns.append({
|
||||
"fieldname": "currency",
|
||||
"label": _("Currency"),
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Link",
|
||||
"options": "Currency",
|
||||
"width": 100
|
||||
})
|
||||
if args.get("party_type") == "Customer":
|
||||
|
||||
@@ -34,7 +34,8 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
columns.append({
|
||||
"fieldname": "currency",
|
||||
"label": _("Currency"),
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Link",
|
||||
"options": "Currency",
|
||||
"width": 80
|
||||
})
|
||||
|
||||
|
||||
@@ -55,14 +55,6 @@ def get_columns():
|
||||
"fieldtype": "Date",
|
||||
"width": 90
|
||||
},
|
||||
{
|
||||
"fieldname": "payment_document",
|
||||
"label": _("Payment Document"),
|
||||
"fieldtype": "Link",
|
||||
"options": "DocType",
|
||||
"width": 120,
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "payment_entry",
|
||||
"label": _("Payment Entry"),
|
||||
|
||||
@@ -25,6 +25,9 @@ def execute(filters=None):
|
||||
return columns, res
|
||||
|
||||
def validate_filters(filters, account_details):
|
||||
if not filters.get('company'):
|
||||
frappe.throw(_('{0} is mandatory').format(_('Company')))
|
||||
|
||||
if filters.get("account") and not account_details.get(filters.account):
|
||||
frappe.throw(_("Account {0} does not exists").format(filters.account))
|
||||
|
||||
@@ -87,7 +90,7 @@ def get_columns(filters):
|
||||
columns += [
|
||||
_("Voucher Type") + "::120", _("Voucher No") + ":Dynamic Link/"+_("Voucher Type")+":160",
|
||||
_("Against Account") + "::120", _("Party Type") + "::80", _("Party") + "::150",
|
||||
_("Project") + ":Link/Project:100", _("Cost Center") + ":Link/Cost Center:100",
|
||||
_("Project") + ":Link/Project:100", _("Cost Center") + ":Link/Cost Center:100",
|
||||
_("Remarks") + "::400"
|
||||
]
|
||||
|
||||
@@ -111,7 +114,7 @@ def get_gl_entries(filters):
|
||||
if filters.get("group_by_voucher") else "group by name"
|
||||
|
||||
gl_entries = frappe.db.sql("""
|
||||
select
|
||||
select
|
||||
posting_date, account, party_type, party,
|
||||
sum(debit) as debit, sum(credit) as credit,
|
||||
voucher_type, voucher_no, cost_center, project,
|
||||
|
||||
@@ -79,7 +79,8 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
}
|
||||
} else {
|
||||
return{
|
||||
query: "erpnext.controllers.queries.item_query"
|
||||
query: "erpnext.controllers.queries.item_query",
|
||||
filters: {'is_purchase_item': 1}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -30,7 +30,7 @@ frappe.ui.form.on("Request for Quotation",{
|
||||
},
|
||||
|
||||
onload: function(frm) {
|
||||
frm.add_fetch('standard_reply', 'response', 'response');
|
||||
frm.add_fetch('standard_reply', 'response', 'message_for_supplier');
|
||||
|
||||
if(!frm.doc.message_for_supplier) {
|
||||
frm.set_value("message_for_supplier", __("Please supply the specified items at the best possible rates"))
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Document",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@@ -296,7 +297,7 @@
|
||||
"options": "Standard Reply",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
@@ -638,7 +639,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-06-30 01:57:49.233065",
|
||||
"modified": "2016-08-01 08:45:39.777405",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Request for Quotation",
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
|
||||
<head>
|
||||
|
||||
|
||||
<link href="/assets/frappe/css/c3.min.css" rel="stylesheet" type="text/css">
|
||||
|
||||
|
||||
<script type="text/javascript" src="/assets/frappe/js/lib/d3.min.js"></script>
|
||||
<script type="text/javascript" src="/assets/frappe/js/lib/c3.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
onReady("#chart_div", function() {
|
||||
var chartData = [];
|
||||
{% var q = 0; %}
|
||||
{% for(var j=0, m=data.length+1; j<m; j++) { %}
|
||||
|
||||
var tempData{%=j%} = [];
|
||||
|
||||
{% for(var i=1, l=report.columns.length; i<l; i++) { %}
|
||||
{% if(__(report.columns[i].label) != __("Quotation")) { %}
|
||||
|
||||
{% if(j == 0) { %}
|
||||
{% if(i == 1) { %}
|
||||
tempData{%=j%}[{%=i%}-1] = \"x\";
|
||||
{% } else { %}
|
||||
|
||||
tempData{%=j%}[{%=i%}-1] = Math.log(parseInt(\"{%= report.columns[i].label %}\".replace(\"Qty: \",\"\"))) / Math.LN10;
|
||||
{% } %}
|
||||
{% } else { %}
|
||||
{% if(i == 1) { %}
|
||||
tempData{%=j%}[{%=i%}-1] = \"{%= data[j-1][report.columns[i].field] %} \";
|
||||
{% } else { %}
|
||||
tempData{%=j%}[{%=i%}-1] = {% if(data[j-1][report.columns[i].field] == "") { if (i > 2) { %}
|
||||
tempData{%=j%}[{%=i%}-2]
|
||||
{% } else { %}
|
||||
0
|
||||
{% } } else { %}
|
||||
{%= data[j-1][report.columns[i].field] %}
|
||||
{% } %};
|
||||
{% } %};
|
||||
{% } %}
|
||||
{% } else { %}
|
||||
{% if(j == 0) { %}
|
||||
{% if(i < l-1) { %}
|
||||
tempData{%=j%}[{%=i%}-1] = Math.log(parseInt(\"{%= report.columns[i+1].label %}\".replace(\"Qty: \",\"\"))-1) / Math.LN10;
|
||||
{% } else { %}
|
||||
tempData{%=j%}[{%=i%}-1] = Math.log(2*parseInt(\"{%= report.columns[i-1].label %}\".replace(\"Qty: \",\"\"))) / Math.LN10;
|
||||
{% } %}
|
||||
{% } else { %}
|
||||
|
||||
tempData{%=j%}[{%=i%}-1] = tempData{%=j%}[{%=i%}-2];
|
||||
{% } %}
|
||||
|
||||
{% } %}
|
||||
|
||||
{% } %}
|
||||
chartData[{%=j%}] = tempData{%=j%};
|
||||
{% } %}
|
||||
console.log(chartData);
|
||||
|
||||
hold = {
|
||||
bindto: "#chart_div" ,data: {
|
||||
x: "x",
|
||||
columns: chartData
|
||||
},
|
||||
axis: {
|
||||
x: {
|
||||
tick: {
|
||||
format: function (x22) { return Math.pow(10,x22).toFixed(0); },
|
||||
culling: {
|
||||
max: {%=report.columns.length%} / 2
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
point: {
|
||||
show: false
|
||||
}
|
||||
};
|
||||
console.log(hold);
|
||||
var chart = c3.generate(hold);
|
||||
});
|
||||
|
||||
function onReady(selector, callback) {
|
||||
var intervalID = window.setInterval(function() {
|
||||
if (document.querySelector(selector) !== undefined) {
|
||||
window.clearInterval(intervalID);
|
||||
callback.call(this);
|
||||
}
|
||||
}, 500);}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<div style="margin-bottom: 7px;" class="text-center">
|
||||
{%= frappe.boot.letter_heads[frappe.defaults.get_default("letter_head")] %}
|
||||
</div>
|
||||
<h2 class="text-center">{%= __(report.report_name) %}</h2>
|
||||
<h4 class="text-center">{%= filters.item %} </h4>
|
||||
|
||||
<hr>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
{% for(var i=0, l=report.columns.length; i<l; i++) { %}
|
||||
<th style="width: 15%">{%= report.columns[i].label %}</th>
|
||||
{% } %}
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for(var i=0, l=data.length; i<l; i++) { %}
|
||||
<tr>
|
||||
|
||||
{% for(var j=0,m=report.columns.length; j<m; j++) { %}
|
||||
<td style="width: 15%">{%= data[i][report.columns[j].field] %}</td>
|
||||
{% } %}
|
||||
|
||||
</tr>
|
||||
{% } %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4 class="text-center"> Analysis Chart </h4>
|
||||
<div id="chart_div"></div>
|
||||
|
||||
|
||||
|
||||
<p class="text-right text-muted">Printed On {%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>
|
||||
@@ -11,5 +11,72 @@ frappe.query_reports["Quoted Item Comparison"] = {
|
||||
"default": ""
|
||||
|
||||
}
|
||||
]
|
||||
],
|
||||
onload: function(report) {
|
||||
//Create a button for setting the default supplier
|
||||
report.page.add_inner_button(__("Select Default Supplier"), function() {
|
||||
|
||||
var reporter = frappe.query_reports["Quoted Item Comparison"];
|
||||
|
||||
//Always make a new one so that the latest values get updated
|
||||
reporter.make_default_supplier_dialog(report);
|
||||
report.dialog.show();
|
||||
setTimeout(function() { report.dialog.input.focus(); }, 1000);
|
||||
|
||||
}, 'Tools');
|
||||
|
||||
},
|
||||
"make_default_supplier_dialog": function (report) {
|
||||
//Get the name of the item to change
|
||||
var filters = report.get_values();
|
||||
var item_code = filters.item;
|
||||
|
||||
//Get a list of the suppliers (with a blank as well) for the user to select
|
||||
var select_options = "";
|
||||
for (let supplier of report.data)
|
||||
{
|
||||
select_options += supplier.supplier_name+ '\n'
|
||||
}
|
||||
|
||||
//Create a dialog window for the user to pick their supplier
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __('Select Default Supplier'),
|
||||
fields: [
|
||||
{fieldname: 'supplier', fieldtype:'Select', label:'Supplier', reqd:1,options:select_options},
|
||||
{fieldname: 'ok_button', fieldtype:'Button', label:'Set Default Supplier'},
|
||||
]
|
||||
});
|
||||
|
||||
//On the user clicking the ok button
|
||||
d.fields_dict.ok_button.input.onclick = function() {
|
||||
var btn = d.fields_dict.ok_button.input;
|
||||
var v = report.dialog.get_values();
|
||||
if(v) {
|
||||
$(btn).set_working();
|
||||
|
||||
//Set the default_supplier field of the appropriate Item to the selected supplier
|
||||
frappe.call({
|
||||
method: "frappe.client.set_value",
|
||||
args: {
|
||||
doctype: "Item",
|
||||
name: item_code,
|
||||
fieldname: "default_supplier",
|
||||
value: v.supplier,
|
||||
},
|
||||
callback: function (r){
|
||||
$(btn).done_working();
|
||||
msgprint("Successfully Set Supplier");
|
||||
report.dialog.hide();
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
report.dialog = d;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
|
||||
import frappe
|
||||
|
||||
def execute(filters=None):
|
||||
@@ -22,6 +24,7 @@ def get_quote_list(item, qty_list):
|
||||
if item:
|
||||
price_data = []
|
||||
suppliers = []
|
||||
company_currency = frappe.db.get_default("currency")
|
||||
# Get the list of suppliers
|
||||
for root in frappe.db.sql("""select parent, qty, rate from `tabSupplier Quotation Item` where item_code=%s and docstatus < 2""", item, as_dict=1):
|
||||
for splr in frappe.db.sql("""SELECT supplier from `tabSupplier Quotation` where name =%s and docstatus < 2""", root.parent, as_dict=1):
|
||||
@@ -35,6 +38,9 @@ def get_quote_list(item, qty_list):
|
||||
|
||||
#Add a row for each supplier
|
||||
for root in set(suppliers):
|
||||
supplier_currency = frappe.db.get_value("Supplier",root,"default_currency")
|
||||
exg = get_exchange_rate(supplier_currency,company_currency)
|
||||
|
||||
row = frappe._dict({
|
||||
"supplier_name": root
|
||||
})
|
||||
@@ -42,7 +48,7 @@ def get_quote_list(item, qty_list):
|
||||
# Get the quantity for this row
|
||||
for item_price in price_data:
|
||||
if str(item_price.qty) == col.key and item_price.supplier == root:
|
||||
row[col.key] = item_price.rate
|
||||
row[col.key] = item_price.rate * exg
|
||||
row[col.key + "QUOTE"] = item_price.parent
|
||||
break
|
||||
else:
|
||||
|
||||
58
erpnext/change_log/v7/v7_0_0.md
Normal file
@@ -0,0 +1,58 @@
|
||||
#### New POS
|
||||
- Offline
|
||||
- Multiple Payment Modes
|
||||
- Standard documents cannot be edited in POS view
|
||||
|
||||
#### Payment Entry
|
||||
- Dedicated form for managing Payments
|
||||
- Designed for normal users who do not have accounting background
|
||||
|
||||
#### Request for Quotation
|
||||
- Updated workflow: Material Request -> **Request for Quotation** -> Supplier Quotation -> Purchase Order
|
||||
|
||||
#### Fixed Asset Management
|
||||
- Manage fixed asset records and their depreciation
|
||||
|
||||
#### Improved Navigation
|
||||
- Heatmaps
|
||||
- Centralized navigation from Masters like Item, Customer, Supplier, Employee etc.
|
||||
|
||||
#### Timesheets
|
||||
- New grid
|
||||
- Multiple time logs in one timesheets
|
||||
- Linked to Payroll and Billing
|
||||
|
||||
#### Graphs in Reports
|
||||
- Added graphs in some important reports like Balance Sheet, Accounts Receivable etc.
|
||||
|
||||
#### Sub-warehouse
|
||||
- Tree view for Warehouse
|
||||
|
||||
#### New Portal Design
|
||||
- New Homepage Design
|
||||
- Sidebar in Portal View
|
||||
- New Cart View
|
||||
|
||||
#### Collaborative Project Management
|
||||
- Web View
|
||||
- Customers/Suppliers can add/edit issues and view timesheets
|
||||
|
||||
#### Budget
|
||||
- Dedicated budget form
|
||||
- Budget can be assigned against Cost Center Group
|
||||
|
||||
#### Check Printing Format
|
||||
- Ability to customize Cheque Printing Format for any bank
|
||||
|
||||
#### Schools application is now part of ERPNext
|
||||
|
||||
#### Minor
|
||||
|
||||
- Selling Price calculation based on Margin defined in the Pricing Rule
|
||||
- Document flow-chart on Sales / Purchase Transactions
|
||||
- Domain specific desktop views
|
||||
- Add opening Stock and Rate while creating a new Item
|
||||
- Book payments and update stock directly from Purchase Invoice
|
||||
- List view for Products on Website
|
||||
- Features Setup is deprecated, settings moved to individual module setup views
|
||||
- Added Safety Stock to Item Master
|
||||
@@ -229,12 +229,12 @@ def get_data():
|
||||
"type": "list"
|
||||
},
|
||||
{
|
||||
"module_name": "Examination",
|
||||
"module_name": "Assessment",
|
||||
"color": "#8a70be",
|
||||
"icon": "icon-file-text-alt",
|
||||
"label": _("Examination"),
|
||||
"link": "List/Examination",
|
||||
"_doctype": "Examination",
|
||||
"label": _("Assessment"),
|
||||
"link": "List/Assessment",
|
||||
"_doctype": "Assessment",
|
||||
"type": "list"
|
||||
},
|
||||
{
|
||||
@@ -261,7 +261,7 @@ def get_data():
|
||||
"icon": "icon-map-marker",
|
||||
"label": _("Room"),
|
||||
"link": "List/Room",
|
||||
"_doctype": "Examination",
|
||||
"_doctype": "Room",
|
||||
"type": "list"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ You can create Custom Form, Fields, Scripts and can also create your own Apps
|
||||
to extend ERPNext functionality.
|
||||
|
||||
ERPNext is Open Source under the GNU General Public Licence v3 and has been
|
||||
listed as one of the Best Open Source Softwares in the world by my online
|
||||
listed as one of the Best Open Source Softwares in the world by many online
|
||||
blogs."""
|
||||
|
||||
docs_version = "6.x.x"
|
||||
|
||||
@@ -61,7 +61,11 @@ def get_data():
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Examination"
|
||||
"name": "Assessment"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Assessment Group"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
|
||||
@@ -142,7 +142,7 @@ class StatusUpdater(Document):
|
||||
if item['reduce_by'] > .01:
|
||||
self.limits_crossed_error(args, item)
|
||||
|
||||
else:
|
||||
elif item[args['target_ref_field']]:
|
||||
self.check_overflow_with_tolerance(item, args)
|
||||
|
||||
def check_overflow_with_tolerance(self, item, args):
|
||||
|
||||
@@ -38,6 +38,7 @@ class StockController(AccountsController):
|
||||
|
||||
gl_list = []
|
||||
warehouse_with_no_account = []
|
||||
|
||||
for detail in voucher_details:
|
||||
sle_list = sle_map.get(detail.name)
|
||||
if sle_list:
|
||||
@@ -203,10 +204,10 @@ class StockController(AccountsController):
|
||||
from erpnext.stock.stock_ledger import make_sl_entries
|
||||
make_sl_entries(sl_entries, is_amended, allow_negative_stock, via_landed_cost_voucher)
|
||||
|
||||
def make_gl_entries_on_cancel(self):
|
||||
def make_gl_entries_on_cancel(self, repost_future_gle=True):
|
||||
if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s
|
||||
and voucher_no=%s""", (self.doctype, self.name)):
|
||||
self.make_gl_entries()
|
||||
self.make_gl_entries(repost_future_gle)
|
||||
|
||||
def get_serialized_items(self):
|
||||
serialized_items = []
|
||||
@@ -260,16 +261,15 @@ def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for
|
||||
|
||||
future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items)
|
||||
gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date)
|
||||
|
||||
|
||||
for voucher_type, voucher_no in future_stock_vouchers:
|
||||
existing_gle = gle.get((voucher_type, voucher_no), [])
|
||||
voucher_obj = frappe.get_doc(voucher_type, voucher_no)
|
||||
expected_gle = voucher_obj.get_gl_entries(warehouse_account)
|
||||
if expected_gle:
|
||||
if not existing_gle or not compare_existing_and_expected_gle(existing_gle,
|
||||
expected_gle):
|
||||
_delete_gl_entries(voucher_type, voucher_no)
|
||||
voucher_obj.make_gl_entries(repost_future_gle=False)
|
||||
if not existing_gle or not compare_existing_and_expected_gle(existing_gle, expected_gle):
|
||||
_delete_gl_entries(voucher_type, voucher_no)
|
||||
voucher_obj.make_gl_entries(repost_future_gle=False)
|
||||
else:
|
||||
_delete_gl_entries(voucher_type, voucher_no)
|
||||
|
||||
|
||||
@@ -420,8 +420,10 @@ class calculate_taxes_and_totals(object):
|
||||
# NOTE:
|
||||
# write_off_amount is only for POS Invoice
|
||||
# total_advance is only for non POS Invoice
|
||||
if self.doc.is_return:
|
||||
return
|
||||
if self.doc.doctype == "Sales Invoice":
|
||||
self.calculate_paid_amount()
|
||||
|
||||
if self.doc.is_return: return
|
||||
|
||||
self.doc.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount"])
|
||||
self._set_in_company_currency(self.doc, ['write_off_amount'])
|
||||
@@ -435,11 +437,11 @@ class calculate_taxes_and_totals(object):
|
||||
- flt(self.doc.base_write_off_amount), self.doc.precision("grand_total"))
|
||||
|
||||
if self.doc.doctype == "Sales Invoice":
|
||||
self.calculate_paid_amount()
|
||||
self.doc.round_floats_in(self.doc, ["paid_amount"])
|
||||
paid_amount = self.doc.paid_amount \
|
||||
if self.doc.party_account_currency == self.doc.currency else self.doc.base_paid_amount
|
||||
|
||||
self.calculate_write_off_amount()
|
||||
self.calculate_change_amount()
|
||||
|
||||
self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) +
|
||||
@@ -451,10 +453,9 @@ class calculate_taxes_and_totals(object):
|
||||
def calculate_paid_amount(self):
|
||||
paid_amount = base_paid_amount = 0.0
|
||||
for payment in self.doc.get('payments'):
|
||||
if flt(payment.amount) > 0:
|
||||
payment.base_amount = flt(payment.amount * self.doc.conversion_rate)
|
||||
paid_amount += payment.amount
|
||||
base_paid_amount += payment.base_amount
|
||||
payment.base_amount = flt(payment.amount * self.doc.conversion_rate)
|
||||
paid_amount += payment.amount
|
||||
base_paid_amount += payment.base_amount
|
||||
|
||||
self.doc.paid_amount = flt(paid_amount, self.doc.precision("paid_amount"))
|
||||
self.doc.base_paid_amount = flt(base_paid_amount, self.doc.precision("base_paid_amount"))
|
||||
@@ -468,6 +469,13 @@ class calculate_taxes_and_totals(object):
|
||||
self.doc.base_change_amount = flt(self.doc.change_amount * self.doc.conversion_rate,
|
||||
self.doc.precision("base_change_amount"))
|
||||
|
||||
def calculate_write_off_amount(self):
|
||||
if flt(self.doc.change_amount) > 0:
|
||||
self.doc.write_off_amount = flt(self.doc.grand_total - self.doc.paid_amount + self.doc.change_amount,
|
||||
self.doc.precision("write_off_amount"))
|
||||
self.doc.base_write_off_amount = flt(self.doc.write_off_amount * self.doc.conversion_rate,
|
||||
self.doc.precision("base_write_off_amount"))
|
||||
|
||||
def calculate_margin(self, item):
|
||||
total_margin = 0.0
|
||||
if item.price_list_rate:
|
||||
|
||||
@@ -38,7 +38,8 @@ class Lead(SellingController):
|
||||
frappe.throw(_("Campaign Name is required"))
|
||||
|
||||
if self.email_id:
|
||||
validate_email_add(self.email_id, True)
|
||||
if not self.flags.ignore_email_validation:
|
||||
validate_email_add(self.email_id, True)
|
||||
|
||||
if self.email_id == self.lead_owner:
|
||||
# Lead Owner cannot be same as the Lead
|
||||
|
||||
@@ -51,7 +51,8 @@ erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({
|
||||
|
||||
this.frm.set_query("item_code", "items", function() {
|
||||
return {
|
||||
query: "erpnext.controllers.queries.item_query"
|
||||
query: "erpnext.controllers.queries.item_query",
|
||||
filters: {'is_sales_item': 1}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
from frappe.utils import cstr, cint, get_fullname, validate_email_add
|
||||
from frappe.utils import cstr, cint, get_fullname
|
||||
from frappe import msgprint, _
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
@@ -43,7 +43,7 @@ class Opportunity(TransactionBase):
|
||||
|
||||
def make_new_lead_if_required(self):
|
||||
"""Set lead against new opportunity"""
|
||||
if not (self.lead or self.customer) and self.contact_email and validate_email_add(self.contact_email):
|
||||
if not (self.lead or self.customer) and self.contact_email:
|
||||
lead_name = frappe.db.get_value("Lead", {"email_id": self.contact_email})
|
||||
if not lead_name:
|
||||
sender_name = get_fullname(self.contact_email)
|
||||
@@ -64,6 +64,7 @@ class Opportunity(TransactionBase):
|
||||
"lead_name": sender_name
|
||||
})
|
||||
|
||||
lead.flags.ignore_email_validation = True
|
||||
lead.insert(ignore_permissions=True)
|
||||
lead_name = lead.name
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ def simulate():
|
||||
if not runs_for:
|
||||
runs_for = frappe.utils.date_diff(frappe.utils.nowdate(), current_date)
|
||||
# runs_for = 100
|
||||
|
||||
|
||||
fixed_asset.work()
|
||||
|
||||
for i in xrange(runs_for):
|
||||
@@ -72,9 +72,6 @@ def simulate():
|
||||
stock.work()
|
||||
accounts.work()
|
||||
projects.run_projects(current_date)
|
||||
# run_stock()
|
||||
# run_accounts()
|
||||
# run_projects()
|
||||
# run_messages()
|
||||
|
||||
current_date = frappe.utils.add_days(current_date, 1)
|
||||
|
||||
@@ -212,7 +212,7 @@ def setup_user():
|
||||
user = frappe.new_doc("User")
|
||||
user.update(u)
|
||||
user.flags.no_welcome_mail
|
||||
user.password = 'demo'
|
||||
user.new_password = 'demo'
|
||||
user.insert()
|
||||
|
||||
def import_json(doctype, submit=False, values=None):
|
||||
@@ -377,6 +377,12 @@ def setup_budget():
|
||||
|
||||
|
||||
def setup_user_roles():
|
||||
user = frappe.get_doc('User', 'demo@erpnext.com')
|
||||
user.add_roles('HR User', 'HR Manager', 'Accounts User', 'Accounts Manager',
|
||||
'Stock User', 'Stock Manager', 'Sales User', 'Sales Manager', 'Purchase User',
|
||||
'Purchase Manager', 'Projects User', 'Manufacturing User', 'Manufacturing Manager',
|
||||
'Support Team')
|
||||
|
||||
if not frappe.db.get_global('demo_hr_user'):
|
||||
user = frappe.get_doc('User', 'CharmaineGaudreau@example.com')
|
||||
user.add_roles('HR User', 'HR Manager', 'Accounts User')
|
||||
@@ -439,7 +445,7 @@ def setup_leave_allocation():
|
||||
for leave_type in leave_types:
|
||||
if not leave_type.max_days_allowed:
|
||||
leave_type.max_days_allowed = 10
|
||||
|
||||
|
||||
leave_allocation = frappe.get_doc({
|
||||
"doctype": "Leave Allocation",
|
||||
"employee": employee.name,
|
||||
@@ -450,4 +456,4 @@ def setup_leave_allocation():
|
||||
})
|
||||
leave_allocation.insert()
|
||||
leave_allocation.submit()
|
||||
frappe.db.commit()
|
||||
frappe.db.commit()
|
||||
|
||||
BIN
erpnext/docs/assets/img/accounts/opening-2.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
erpnext/docs/assets/img/accounts/opening-3.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
erpnext/docs/assets/img/accounts/opening-4.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
erpnext/docs/assets/img/accounts/opening-5.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
erpnext/docs/assets/img/accounts/opening-6.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
erpnext/docs/assets/img/accounts/opening-7.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
erpnext/docs/assets/img/accounts/perpetual-1.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
erpnext/docs/assets/img/accounts/perpetual-2.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
erpnext/docs/assets/img/accounts/perpetual-3.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 547 KiB |
|
Before Width: | Height: | Size: 85 KiB |
BIN
erpnext/docs/assets/img/articles/freeze-account-1.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
erpnext/docs/assets/img/articles/freeze-account-2.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 86 KiB |
BIN
erpnext/docs/assets/img/articles/post-dated-1.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/assign-1.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/assign-2.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/assign-3.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/assign-4.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/calendar-1.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/calendar-2.gif
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/calendar-3.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/calendar-4.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/calendar-5.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/calendar-6.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/calendar-7.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/chat-1.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/chat-2.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/comments-1.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/note-1.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/share-1.gif
Normal file
|
After Width: | Height: | Size: 252 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/tags-1.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
erpnext/docs/assets/img/collaboration-tools/tags-2.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
erpnext/docs/assets/img/schools/fees/fee-category.png
Normal file
|
After Width: | Height: | Size: 73 KiB |
BIN
erpnext/docs/assets/img/schools/fees/fee-structure.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
erpnext/docs/assets/img/schools/fees/fees-section.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
erpnext/docs/assets/img/schools/fees/fees.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
erpnext/docs/assets/img/schools/home.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 76 KiB |
BIN
erpnext/docs/assets/img/schools/schedule/course-schedule-att.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
erpnext/docs/assets/img/schools/schedule/course-schedule.png
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
erpnext/docs/assets/img/schools/schedule/examination.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
erpnext/docs/assets/img/schools/schedule/schedule-section.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
erpnext/docs/assets/img/schools/schedule/scheduling-tool.png
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
erpnext/docs/assets/img/schools/schedule/student-attendance.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
0
erpnext/docs/assets/img/schools/setup/__init__.py
Normal file
BIN
erpnext/docs/assets/img/schools/setup/academic-term.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
erpnext/docs/assets/img/schools/setup/academic-year.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
erpnext/docs/assets/img/schools/setup/course.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
erpnext/docs/assets/img/schools/setup/instructor.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
erpnext/docs/assets/img/schools/setup/program.png
Normal file
|
After Width: | Height: | Size: 119 KiB |