Compare commits
192 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9cafcb8ae | ||
|
|
bdfd0d1ff9 | ||
|
|
afc8b1a087 | ||
|
|
6c1773025b | ||
|
|
e24365f1f4 | ||
|
|
fd334bf451 | ||
|
|
5515b1ea7f | ||
|
|
96d67f5153 | ||
|
|
8a00319962 | ||
|
|
c6136e4801 | ||
|
|
0938b5dec6 | ||
|
|
88f8fcb32e | ||
|
|
f40ce616a7 | ||
|
|
b02788b915 | ||
|
|
b094ee45d7 | ||
|
|
de0c87757a | ||
|
|
5604f987f2 | ||
|
|
9d14f0f36a | ||
|
|
a74468b353 | ||
|
|
35f81b24f1 | ||
|
|
40431cbf89 | ||
|
|
5529f14aaf | ||
|
|
54c31b498b | ||
|
|
899dba9022 | ||
|
|
7d8fa8089a | ||
|
|
ac86c5b6d1 | ||
|
|
ecc3f312b9 | ||
|
|
b65b5f43a7 | ||
|
|
c3270d7504 | ||
|
|
ea909ace01 | ||
|
|
f64d11da3c | ||
|
|
95225be93d | ||
|
|
e5d169b8d2 | ||
|
|
da4e3fb366 | ||
|
|
13ce150149 | ||
|
|
a04489a72b | ||
|
|
35cd88b09b | ||
|
|
ff56566506 | ||
|
|
01ad94bfad | ||
|
|
cfe3c54ca0 | ||
|
|
2f6a20a93a | ||
|
|
5d1543f241 | ||
|
|
c56650c773 | ||
|
|
cb11f27558 | ||
|
|
98be98816c | ||
|
|
ca2c297f72 | ||
|
|
387e1e21cb | ||
|
|
d6e49150a8 | ||
|
|
49a2729663 | ||
|
|
06baf20edd | ||
|
|
13553c2bf0 | ||
|
|
f638c1acd5 | ||
|
|
e4c659386a | ||
|
|
cd7a1661c6 | ||
|
|
96962e2101 | ||
|
|
7eedebc970 | ||
|
|
437e34accb | ||
|
|
0f2137be18 | ||
|
|
f87a622ef0 | ||
|
|
07722b835c | ||
|
|
3cd7a45c1b | ||
|
|
90b5174256 | ||
|
|
bffad26226 | ||
|
|
a578f3e23a | ||
|
|
870dd43268 | ||
|
|
ad0bd4ca92 | ||
|
|
eba480e15a | ||
|
|
4b83403a63 | ||
|
|
22c9e42f4d | ||
|
|
6ddc487fb6 | ||
|
|
3a34cadcb2 | ||
|
|
b71d1a4c7f | ||
|
|
bef80bab0d | ||
|
|
190210394c | ||
|
|
5cafcf66b0 | ||
|
|
d71e50c9fc | ||
|
|
35ebe1bf78 | ||
|
|
b14cc0417d | ||
|
|
399a3097e8 | ||
|
|
c8f5c3cdbe | ||
|
|
e83d506319 | ||
|
|
690bcd7b66 | ||
|
|
f18d285eab | ||
|
|
7887ccb441 | ||
|
|
d57b57a21d | ||
|
|
5cc0531d27 | ||
|
|
0e5cdc8495 | ||
|
|
b80d892eab | ||
|
|
185af03fb2 | ||
|
|
abcbbc63d8 | ||
|
|
6871c74ce1 | ||
|
|
d0a44ca85c | ||
|
|
83db3e3ddb | ||
|
|
cc11045fd3 | ||
|
|
1b5afe737f | ||
|
|
3d65d9602e | ||
|
|
9440d080d4 | ||
|
|
9269c86339 | ||
|
|
7c82d616c9 | ||
|
|
f227379d2f | ||
|
|
eba88919c1 | ||
|
|
3408432b50 | ||
|
|
a0949158b7 | ||
|
|
ea91d2aaf1 | ||
|
|
de992abf83 | ||
|
|
5d8635a8dc | ||
|
|
7e911bae95 | ||
|
|
0676cf6d3f | ||
|
|
b74ae7aa31 | ||
|
|
0ad7db3bbd | ||
|
|
db74e316d2 | ||
|
|
1897360e4b | ||
|
|
e7fb957415 | ||
|
|
2f4567fa3c | ||
|
|
0a7abc188e | ||
|
|
5eeef7f065 | ||
|
|
7d36875d6f | ||
|
|
2fa718705a | ||
|
|
b1fdbf2335 | ||
|
|
2277922313 | ||
|
|
3e1029309c | ||
|
|
aa5deaa070 | ||
|
|
6b5d51ca22 | ||
|
|
2c114b5bb5 | ||
|
|
bd38a79e5e | ||
|
|
ccd9fd3e94 | ||
|
|
4215b3afc3 | ||
|
|
f60f111afe | ||
|
|
6fe0a3cee3 | ||
|
|
f004077734 | ||
|
|
6c5cfd2148 | ||
|
|
6c1011df92 | ||
|
|
1582a0ce78 | ||
|
|
b5b821363d | ||
|
|
399afc87ef | ||
|
|
8c842af172 | ||
|
|
bf836277f9 | ||
|
|
10d1806d81 | ||
|
|
bc41ce95fc | ||
|
|
4948d336c4 | ||
|
|
be2527d93d | ||
|
|
7f5bb1c8aa | ||
|
|
a8d40e4409 | ||
|
|
e9b4686fec | ||
|
|
5086ef2499 | ||
|
|
8a55d9a795 | ||
|
|
1caca80203 | ||
|
|
9114c26857 | ||
|
|
941a965af4 | ||
|
|
4acd431b92 | ||
|
|
fad0d566f9 | ||
|
|
e2d4079363 | ||
|
|
b9ce1f590b | ||
|
|
36463ed790 | ||
|
|
3c8838816d | ||
|
|
11e50a8eee | ||
|
|
9de4c60bd6 | ||
|
|
5288bdeabb | ||
|
|
f5804438bb | ||
|
|
6e06357dc5 | ||
|
|
28913b97b0 | ||
|
|
c59cd46391 | ||
|
|
dda239fd49 | ||
|
|
b86a6ce26a | ||
|
|
ee212e7bb5 | ||
|
|
4952c7b3b5 | ||
|
|
4e61536f50 | ||
|
|
f2886f152b | ||
|
|
b5c56f6cea | ||
|
|
80e95388f5 | ||
|
|
daed0b655a | ||
|
|
fbb994c731 | ||
|
|
10b155a486 | ||
|
|
ce6eda709b | ||
|
|
14e1d20df3 | ||
|
|
da8a02d56e | ||
|
|
16343683d9 | ||
|
|
2bdc017aff | ||
|
|
16e05c321c | ||
|
|
23d7919865 | ||
|
|
38265efc39 | ||
|
|
2d414706dc | ||
|
|
d85e4b0d46 | ||
|
|
45d03af8f6 | ||
|
|
73a3a2a131 | ||
|
|
73804580d4 | ||
|
|
259f9779db | ||
|
|
14e0e58a7d | ||
|
|
5eb373f7b5 | ||
|
|
4595c30a7b | ||
|
|
fc2dd44694 | ||
|
|
053c54017e |
@@ -1 +1 @@
|
||||
__version__ = '4.7.2'
|
||||
__version__ = '4.16.0'
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import flt, cstr, cint, getdate, add_days, formatdate
|
||||
from frappe.utils import flt, cstr, cint, getdate
|
||||
from frappe import msgprint, throw, _
|
||||
from frappe.model.document import Document
|
||||
|
||||
@@ -176,15 +176,7 @@ class Account(Document):
|
||||
frappe.throw(_("Due Date cannot be before Posting Date"))
|
||||
|
||||
elif credit_days is not None and diff > credit_days:
|
||||
is_credit_controller = frappe.db.get_value("Accounts Settings", None,
|
||||
"credit_controller") in frappe.user.get_roles()
|
||||
|
||||
if is_credit_controller:
|
||||
msgprint(_("Note: Due Date exceeds the allowed credit days by {0} day(s)").format(
|
||||
diff - credit_days))
|
||||
else:
|
||||
max_due_date = formatdate(add_days(posting_date, credit_days))
|
||||
frappe.throw(_("Due Date cannot be after {0}").format(max_due_date))
|
||||
msgprint(_("Note: Due Date exceeds the allowed credit days by {0} day(s)").format(diff - credit_days))
|
||||
|
||||
def validate_trash(self):
|
||||
"""checks gl entries and if child exists"""
|
||||
|
||||
@@ -124,6 +124,10 @@ def update_outstanding_amt(account, against_voucher_type, against_voucher, on_ca
|
||||
from `tabGL Entry` where voucher_type = 'Journal Voucher' and voucher_no = %s
|
||||
and account = %s and ifnull(against_voucher, '') = ''""",
|
||||
(against_voucher, account))[0][0])
|
||||
if not against_voucher_amount:
|
||||
frappe.throw(_("Against Journal Voucher {0} is already adjusted against some other voucher")
|
||||
.format(against_voucher))
|
||||
|
||||
bal = against_voucher_amount + bal
|
||||
if against_voucher_amount < 0:
|
||||
bal = -bal
|
||||
|
||||
@@ -213,10 +213,11 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
|
||||
return;
|
||||
|
||||
var update_jv_details = function(doc, r) {
|
||||
$.each(r.message, function(i, d) {
|
||||
var jvdetail = frappe.model.add_child(doc, "Journal Voucher Detail", "entries");
|
||||
jvdetail.account = d.account;
|
||||
jvdetail.balance = d.balance;
|
||||
var jvdetail = frappe.model.add_child(doc, "Journal Voucher Detail", "entries");
|
||||
$.each(r, function(i, d) {
|
||||
var row = frappe.model.add_child(doc, "Journal Voucher Detail", "entries");
|
||||
row.account = d.account;
|
||||
row.balance = d.balance;
|
||||
});
|
||||
refresh_field("entries");
|
||||
}
|
||||
@@ -231,7 +232,7 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
update_jv_details(doc, r);
|
||||
update_jv_details(doc, [r.message]);
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -245,7 +246,7 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
|
||||
callback: function(r) {
|
||||
frappe.model.clear_table(doc, "entries");
|
||||
if(r.message) {
|
||||
update_jv_details(doc, r);
|
||||
update_jv_details(doc, r.message);
|
||||
}
|
||||
cur_frm.set_value("is_opening", "Yes")
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import cint, cstr, flt, fmt_money, formatdate, getdate
|
||||
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate
|
||||
from frappe import msgprint, _, scrub
|
||||
from erpnext.setup.utils import get_company_currency
|
||||
|
||||
@@ -13,10 +13,6 @@ from erpnext.controllers.accounts_controller import AccountsController
|
||||
class JournalVoucher(AccountsController):
|
||||
def __init__(self, arg1, arg2=None):
|
||||
super(JournalVoucher, self).__init__(arg1, arg2)
|
||||
self.master_type = {}
|
||||
self.credit_days_for = {}
|
||||
self.credit_days_global = -1
|
||||
self.is_approving_authority = -1
|
||||
|
||||
def validate(self):
|
||||
if not self.is_opening:
|
||||
@@ -40,7 +36,7 @@ class JournalVoucher(AccountsController):
|
||||
|
||||
def on_submit(self):
|
||||
if self.voucher_type in ['Bank Voucher', 'Contra Voucher', 'Journal Entry']:
|
||||
self.check_credit_days()
|
||||
self.check_reference_date()
|
||||
self.make_gl_entries()
|
||||
self.check_credit_limit()
|
||||
self.update_advance_paid()
|
||||
@@ -88,15 +84,24 @@ class JournalVoucher(AccountsController):
|
||||
def validate_against_jv(self):
|
||||
for d in self.get('entries'):
|
||||
if d.against_jv:
|
||||
account_root_type = frappe.db.get_value("Account", d.account, "root_type")
|
||||
if account_root_type == "Asset" and flt(d.debit) > 0:
|
||||
frappe.throw(_("For {0}, only credit entries can be linked against another debit entry")
|
||||
.format(d.account))
|
||||
elif account_root_type == "Liability" and flt(d.credit) > 0:
|
||||
frappe.throw(_("For {0}, only debit entries can be linked against another credit entry")
|
||||
.format(d.account))
|
||||
|
||||
if d.against_jv == self.name:
|
||||
frappe.throw(_("You can not enter current voucher in 'Against Journal Voucher' column"))
|
||||
|
||||
against_entries = frappe.db.sql("""select * from `tabJournal Voucher Detail`
|
||||
where account = %s and docstatus = 1 and parent = %s
|
||||
and ifnull(against_jv, '') = ''""", (d.account, d.against_jv), as_dict=True)
|
||||
and ifnull(against_jv, '') = '' and ifnull(against_invoice, '') = ''
|
||||
and ifnull(against_voucher, '') = ''""", (d.account, d.against_jv), as_dict=True)
|
||||
|
||||
if not against_entries:
|
||||
frappe.throw(_("Journal Voucher {0} does not have account {1} or already matched")
|
||||
frappe.throw(_("Journal Voucher {0} does not have account {1} or already matched against other voucher")
|
||||
.format(d.against_jv, d.account))
|
||||
else:
|
||||
dr_or_cr = "debit" if d.credit > 0 else "credit"
|
||||
@@ -153,7 +158,7 @@ class JournalVoucher(AccountsController):
|
||||
and voucher_account != d.account:
|
||||
frappe.throw(_("Row {0}: Account {1} does not match with {2} {3} account") \
|
||||
.format(d.idx, d.account, doctype, field_dict.get(doctype)))
|
||||
|
||||
|
||||
if against_field in ["against_sales_order", "against_purchase_order"]:
|
||||
if voucher_account != account_master_name:
|
||||
frappe.throw(_("Row {0}: Account {1} does not match with {2} {3} Name") \
|
||||
@@ -165,7 +170,7 @@ class JournalVoucher(AccountsController):
|
||||
|
||||
def validate_against_invoice_fields(self, doctype, payment_against_voucher):
|
||||
for voucher_no, payment_list in payment_against_voucher.items():
|
||||
voucher_properties = frappe.db.get_value(doctype, voucher_no,
|
||||
voucher_properties = frappe.db.get_value(doctype, voucher_no,
|
||||
["docstatus", "outstanding_amount"])
|
||||
|
||||
if voucher_properties[0] != 1:
|
||||
@@ -177,7 +182,7 @@ class JournalVoucher(AccountsController):
|
||||
|
||||
def validate_against_order_fields(self, doctype, payment_against_voucher):
|
||||
for voucher_no, payment_list in payment_against_voucher.items():
|
||||
voucher_properties = frappe.db.get_value(doctype, voucher_no,
|
||||
voucher_properties = frappe.db.get_value(doctype, voucher_no,
|
||||
["docstatus", "per_billed", "status", "advance_paid", "grand_total"])
|
||||
|
||||
if voucher_properties[0] != 1:
|
||||
@@ -280,71 +285,38 @@ class JournalVoucher(AccountsController):
|
||||
|
||||
def set_print_format_fields(self):
|
||||
for d in self.get('entries'):
|
||||
result = frappe.db.get_value("Account", d.account,
|
||||
["account_type", "master_type"])
|
||||
acc = frappe.db.get_value("Account", d.account, ["account_type", "master_type"], as_dict=1)
|
||||
|
||||
if not result:
|
||||
continue
|
||||
if not acc: continue
|
||||
|
||||
account_type, master_type = result
|
||||
|
||||
if master_type in ['Supplier', 'Customer']:
|
||||
if acc.master_type in ['Supplier', 'Customer']:
|
||||
if not self.pay_to_recd_from:
|
||||
self.pay_to_recd_from = frappe.db.get_value(master_type,
|
||||
' - '.join(d.account.split(' - ')[:-1]),
|
||||
master_type == 'Customer' and 'customer_name' or 'supplier_name')
|
||||
self.pay_to_recd_from = frappe.db.get_value(acc.master_type, ' - '.join(d.account.split(' - ')[:-1]),
|
||||
acc.master_type == 'Customer' and 'customer_name' or 'supplier_name')
|
||||
if self.voucher_type in ["Credit Note", "Debit Note"]:
|
||||
self.set_total_amount(d.debit or d.credit)
|
||||
|
||||
if account_type in ['Bank', 'Cash']:
|
||||
company_currency = get_company_currency(self.company)
|
||||
amt = flt(d.debit) and d.debit or d.credit
|
||||
self.total_amount = fmt_money(amt, currency=company_currency)
|
||||
from frappe.utils import money_in_words
|
||||
self.total_amount_in_words = money_in_words(amt, company_currency)
|
||||
if acc.account_type in ['Bank', 'Cash']:
|
||||
self.set_total_amount(d.debit or d.credit)
|
||||
|
||||
def check_credit_days(self):
|
||||
date_diff = 0
|
||||
def set_total_amount(self, amt):
|
||||
company_currency = get_company_currency(self.company)
|
||||
self.total_amount = fmt_money(amt, currency=company_currency)
|
||||
from frappe.utils import money_in_words
|
||||
self.total_amount_in_words = money_in_words(amt, company_currency)
|
||||
|
||||
def check_reference_date(self):
|
||||
if self.cheque_date:
|
||||
date_diff = (getdate(self.cheque_date)-getdate(self.posting_date)).days
|
||||
for d in self.get("entries"):
|
||||
due_date = None
|
||||
if d.against_invoice and flt(d.credit) > 0:
|
||||
due_date = frappe.db.get_value("Sales Invoice", d.against_invoice, "due_date")
|
||||
elif d.against_voucher and flt(d.debit) > 0:
|
||||
due_date = frappe.db.get_value("Purchase Invoice", d.against_voucher, "due_date")
|
||||
|
||||
if date_diff <= 0: return
|
||||
|
||||
# Get List of Customer Account
|
||||
acc_list = filter(lambda d: frappe.db.get_value("Account", d.account,
|
||||
"master_type")=='Customer', self.get('entries'))
|
||||
|
||||
for d in acc_list:
|
||||
credit_days = self.get_credit_days_for(d.account)
|
||||
# Check credit days
|
||||
if credit_days > 0 and not self.get_authorized_user() and cint(date_diff) > credit_days:
|
||||
msgprint(_("Maximum allowed credit is {0} days after posting date").format(credit_days),
|
||||
raise_exception=1)
|
||||
|
||||
def get_credit_days_for(self, ac):
|
||||
if not self.credit_days_for.has_key(ac):
|
||||
self.credit_days_for[ac] = cint(frappe.db.get_value("Account", ac, "credit_days"))
|
||||
|
||||
if not self.credit_days_for[ac]:
|
||||
if self.credit_days_global==-1:
|
||||
self.credit_days_global = cint(frappe.db.get_value("Company",
|
||||
self.company, "credit_days"))
|
||||
|
||||
return self.credit_days_global
|
||||
else:
|
||||
return self.credit_days_for[ac]
|
||||
|
||||
def get_authorized_user(self):
|
||||
if self.is_approving_authority==-1:
|
||||
self.is_approving_authority = 0
|
||||
|
||||
# Fetch credit controller role
|
||||
approving_authority = frappe.db.get_value("Accounts Settings", None,
|
||||
"credit_controller")
|
||||
|
||||
# Check logged-in user is authorized
|
||||
if approving_authority in frappe.user.get_roles():
|
||||
self.is_approving_authority = 1
|
||||
|
||||
return self.is_approving_authority
|
||||
if due_date and getdate(self.cheque_date) > getdate(due_date):
|
||||
msgprint(_("Note: Reference Date {0} is after invoice due date {1}")
|
||||
.format(formatdate(self.cheque_date), formatdate(due_date)))
|
||||
|
||||
def make_gl_entries(self, cancel=0, adv_adj=0):
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
@@ -377,7 +349,7 @@ class JournalVoucher(AccountsController):
|
||||
for d in self.get("entries"):
|
||||
master_type, master_name = frappe.db.get_value("Account", d.account,
|
||||
["master_type", "master_name"])
|
||||
if master_type == "Customer" and master_name:
|
||||
if master_type == "Customer" and master_name and flt(d.debit) > 0:
|
||||
super(JournalVoucher, self).check_credit_limit(d.account)
|
||||
|
||||
def get_balance(self):
|
||||
@@ -532,9 +504,10 @@ def get_against_sales_invoice(doctype, txt, searchfield, start, page_len, filter
|
||||
(filters["account"], "%%%s%%" % txt, start, page_len))
|
||||
|
||||
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
|
||||
return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
|
||||
from `tabJournal Voucher` jv, `tabJournal Voucher Detail` jv_detail
|
||||
where jv_detail.parent = jv.name and jv_detail.account = %s and jv.docstatus = 1
|
||||
return frappe.db.sql("""select distinct jv.name, jv.posting_date, jv.user_remark
|
||||
from `tabJournal Voucher` jv, `tabJournal Voucher Detail` jvd
|
||||
where jvd.parent = jv.name and jvd.account = %s and jv.docstatus = 1
|
||||
and (ifnull(jvd.against_invoice, '') = '' and ifnull(jvd.against_voucher, '') = '' and ifnull(jvd.against_jv, '') = '' )
|
||||
and jv.%s like %s order by jv.name desc limit %s, %s""" %
|
||||
("%s", searchfield, "%s", "%s", "%s"),
|
||||
(filters["account"], "%%%s%%" % txt, start, page_len))
|
||||
|
||||
@@ -19,9 +19,9 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
this.frm.set_query('bank_cash_account', function() {
|
||||
if(!me.frm.doc.company) {
|
||||
msgprint(__("Please select company first"));
|
||||
@@ -35,12 +35,8 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
var help_content = '<i class="icon-hand-right"></i> ' + __("Note") + ':<br>'+
|
||||
'<ul>' + __("If you are unable to match the exact amount, then amend your Journal Voucher and split rows such that payment amount match the invoice amount.") + '</ul>';
|
||||
this.frm.set_value("reconcile_help", help_content);
|
||||
},
|
||||
|
||||
|
||||
get_unreconciled_entries: function() {
|
||||
var me = this;
|
||||
return this.frm.call({
|
||||
@@ -48,12 +44,12 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
|
||||
method: 'get_unreconciled_entries',
|
||||
callback: function(r, rt) {
|
||||
var invoices = [];
|
||||
|
||||
|
||||
$.each(me.frm.doc.payment_reconciliation_invoices || [], function(i, row) {
|
||||
if (row.invoice_number && !inList(invoices, row.invoice_number))
|
||||
if (row.invoice_number && !inList(invoices, row.invoice_number))
|
||||
invoices.push(row.invoice_number);
|
||||
});
|
||||
|
||||
|
||||
frappe.meta.get_docfield("Payment Reconciliation Payment", "invoice_number",
|
||||
me.frm.doc.name).options = invoices.join("\n");
|
||||
|
||||
@@ -79,4 +75,4 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
|
||||
|
||||
$.extend(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({frm: cur_frm}));
|
||||
|
||||
cur_frm.add_fetch('party_account', 'master_type', 'party_type')
|
||||
cur_frm.add_fetch('party_account', 'master_type', 'party_type')
|
||||
|
||||
@@ -118,19 +118,12 @@
|
||||
"options": "Payment Reconciliation Invoice",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "reconcile_help",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
"icon": "icon-resize-horizontal",
|
||||
"issingle": 1,
|
||||
"modified": "2014-07-31 05:43:03.410832",
|
||||
"modified": "2014-10-16 17:51:44.367107",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation",
|
||||
|
||||
@@ -96,13 +96,14 @@ class PaymentReconciliation(Document):
|
||||
|
||||
payment_amount = payment_amount[0][0] if payment_amount else 0
|
||||
|
||||
if d.invoice_amount > payment_amount:
|
||||
if d.invoice_amount - payment_amount > 0.005:
|
||||
non_reconciled_invoices.append({
|
||||
'voucher_no': d.voucher_no,
|
||||
'voucher_type': d.voucher_type,
|
||||
'posting_date': d.posting_date,
|
||||
'invoice_amount': flt(d.invoice_amount),
|
||||
'outstanding_amount': d.invoice_amount - payment_amount})
|
||||
'outstanding_amount': flt(d.invoice_amount - payment_amount, 2)
|
||||
})
|
||||
|
||||
self.add_invoice_entries(non_reconciled_invoices)
|
||||
|
||||
@@ -124,7 +125,7 @@ class PaymentReconciliation(Document):
|
||||
dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
|
||||
lst = []
|
||||
for e in self.get('payment_reconciliation_payments'):
|
||||
if e.invoice_type and e.invoice_number:
|
||||
if e.invoice_type and e.invoice_number and e.allocated_amount:
|
||||
lst.append({
|
||||
'voucher_no' : e.journal_voucher,
|
||||
'voucher_detail_no' : e.voucher_detail_number,
|
||||
@@ -134,7 +135,7 @@ class PaymentReconciliation(Document):
|
||||
'is_advance' : e.is_advance,
|
||||
'dr_or_cr' : dr_or_cr,
|
||||
'unadjusted_amt' : flt(e.amount),
|
||||
'allocated_amt' : flt(e.amount)
|
||||
'allocated_amt' : flt(e.allocated_amount)
|
||||
})
|
||||
|
||||
if lst:
|
||||
@@ -162,18 +163,23 @@ class PaymentReconciliation(Document):
|
||||
|
||||
invoices_to_reconcile = []
|
||||
for p in self.get("payment_reconciliation_payments"):
|
||||
if p.invoice_type and p.invoice_number:
|
||||
if p.invoice_type and p.invoice_number and p.allocated_amount:
|
||||
invoices_to_reconcile.append(p.invoice_number)
|
||||
|
||||
if p.invoice_number not in unreconciled_invoices.get(p.invoice_type, {}):
|
||||
frappe.throw(_("{0}: {1} not found in Invoice Details table")
|
||||
.format(p.invoice_type, p.invoice_number))
|
||||
|
||||
if p.amount > unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number):
|
||||
frappe.throw(_("Row {0}: Payment amount must be less than or equals to invoice outstanding amount. Please refer Note below.").format(p.idx))
|
||||
if flt(p.allocated_amount) > flt(p.amount):
|
||||
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to JV amount {2}")
|
||||
.format(p.idx, p.allocated_amount, p.amount))
|
||||
|
||||
if flt(p.allocated_amount) > unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number):
|
||||
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to invoice outstanding amount {2}")
|
||||
.format(p.idx, p.allocated_amount, unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number)))
|
||||
|
||||
if not invoices_to_reconcile:
|
||||
frappe.throw(_("Please select Invoice Type and Invoice Number in atleast one row"))
|
||||
frappe.throw(_("Please select Allocated Amount, Invoice Type and Invoice Number in atleast one row"))
|
||||
|
||||
def check_condition(self, dr_or_cr):
|
||||
cond = self.from_date and " and posting_date >= '" + self.from_date + "'" or ""
|
||||
|
||||
@@ -53,11 +53,20 @@
|
||||
"label": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "allocated_amount",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Allocated amount",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "Sales Invoice",
|
||||
"fieldname": "invoice_type",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"in_list_view": 0,
|
||||
"label": "Invoice Type",
|
||||
"options": "\nSales Invoice\nPurchase Invoice\nJournal Voucher",
|
||||
"permlevel": 0,
|
||||
@@ -95,7 +104,7 @@
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2014-07-21 16:53:56.206169",
|
||||
"modified": "2014-10-16 17:40:54.040194",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation Payment",
|
||||
|
||||
@@ -42,9 +42,6 @@ frappe.ui.form.on("Payment Tool", "received_or_paid", function(frm) {
|
||||
erpnext.payment_tool.check_mandatory_to_set_button(frm);
|
||||
});
|
||||
|
||||
// Fetch bank/cash account based on payment mode
|
||||
cur_frm.add_fetch("payment_mode", "default_account", "payment_account");
|
||||
|
||||
// Set party account name
|
||||
frappe.ui.form.on("Payment Tool", "customer", function(frm) {
|
||||
erpnext.payment_tool.set_party_account(frm);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _, scrub
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
from frappe.model.document import Document
|
||||
import json
|
||||
@@ -93,7 +93,7 @@ def get_orders_to_be_billed(party_type, party_name):
|
||||
and docstatus = 1
|
||||
and ifnull(status, "") != "Stopped"
|
||||
and ifnull(grand_total, 0) > ifnull(advance_paid, 0)
|
||||
and ifnull(per_billed, 0) < 100.0
|
||||
and abs(100 - ifnull(per_billed, 0)) > 0.01
|
||||
""" % (voucher_type, 'customer' if party_type == "Customer" else 'supplier', '%s'),
|
||||
party_name, as_dict = True)
|
||||
|
||||
|
||||
@@ -800,7 +800,8 @@
|
||||
"fieldtype": "Date",
|
||||
"label": "From Date",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0
|
||||
"permlevel": 0,
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
@@ -810,7 +811,8 @@
|
||||
"fieldtype": "Date",
|
||||
"label": "To Date",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0
|
||||
"permlevel": 0,
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
@@ -878,7 +880,7 @@
|
||||
"icon": "icon-file-text",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-10-08 14:23:20.234176",
|
||||
"modified": "2014-11-27 17:28:20.133701",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
|
||||
@@ -233,6 +233,11 @@ erpnext.POS = Class.extend({
|
||||
},
|
||||
make_item_list: function() {
|
||||
var me = this;
|
||||
if(!this.price_list) {
|
||||
msgprint(__("Price List not found or disabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
me.item_timeout = null;
|
||||
frappe.call({
|
||||
method: 'erpnext.accounts.doctype.sales_invoice.pos.get_items',
|
||||
@@ -487,7 +492,7 @@ erpnext.POS = Class.extend({
|
||||
});
|
||||
|
||||
me.refresh_delete_btn();
|
||||
if(me.frm.doc[this.party]) {
|
||||
if(me.frm.doc[this.party.toLowerCase()]) {
|
||||
this.barcode.$input.focus();
|
||||
} else {
|
||||
this.party_field.$input.focus();
|
||||
|
||||
@@ -225,8 +225,7 @@ $.extend(cur_frm.cscript, new erpnext.accounts.SalesInvoiceController({frm: cur_
|
||||
// Hide Fields
|
||||
// ------------
|
||||
cur_frm.cscript.hide_fields = function(doc) {
|
||||
par_flds = ['project_name', 'due_date', 'is_opening', 'source', 'total_advance', 'gross_profit',
|
||||
'gross_profit_percent', 'get_advances_received',
|
||||
par_flds = ['project_name', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances_received',
|
||||
'advance_adjustment_details', 'sales_partner', 'commission_rate',
|
||||
'total_commission', 'advances', 'from_date', 'to_date'];
|
||||
|
||||
|
||||
@@ -568,27 +568,6 @@
|
||||
"print_hide": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "gross_profit",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Gross Profit",
|
||||
"oldfieldname": "gross_profit",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "gross_profit_percent",
|
||||
"fieldtype": "Float",
|
||||
"label": "Gross Profit (%)",
|
||||
"oldfieldname": "gross_profit_percent",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "advances",
|
||||
"fieldtype": "Section Break",
|
||||
@@ -1213,7 +1192,7 @@
|
||||
"icon": "icon-file-text",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-10-10 16:54:22.284284",
|
||||
"modified": "2014-12-11 16:26:12.402110",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
||||
@@ -1,155 +1,156 @@
|
||||
{
|
||||
"autoname": "INVTD.######",
|
||||
"creation": "2013-04-24 11:39:32",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"autoname": "INVTD.######",
|
||||
"creation": "2013-04-24 11:39:32",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "charge_type",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Type",
|
||||
"oldfieldname": "charge_type",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total",
|
||||
"permlevel": 0,
|
||||
"fieldname": "charge_type",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Type",
|
||||
"oldfieldname": "charge_type",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1",
|
||||
"fieldname": "row_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Reference Row #",
|
||||
"oldfieldname": "row_id",
|
||||
"oldfieldtype": "Data",
|
||||
"depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1",
|
||||
"fieldname": "row_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "Reference Row #",
|
||||
"oldfieldname": "row_id",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"print_width": "300px",
|
||||
"reqd": 1,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"print_width": "300px",
|
||||
"reqd": 1,
|
||||
"width": "300px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break_1",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"fieldname": "col_break_1",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "account_head",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 0,
|
||||
"label": "Account Head",
|
||||
"oldfieldname": "account_head",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"reqd": 1,
|
||||
"fieldname": "account_head",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 0,
|
||||
"label": "Account Head",
|
||||
"oldfieldname": "account_head",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"default": ":Company",
|
||||
"fieldname": "cost_center",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 0,
|
||||
"label": "Cost Center",
|
||||
"oldfieldname": "cost_center_other_charges",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Cost Center",
|
||||
"default": ":Company",
|
||||
"fieldname": "cost_center",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 0,
|
||||
"label": "Cost Center",
|
||||
"oldfieldname": "cost_center_other_charges",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Cost Center",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Rate",
|
||||
"oldfieldname": "rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Rate",
|
||||
"oldfieldname": "rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "tax_amount",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
"oldfieldname": "tax_amount",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1,
|
||||
"fieldname": "tax_amount",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Amount",
|
||||
"oldfieldname": "tax_amount",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1,
|
||||
"reqd": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "total",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total",
|
||||
"oldfieldname": "total",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"fieldname": "total",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total",
|
||||
"oldfieldname": "total",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"description": "If checked, the tax amount will be considered as already included in the Print Rate / Print Amount",
|
||||
"fieldname": "included_in_print_rate",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is this Tax included in Basic Rate?",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_width": "150px",
|
||||
"report_hide": 1,
|
||||
"allow_on_submit": 0,
|
||||
"description": "If checked, the tax amount will be considered as already included in the Print Rate / Print Amount",
|
||||
"fieldname": "included_in_print_rate",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is this Tax included in Basic Rate?",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_width": "150px",
|
||||
"report_hide": 1,
|
||||
"width": "150px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "tax_amount_after_discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 1,
|
||||
"label": "Tax Amount After Discount Amount",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"depends_on": "eval:parent.discount_amount",
|
||||
"fieldname": "tax_amount_after_discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"label": "Tax Amount After Discount Amount",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "item_wise_tax_detail",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 1,
|
||||
"label": "Item Wise Tax Detail",
|
||||
"oldfieldname": "item_wise_tax_detail",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"fieldname": "item_wise_tax_detail",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 1,
|
||||
"label": "Item Wise Tax Detail",
|
||||
"oldfieldname": "item_wise_tax_detail",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "parenttype",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"in_filter": 1,
|
||||
"label": "Parenttype",
|
||||
"oldfieldname": "parenttype",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"fieldname": "parenttype",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"in_filter": 1,
|
||||
"label": "Parenttype",
|
||||
"oldfieldname": "parenttype",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"search_index": 1
|
||||
}
|
||||
],
|
||||
"hide_heading": 1,
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-05-30 03:43:39.740638",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Taxes and Charges",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"hide_heading": 1,
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-12-10 12:26:41.222471",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Taxes and Charges",
|
||||
"owner": "Administrator",
|
||||
"permissions": []
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
"doc_type": "Journal Voucher",
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Format",
|
||||
"html": "{%- from \"templates/print_formats/standard_macros.html\" import add_header -%}\n\n<div class=\"page-break\">\n {%- if not doc.get(\"print_heading\") and not doc.get(\"select_print_heading\") \n and doc.set(\"select_print_heading\", _(\"Credit Note\")) -%}{%- endif -%}\n {{ add_header(0, 1, doc, letter_head, no_letterhead) }}\n\n {%- for label, value in (\n (_(\"Credit To\"), doc.pay_to_recd_from),\n (_(\"Date\"), frappe.utils.formatdate(doc.voucher_date)),\n (_(\"Amount\"), \"<strong>\" + doc.total_amount + \"</strong><br>\" + (doc.total_amount_in_words or \"\") + \"<br>\"),\n (_(\"Remarks\"), doc.remark)\n ) -%}\n\n <div class=\"row\">\n <div class=\"col-sm-3\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-sm-9\">{{ value }}</div>\n </div>\n\n {%- endfor -%}\n\n <hr>\n <br>\n <p class=\"strong\">\n {{ _(\"For\") }} {{ doc.company }},<br>\n <br>\n <br>\n <br>\n {{ _(\"Authorized Signatory\") }}\n </p>\n</div>\n\n\n",
|
||||
"html": "{%- from \"templates/print_formats/standard_macros.html\" import add_header -%}\n\n<div class=\"page-break\">\n {%- if not doc.get(\"print_heading\") and not doc.get(\"select_print_heading\") \n and doc.set(\"select_print_heading\", _(\"Credit Note\")) -%}{%- endif -%}\n {{ add_header(0, 1, doc, letter_head, no_letterhead) }}\n\n {%- for label, value in (\n (_(\"Credit To\"), doc.pay_to_recd_from),\n (_(\"Date\"), frappe.utils.formatdate(doc.voucher_date)),\n (_(\"Amount\"), \"<strong>\" + frappe.utils.cstr(doc.total_amount) + \"</strong><br>\" + (doc.total_amount_in_words or \"\") + \"<br>\"),\n (_(\"Remarks\"), doc.remark)\n ) -%}\n\n <div class=\"row\">\n <div class=\"col-sm-3\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-sm-9\">{{ value }}</div>\n </div>\n\n {%- endfor -%}\n\n <hr>\n <br>\n <p class=\"strong\">\n {{ _(\"For\") }} {{ doc.company }},<br>\n <br>\n <br>\n <br>\n {{ _(\"Authorized Signatory\") }}\n </p>\n</div>\n\n\n",
|
||||
"idx": 2,
|
||||
"modified": "2014-08-29 13:20:15.789533",
|
||||
"modified": "2014-10-17 17:20:02.740340",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Credit Note",
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
"doc_type": "Journal Voucher",
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Format",
|
||||
"html": "{%- from \"templates/print_formats/standard_macros.html\" import add_header -%}\n<div class=\"page-break\">\n {%- if not doc.get(\"print_heading\") and not doc.get(\"select_print_heading\") \n and doc.set(\"select_print_heading\", _(\"Payment Receipt Note\")) -%}{%- endif -%}\n {{ add_header(0, 1, doc, letter_head, no_letterhead) }}\n\n {%- for label, value in (\n (_(\"Received On\"), frappe.utils.formatdate(doc.voucher_date)),\n (_(\"Received From\"), doc.pay_to_recd_from),\n (_(\"Amount\"), \"<strong>\" + doc.total_amount + \"</strong><br>\" + (doc.total_amount_in_words or \"\") + \"<br>\"),\n (_(\"Remarks\"), doc.remark)\n ) -%}\n <div class=\"row\">\n <div class=\"col-sm-3\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-sm-9\">{{ value }}</div>\n </div>\n\n {%- endfor -%}\n\n <hr>\n <br>\n <p class=\"strong\">\n {{ _(\"For\") }} {{ doc.company }},<br>\n <br>\n <br>\n <br>\n {{ _(\"Authorized Signatory\") }}\n </p>\n</div>\n\n",
|
||||
"html": "{%- from \"templates/print_formats/standard_macros.html\" import add_header -%}\n<div class=\"page-break\">\n {%- if not doc.get(\"print_heading\") and not doc.get(\"select_print_heading\") \n and doc.set(\"select_print_heading\", _(\"Payment Receipt Note\")) -%}{%- endif -%}\n {{ add_header(0, 1, doc, letter_head, no_letterhead) }}\n\n {%- for label, value in (\n (_(\"Received On\"), frappe.utils.formatdate(doc.voucher_date)),\n (_(\"Received From\"), doc.pay_to_recd_from),\n (_(\"Amount\"), \"<strong>\" + doc.total_amount or 0 + \"</strong><br>\" + (doc.total_amount_in_words or \"\") + \"<br>\"),\n (_(\"Remarks\"), doc.remark)\n ) -%}\n <div class=\"row\">\n <div class=\"col-sm-3\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-sm-9\">{{ value }}</div>\n </div>\n\n {%- endfor -%}\n\n <hr>\n <br>\n <p class=\"strong\">\n {{ _(\"For\") }} {{ doc.company }},<br>\n <br>\n <br>\n <br>\n {{ _(\"Authorized Signatory\") }}\n </p>\n</div>\n\n",
|
||||
"idx": 1,
|
||||
"modified": "2014-08-29 15:55:34.248384",
|
||||
"modified": "2014-11-04 11:25:57.560873",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Receipt Voucher",
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
"doc_type": "Sales Invoice",
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Format",
|
||||
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"60%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"10%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Rate\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.entries -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}</td>\n\t\t\t<td class=\"text-right\">{{ item.amount }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ _(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"net_total_export\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- for row in doc.other_charges -%}\n\t\t{%- if not row.included_in_print_rate -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total_export\") }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n{% if doc.get(\"other_charges\", filters={\"included_in_print_rate\": 1}) %}\n<hr>\n<p><b>Taxes Included:</b></p>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t{%- for row in doc.other_charges -%}\n\t\t{%- if row.included_in_print_rate -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t</td>\n\t\t<tr>\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n{%- endif -%}\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
|
||||
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"60%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"10%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Rate\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.entries -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}</td>\n\t\t\t<td class=\"text-right\">{{ item.amount }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ _(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"net_total_export\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- for row in doc.other_charges -%}\n\t\t{%- if not row.included_in_print_rate -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total_export\") }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n{% if doc.get(\"other_charges\", filters={\"included_in_print_rate\": 1}) %}\n<hr>\n<p><b>Taxes Included:</b></p>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t{%- for row in doc.other_charges -%}\n\t\t{%- if row.included_in_print_rate -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ row.get_formatted(\"tax_amount_after_discount_amount\", doc) }}\n\t\t\t</td>\n\t\t<tr>\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n{%- endif -%}\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
|
||||
"idx": 1,
|
||||
"modified": "2014-07-22 02:08:26.603223",
|
||||
"modified": "2014-12-10 12:37:10.854370",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Invoice",
|
||||
|
||||
@@ -13,17 +13,17 @@ class AccountsReceivableReport(object):
|
||||
self.age_as_on = getdate(nowdate()) \
|
||||
if self.filters.report_date > getdate(nowdate()) \
|
||||
else self.filters.report_date
|
||||
|
||||
|
||||
def run(self):
|
||||
customer_naming_by = frappe.db.get_value("Selling Settings", None, "cust_master_name")
|
||||
return self.get_columns(customer_naming_by), self.get_data(customer_naming_by)
|
||||
|
||||
|
||||
def get_columns(self, customer_naming_by):
|
||||
columns = [
|
||||
_("Posting Date") + ":Date:80", _("Account") + ":Link/Account:150",
|
||||
_("Voucher Type") + "::110", _("Voucher No") + ":Dynamic Link/Voucher Type:120",
|
||||
_("Due Date") + ":Date:80",
|
||||
_("Invoiced Amount") + ":Currency:100", _("Payment Received") + ":Currency:100",
|
||||
_("Due Date") + ":Date:80",
|
||||
_("Invoiced Amount") + ":Currency:100", _("Payment Received") + ":Currency:100",
|
||||
_("Outstanding Amount") + ":Currency:100", _("Age") + ":Int:50", "0-30:Currency:100",
|
||||
"30-60:Currency:100", "60-90:Currency:100", _("90-Above") + ":Currency:100",
|
||||
_("Customer") + ":Link/Customer:200"
|
||||
@@ -69,27 +69,27 @@ class AccountsReceivableReport(object):
|
||||
# returns a distinct list
|
||||
return list(set([(e.voucher_type, e.voucher_no) for e in self.get_gl_entries()
|
||||
if getdate(e.posting_date) > report_date]))
|
||||
|
||||
|
||||
def get_entries_till(self, report_date):
|
||||
# returns a generator
|
||||
return (e for e in self.get_gl_entries()
|
||||
return (e for e in self.get_gl_entries()
|
||||
if getdate(e.posting_date) <= report_date)
|
||||
|
||||
|
||||
def is_receivable(self, gle, future_vouchers):
|
||||
return (
|
||||
# advance
|
||||
(not gle.against_voucher) or
|
||||
(not gle.against_voucher) or
|
||||
|
||||
# against sales order
|
||||
(gle.against_voucher_type == "Sales Order") or
|
||||
|
||||
|
||||
# sales invoice
|
||||
(gle.against_voucher==gle.voucher_no and gle.debit > 0) or
|
||||
|
||||
(gle.against_voucher==gle.voucher_no and gle.debit > 0) or
|
||||
|
||||
# entries adjusted with future vouchers
|
||||
((gle.against_voucher_type, gle.against_voucher) in future_vouchers)
|
||||
)
|
||||
|
||||
|
||||
def get_outstanding_amount(self, gle, report_date):
|
||||
payment_received = 0.0
|
||||
for e in self.get_gl_entries_for(gle.account, gle.voucher_type, gle.voucher_no):
|
||||
@@ -97,7 +97,7 @@ class AccountsReceivableReport(object):
|
||||
payment_received += (flt(e.credit) - flt(e.debit))
|
||||
|
||||
return flt(gle.debit) - flt(gle.credit) - payment_received
|
||||
|
||||
|
||||
def get_customer(self, account):
|
||||
return self.get_account_map().get(account, {}).get("customer") or ""
|
||||
|
||||
@@ -106,25 +106,25 @@ class AccountsReceivableReport(object):
|
||||
|
||||
def get_territory(self, account):
|
||||
return self.get_account_map().get(account, {}).get("territory") or ""
|
||||
|
||||
|
||||
def get_account_map(self):
|
||||
if not hasattr(self, "account_map"):
|
||||
self.account_map = dict(((r.name, r) for r in frappe.db.sql("""select
|
||||
self.account_map = dict(((r.name, r) for r in frappe.db.sql("""select
|
||||
acc.name, cust.name as customer, cust.customer_name, cust.territory
|
||||
from `tabAccount` acc left join `tabCustomer` cust
|
||||
from `tabAccount` acc left join `tabCustomer` cust
|
||||
on cust.name=acc.master_name where acc.master_type="Customer" """, as_dict=True)))
|
||||
|
||||
|
||||
return self.account_map
|
||||
|
||||
|
||||
def get_due_date(self, gle):
|
||||
if not hasattr(self, "invoice_due_date_map"):
|
||||
# TODO can be restricted to posting date
|
||||
self.invoice_due_date_map = dict(frappe.db.sql("""select name, due_date
|
||||
from `tabSales Invoice` where docstatus=1"""))
|
||||
|
||||
|
||||
return gle.voucher_type == "Sales Invoice" \
|
||||
and self.invoice_due_date_map.get(gle.voucher_no) or ""
|
||||
|
||||
|
||||
def get_gl_entries(self):
|
||||
if not hasattr(self, "gl_entries"):
|
||||
conditions, values = self.prepare_conditions()
|
||||
@@ -132,15 +132,15 @@ class AccountsReceivableReport(object):
|
||||
where docstatus < 2 {0} order by posting_date, account""".format(conditions),
|
||||
values, as_dict=True)
|
||||
return self.gl_entries
|
||||
|
||||
|
||||
def prepare_conditions(self):
|
||||
conditions = [""]
|
||||
values = {}
|
||||
|
||||
|
||||
if self.filters.company:
|
||||
conditions.append("company=%(company)s")
|
||||
values["company"] = self.filters.company
|
||||
|
||||
|
||||
if self.filters.account:
|
||||
conditions.append("account=%(account)s")
|
||||
values["account"] = self.filters.account
|
||||
@@ -149,11 +149,11 @@ class AccountsReceivableReport(object):
|
||||
if not account_map:
|
||||
frappe.throw(_("No Customer Accounts found."))
|
||||
else:
|
||||
accounts_list = ['"{0}"'.format(ac) for ac in account_map]
|
||||
accounts_list = ['"{0}"'.format(ac.replace('"', '\"')) for ac in account_map]
|
||||
conditions.append("account in ({0})".format(", ".join(accounts_list)))
|
||||
|
||||
|
||||
return " and ".join(conditions), values
|
||||
|
||||
|
||||
def get_gl_entries_for(self, account, against_voucher_type, against_voucher):
|
||||
if not hasattr(self, "gl_entries_map"):
|
||||
self.gl_entries_map = {}
|
||||
@@ -163,7 +163,7 @@ class AccountsReceivableReport(object):
|
||||
.setdefault(gle.against_voucher_type, {})\
|
||||
.setdefault(gle.against_voucher, [])\
|
||||
.append(gle)
|
||||
|
||||
|
||||
return self.gl_entries_map.get(account, {})\
|
||||
.get(against_voucher_type, {})\
|
||||
.get(against_voucher, [])
|
||||
@@ -176,15 +176,15 @@ def get_ageing_data(age_as_on, entry_date, outstanding_amount):
|
||||
outstanding_range = [0.0, 0.0, 0.0, 0.0]
|
||||
if not (age_as_on and entry_date):
|
||||
return [0] + outstanding_range
|
||||
|
||||
|
||||
age = (getdate(age_as_on) - getdate(entry_date)).days or 0
|
||||
index = None
|
||||
for i, days in enumerate([30, 60, 90]):
|
||||
if age <= days:
|
||||
index = i
|
||||
break
|
||||
|
||||
|
||||
if index is None: index = 3
|
||||
outstanding_range[index] = outstanding_amount
|
||||
|
||||
|
||||
return [age] + outstanding_range
|
||||
|
||||
@@ -28,7 +28,7 @@ def get_fiscal_years(date=None, fiscal_year=None, label="Date", verbose=1):
|
||||
from `tabFiscal Year` where %s order by year_start_date desc""" % cond)
|
||||
|
||||
if not fy:
|
||||
error_msg = _("""{0} {1} not in any Fiscal Year""").format(label, formatdate(date))
|
||||
error_msg = _("""{0} {1} not in any Fiscal Year. For more details check {2}.""").format(label, formatdate(date), "https://erpnext.com/kb/accounts/fiscal-year-error")
|
||||
if verbose: frappe.msgprint(error_msg)
|
||||
raise FiscalYearError, error_msg
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
},
|
||||
|
||||
contact_person: function() {
|
||||
this.supplier_address();
|
||||
erpnext.utils.get_contact_details(this.frm);
|
||||
},
|
||||
|
||||
buying_price_list: function() {
|
||||
@@ -210,14 +210,16 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
calculate_totals: function() {
|
||||
var tax_count = this.frm.tax_doclist.length;
|
||||
this.frm.doc.grand_total = flt(tax_count ?
|
||||
this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
|
||||
precision("grand_total"));
|
||||
this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total /
|
||||
this.frm.doc.conversion_rate, precision("grand_total_import"));
|
||||
this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total);
|
||||
this.frm.doc.grand_total_import = flt(tax_count ?
|
||||
flt(this.frm.doc.grand_total / this.frm.doc.conversion_rate) : this.frm.doc.net_total_import);
|
||||
|
||||
this.frm.doc.total_tax = flt(this.frm.doc.grand_total - this.frm.doc.net_total,
|
||||
precision("total_tax"));
|
||||
|
||||
this.frm.doc.grand_total = flt(this.frm.doc.grand_total, precision("grand_total"));
|
||||
this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total_import, precision("grand_total_import"));
|
||||
|
||||
// rounded totals
|
||||
if(frappe.meta.get_docfield(this.frm.doc.doctype, "rounded_total", this.frm.doc.name)) {
|
||||
this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total);
|
||||
|
||||
@@ -3,15 +3,13 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import cstr, flt
|
||||
from frappe.utils import flt
|
||||
from frappe import _
|
||||
|
||||
from erpnext.stock.doctype.item.item import get_last_purchase_details
|
||||
from erpnext.controllers.buying_controller import BuyingController
|
||||
|
||||
class PurchaseCommon(BuyingController):
|
||||
|
||||
def update_last_purchase_rate(self, obj, is_submit):
|
||||
"""updates last_purchase_rate in item table for each item"""
|
||||
|
||||
@@ -123,27 +121,6 @@ class PurchaseCommon(BuyingController):
|
||||
else:
|
||||
chk_dupl_itm.append(f)
|
||||
|
||||
def get_qty(self, curr_doctype, ref_tab_fname, ref_tab_dn, ref_doc_tname, transaction, curr_parent_name):
|
||||
# Get total Quantities of current doctype (eg. PR) except for qty of this transaction
|
||||
#------------------------------
|
||||
# please check as UOM changes from Material Request - Purchase Order ,so doing following else uom should be same .
|
||||
# i.e. in PO uom is NOS then in PR uom should be NOS
|
||||
# but if in Material Request uom KG it can change in PO
|
||||
|
||||
get_qty = (transaction == 'Material Request - Purchase Order') and 'qty * conversion_factor' or 'qty'
|
||||
qty = frappe.db.sql("""select sum(%s) from `tab%s` where %s = %s and
|
||||
docstatus = 1 and parent != %s""" % (get_qty, curr_doctype, ref_tab_fname, '%s', '%s'),
|
||||
(ref_tab_dn, curr_parent_name))
|
||||
qty = qty and flt(qty[0][0]) or 0
|
||||
|
||||
# get total qty of ref doctype
|
||||
#--------------------
|
||||
max_qty = frappe.db.sql("""select qty from `tab%s` where name = %s
|
||||
and docstatus = 1""" % (ref_doc_tname, '%s'), ref_tab_dn)
|
||||
max_qty = max_qty and flt(max_qty[0][0]) or 0
|
||||
|
||||
return cstr(qty)+'~~~'+cstr(max_qty)
|
||||
|
||||
def check_for_stopped_status(self, doctype, docname):
|
||||
stopped = frappe.db.sql("""select name from `tab%s` where name = %s and
|
||||
status = 'Stopped'""" % (doctype, '%s'), docname)
|
||||
|
||||
@@ -685,7 +685,8 @@
|
||||
"label": "Recurring Type",
|
||||
"no_copy": 1,
|
||||
"options": "Monthly\nQuarterly\nHalf-yearly\nYearly",
|
||||
"permlevel": 0
|
||||
"permlevel": 0,
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
@@ -695,7 +696,8 @@
|
||||
"fieldtype": "Date",
|
||||
"label": "From Date",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0
|
||||
"permlevel": 0,
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
@@ -705,7 +707,8 @@
|
||||
"fieldtype": "Date",
|
||||
"label": "To Date",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0
|
||||
"permlevel": 0,
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
@@ -772,7 +775,7 @@
|
||||
"icon": "icon-file-text",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-10-08 14:23:29.718779",
|
||||
"modified": "2014-11-27 17:27:38.839440",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
||||
@@ -96,50 +96,45 @@ class PurchaseOrder(BuyingController):
|
||||
check_list.append(d.prevdoc_docname)
|
||||
pc_obj.check_for_stopped_status( d.prevdoc_doctype, d.prevdoc_docname)
|
||||
|
||||
def update_requested_qty(self):
|
||||
material_request_map = {}
|
||||
for d in self.get("po_details"):
|
||||
if d.prevdoc_doctype and d.prevdoc_doctype == "Material Request" and d.prevdoc_detail_docname:
|
||||
material_request_map.setdefault(d.prevdoc_docname, []).append(d.prevdoc_detail_docname)
|
||||
|
||||
def update_bin(self, is_submit, is_stopped = 0):
|
||||
from erpnext.stock.utils import update_bin
|
||||
pc_obj = frappe.get_doc('Purchase Common')
|
||||
for d in self.get('po_details'):
|
||||
#1. Check if is_stock_item == 'Yes'
|
||||
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes":
|
||||
# this happens when item is changed from non-stock to stock item
|
||||
if not d.warehouse:
|
||||
continue
|
||||
for mr, mr_item_rows in material_request_map.items():
|
||||
if mr and mr_item_rows:
|
||||
mr_obj = frappe.get_doc("Material Request", mr)
|
||||
|
||||
ind_qty, po_qty = 0, flt(d.qty) * flt(d.conversion_factor)
|
||||
if is_stopped:
|
||||
po_qty = flt(d.qty) > flt(d.received_qty) and \
|
||||
flt( flt(flt(d.qty) - flt(d.received_qty))*flt(d.conversion_factor)) or 0
|
||||
if mr_obj.status in ["Stopped", "Cancelled"]:
|
||||
frappe.throw(_("Material Request {0} is cancelled or stopped").format(mr), frappe.InvalidStatusError)
|
||||
|
||||
# No updates in Material Request on Stop / Unstop
|
||||
if cstr(d.prevdoc_doctype) == 'Material Request' and not is_stopped:
|
||||
# get qty and pending_qty of prevdoc
|
||||
curr_ref_qty = pc_obj.get_qty(d.doctype, 'prevdoc_detail_docname',
|
||||
d.prevdoc_detail_docname, 'Material Request Item',
|
||||
'Material Request - Purchase Order', self.name)
|
||||
max_qty, qty, curr_qty = flt(curr_ref_qty.split('~~~')[1]), \
|
||||
flt(curr_ref_qty.split('~~~')[0]), 0
|
||||
mr_obj.update_requested_qty(mr_item_rows)
|
||||
|
||||
if flt(qty) + flt(po_qty) > flt(max_qty):
|
||||
curr_qty = flt(max_qty) - flt(qty)
|
||||
# special case as there is no restriction
|
||||
# for Material Request - Purchase Order
|
||||
curr_qty = curr_qty > 0 and curr_qty or 0
|
||||
else:
|
||||
curr_qty = flt(po_qty)
|
||||
def update_ordered_qty(self, po_item_rows=None):
|
||||
"""update requested qty (before ordered_qty is updated)"""
|
||||
from erpnext.stock.utils import get_bin
|
||||
|
||||
ind_qty = -flt(curr_qty)
|
||||
def _update_ordered_qty(item_code, warehouse):
|
||||
ordered_qty = frappe.db.sql("""
|
||||
select sum((po_item.qty - ifnull(po_item.received_qty, 0))*po_item.conversion_factor)
|
||||
from `tabPurchase Order Item` po_item, `tabPurchase Order` po
|
||||
where po_item.item_code=%s and po_item.warehouse=%s
|
||||
and po_item.qty > ifnull(po_item.received_qty, 0) and po_item.parent=po.name
|
||||
and po.status!='Stopped' and po.docstatus=1""", (item_code, warehouse))
|
||||
|
||||
# Update ordered_qty and indented_qty in bin
|
||||
args = {
|
||||
"item_code": d.item_code,
|
||||
"warehouse": d.warehouse,
|
||||
"ordered_qty": (is_submit and 1 or -1) * flt(po_qty),
|
||||
"indented_qty": (is_submit and 1 or -1) * flt(ind_qty),
|
||||
"posting_date": self.transaction_date
|
||||
}
|
||||
update_bin(args)
|
||||
bin_doc = get_bin(item_code, warehouse)
|
||||
bin_doc.ordered_qty = flt(ordered_qty[0][0]) if ordered_qty else 0
|
||||
bin_doc.save()
|
||||
|
||||
item_wh_list = []
|
||||
for d in self.get("po_details"):
|
||||
if (not po_item_rows or d.name in po_item_rows) and [d.item_code, d.warehouse] not in item_wh_list \
|
||||
and frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes" and d.warehouse:
|
||||
item_wh_list.append([d.item_code, d.warehouse])
|
||||
|
||||
for item_code, warehouse in item_wh_list:
|
||||
_update_ordered_qty(item_code, warehouse)
|
||||
|
||||
def check_modified_date(self):
|
||||
mod_db = frappe.db.sql("select modified from `tabPurchase Order` where name = %s",
|
||||
@@ -152,13 +147,11 @@ class PurchaseOrder(BuyingController):
|
||||
|
||||
def update_status(self, status):
|
||||
self.check_modified_date()
|
||||
# step 1:=> Set Status
|
||||
frappe.db.set(self,'status',cstr(status))
|
||||
|
||||
# step 2:=> Update Bin
|
||||
self.update_bin(is_submit = (status == 'Submitted') and 1 or 0, is_stopped = 1)
|
||||
self.update_requested_qty()
|
||||
self.update_ordered_qty()
|
||||
|
||||
# step 3:=> Acknowledge user
|
||||
msgprint(_("Status of {0} {1} is now {2}").format(self.doctype, self.name, status))
|
||||
|
||||
def on_submit(self):
|
||||
@@ -167,7 +160,8 @@ class PurchaseOrder(BuyingController):
|
||||
purchase_controller = frappe.get_doc("Purchase Common")
|
||||
|
||||
self.update_prevdoc_status()
|
||||
self.update_bin(is_submit = 1, is_stopped = 0)
|
||||
self.update_requested_qty()
|
||||
self.update_ordered_qty()
|
||||
|
||||
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
|
||||
self.company, self.grand_total)
|
||||
@@ -192,8 +186,13 @@ class PurchaseOrder(BuyingController):
|
||||
throw(_("Purchase Invoice {0} is already submitted").format(", ".join(submitted)))
|
||||
|
||||
frappe.db.set(self,'status','Cancelled')
|
||||
|
||||
self.update_prevdoc_status()
|
||||
self.update_bin( is_submit = 0, is_stopped = 0)
|
||||
|
||||
# Must be called after updating ordered qty in Material Request
|
||||
self.update_requested_qty()
|
||||
self.update_ordered_qty()
|
||||
|
||||
pc_obj.update_last_purchase_rate(self, is_submit = 0)
|
||||
|
||||
def on_update(self):
|
||||
@@ -248,7 +247,7 @@ def make_purchase_invoice(source_name, target_doc=None):
|
||||
def update_item(obj, target, source_parent):
|
||||
target.amount = flt(obj.amount) - flt(obj.billed_amt)
|
||||
target.base_amount = target.amount * flt(source_parent.conversion_rate)
|
||||
target.qty = target.amount / flt(obj.rate) if flt(obj.rate) else flt(obj.qty)
|
||||
target.qty = target.amount / flt(obj.rate) if (flt(obj.rate) and flt(obj.billed_amt)) else flt(obj.qty)
|
||||
|
||||
doc = get_mapped_doc("Purchase Order", source_name, {
|
||||
"Purchase Order": {
|
||||
|
||||
@@ -29,8 +29,7 @@ class TestPurchaseOrder(unittest.TestCase):
|
||||
frappe.get_doc(pr).insert()
|
||||
|
||||
def test_ordered_qty(self):
|
||||
frappe.db.sql("delete from tabBin")
|
||||
|
||||
existing_ordered_qty = self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC")
|
||||
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
|
||||
|
||||
po = frappe.copy_doc(test_records[0]).insert()
|
||||
@@ -43,8 +42,7 @@ class TestPurchaseOrder(unittest.TestCase):
|
||||
po.get("po_details")[0].item_code = "_Test Item"
|
||||
po.submit()
|
||||
|
||||
self.assertEquals(frappe.db.get_value("Bin", {"item_code": "_Test Item",
|
||||
"warehouse": "_Test Warehouse - _TC"}, "ordered_qty"), 10)
|
||||
self.assertEquals(self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC"), existing_ordered_qty + 10)
|
||||
|
||||
pr = make_purchase_receipt(po.name)
|
||||
|
||||
@@ -56,8 +54,9 @@ class TestPurchaseOrder(unittest.TestCase):
|
||||
pr.insert()
|
||||
pr.submit()
|
||||
|
||||
self.assertEquals(flt(frappe.db.get_value("Bin", {"item_code": "_Test Item",
|
||||
"warehouse": "_Test Warehouse - _TC"}, "ordered_qty")), 6.0)
|
||||
po.load_from_db()
|
||||
self.assertEquals(po.get("po_details")[0].received_qty, 4)
|
||||
self.assertEquals(self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC"), existing_ordered_qty + 6)
|
||||
|
||||
frappe.db.set_value('Item', '_Test Item', 'tolerance', 50)
|
||||
|
||||
@@ -68,8 +67,16 @@ class TestPurchaseOrder(unittest.TestCase):
|
||||
pr1.insert()
|
||||
pr1.submit()
|
||||
|
||||
self.assertEquals(flt(frappe.db.get_value("Bin", {"item_code": "_Test Item",
|
||||
"warehouse": "_Test Warehouse - _TC"}, "ordered_qty")), 0.0)
|
||||
po.load_from_db()
|
||||
self.assertEquals(po.get("po_details")[0].received_qty, 12)
|
||||
self.assertEquals(self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC"), existing_ordered_qty)
|
||||
|
||||
pr1.load_from_db()
|
||||
pr1.cancel()
|
||||
|
||||
po.load_from_db()
|
||||
self.assertEquals(po.get("po_details")[0].received_qty, 4)
|
||||
self.assertEquals(self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC"), existing_ordered_qty + 6)
|
||||
|
||||
def test_make_purchase_invoice(self):
|
||||
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_invoice
|
||||
@@ -111,6 +118,9 @@ class TestPurchaseOrder(unittest.TestCase):
|
||||
from erpnext.controllers.tests.test_recurring_document import test_recurring_document
|
||||
test_recurring_document(self, test_records)
|
||||
|
||||
def _get_ordered_qty(self, item_code, warehouse):
|
||||
return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "ordered_qty"))
|
||||
|
||||
|
||||
test_dependencies = ["BOM", "Item Price"]
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
{% include 'setup/doctype/contact_control/contact_control.js' %};
|
||||
|
||||
cur_frm.cscript.refresh = function(doc, dt, dn) {
|
||||
cur_frm.cscript.make_dashboard(doc);
|
||||
|
||||
@@ -17,15 +15,13 @@ cur_frm.cscript.refresh = function(doc, dt, dn) {
|
||||
}
|
||||
else{
|
||||
unhide_field(['address_html','contact_html']);
|
||||
// make lists
|
||||
cur_frm.cscript.make_address(doc,dt,dn);
|
||||
cur_frm.cscript.make_contact(doc,dt,dn);
|
||||
|
||||
erpnext.utils.render_address_and_contact(cur_frm)
|
||||
|
||||
cur_frm.communication_view = new frappe.views.CommunicationList({
|
||||
list: frappe.get_list("Communication", {"supplier": doc.name}),
|
||||
parent: cur_frm.fields_dict.communication_html.wrapper,
|
||||
doc: doc
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,45 +57,6 @@ cur_frm.cscript.make_dashboard = function(doc) {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
cur_frm.cscript.make_address = function() {
|
||||
if(!cur_frm.address_list) {
|
||||
cur_frm.address_list = new frappe.ui.Listing({
|
||||
parent: cur_frm.fields_dict['address_html'].wrapper,
|
||||
page_length: 5,
|
||||
new_doctype: "Address",
|
||||
get_query: function() {
|
||||
return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where supplier='" +
|
||||
cur_frm.doc.name.replace(/'/g, "\\'") + "' and docstatus != 2 order by is_primary_address desc"
|
||||
},
|
||||
as_dict: 1,
|
||||
no_results_message: __('No addresses created'),
|
||||
render_row: cur_frm.cscript.render_address_row,
|
||||
});
|
||||
// note: render_address_row is defined in contact_control.js
|
||||
}
|
||||
cur_frm.address_list.run();
|
||||
}
|
||||
|
||||
cur_frm.cscript.make_contact = function() {
|
||||
if(!cur_frm.contact_list) {
|
||||
cur_frm.contact_list = new frappe.ui.Listing({
|
||||
parent: cur_frm.fields_dict['contact_html'].wrapper,
|
||||
page_length: 5,
|
||||
new_doctype: "Contact",
|
||||
get_query: function() {
|
||||
return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where supplier='" +
|
||||
cur_frm.doc.name.replace(/'/g, "\\'") + "' and docstatus != 2 order by is_primary_contact desc"
|
||||
},
|
||||
as_dict: 1,
|
||||
no_results_message: __('No contacts created'),
|
||||
render_row: cur_frm.cscript.render_contact_row,
|
||||
});
|
||||
// note: render_contact_row is defined in contact_control.js
|
||||
}
|
||||
cur_frm.contact_list.run();
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['default_price_list'].get_query = function(doc, cdt, cdn) {
|
||||
return{
|
||||
filters:{'buying': 1}
|
||||
|
||||
@@ -9,10 +9,14 @@ from frappe.utils import cint
|
||||
from frappe import msgprint, _
|
||||
from frappe.model.naming import make_autoname
|
||||
from erpnext.accounts.party import create_party_account
|
||||
from erpnext.utilities.address_and_contact import load_address_and_contact
|
||||
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
|
||||
class Supplier(TransactionBase):
|
||||
def onload(self):
|
||||
"""Load address and contacts in `__onload`"""
|
||||
load_address_and_contact(self, "supplier")
|
||||
|
||||
def autoname(self):
|
||||
supp_master_name = frappe.defaults.get_global_default('supp_master_name')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -119,6 +119,10 @@ class AccountsController(TransactionBase):
|
||||
item.get(fieldname) is None and value is not None:
|
||||
item.set(fieldname, value)
|
||||
|
||||
if fieldname == "cost_center" and item.meta.get_field("cost_center") \
|
||||
and not item.get("cost_center") and value is not None:
|
||||
item.set(fieldname, value)
|
||||
|
||||
if ret.get("pricing_rule"):
|
||||
for field in ["base_price_list_rate", "price_list_rate",
|
||||
"discount_percentage", "base_rate", "rate"]:
|
||||
@@ -437,7 +441,7 @@ class AccountsController(TransactionBase):
|
||||
for order, jv_list in order_jv_map.items():
|
||||
for jv in jv_list:
|
||||
if not advance_jv_against_si or jv not in advance_jv_against_si:
|
||||
frappe.throw(_("Journal Voucher {0} is linked against Order {1}, hence it must be fetched as advance in Invoice as well.")
|
||||
frappe.msgprint(_("Journal Voucher {0} is linked against Order {1}, check if it should be pulled as advance in this invoice.")
|
||||
.format(jv, order))
|
||||
|
||||
|
||||
@@ -467,7 +471,7 @@ class AccountsController(TransactionBase):
|
||||
max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100)
|
||||
|
||||
if total_billed_amt - max_allowed_amt > 0.01:
|
||||
frappe.throw(_("Cannot overbill for Item {0} in row {0} more than {1}. To allow overbilling, please set in Stock Settings").format(item.item_code, item.idx, max_allowed_amt))
|
||||
frappe.throw(_("Cannot overbill for Item {0} in row {1} more than {2}. To allow overbilling, please set in Stock Settings").format(item.item_code, item.idx, max_allowed_amt))
|
||||
|
||||
def get_company_default(self, fieldname):
|
||||
from erpnext.accounts.utils import get_company_default
|
||||
|
||||
@@ -110,13 +110,14 @@ class BuyingController(StockController):
|
||||
self.round_floats_in(self, ["net_total", "net_total_import"])
|
||||
|
||||
def calculate_totals(self):
|
||||
self.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist
|
||||
else self.net_total, self.precision("grand_total"))
|
||||
self.grand_total_import = flt(self.grand_total / self.conversion_rate,
|
||||
self.precision("grand_total_import"))
|
||||
self.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist else self.net_total)
|
||||
self.grand_total_import = flt(self.grand_total / self.conversion_rate) \
|
||||
if self.tax_doclist else self.net_total_import
|
||||
|
||||
self.total_tax = flt(self.grand_total - self.net_total,
|
||||
self.precision("total_tax"))
|
||||
self.total_tax = flt(self.grand_total - self.net_total, self.precision("total_tax"))
|
||||
|
||||
self.grand_total = flt(self.grand_total, self.precision("grand_total"))
|
||||
self.grand_total_import = flt(self.grand_total_import, self.precision("grand_total_import"))
|
||||
|
||||
if self.meta.get_field("rounded_total"):
|
||||
self.rounded_total = rounded(self.grand_total)
|
||||
|
||||
@@ -124,10 +124,7 @@ def send_notification(new_rv):
|
||||
frappe.sendmail(new_rv.notification_email_address,
|
||||
subject= _("New {0}: #{1}").format(new_rv.doctype, new_rv.name),
|
||||
message = _("Please find attached {0} #{1}").format(new_rv.doctype, new_rv.name),
|
||||
attachments = [{
|
||||
"fname": new_rv.name + ".pdf",
|
||||
"fcontent": frappe.get_print_format(new_rv.doctype, new_rv.name, as_pdf=True)
|
||||
}])
|
||||
attachments = [frappe.attach_print(new_rv.doctype, new_rv.name, file_name=new_rv.name)])
|
||||
|
||||
def notify_errors(doc, doctype, party, owner):
|
||||
from frappe.utils.user import get_system_managers
|
||||
|
||||
@@ -216,17 +216,18 @@ class SellingController(StockController):
|
||||
self.round_floats_in(self, ["net_total", "net_total_export"])
|
||||
|
||||
def calculate_totals(self):
|
||||
self.grand_total = flt(self.tax_doclist and \
|
||||
self.tax_doclist[-1].total or self.net_total, self.precision("grand_total"))
|
||||
self.grand_total_export = flt(self.grand_total / self.conversion_rate,
|
||||
self.precision("grand_total_export"))
|
||||
self.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist else self.net_total)
|
||||
|
||||
self.other_charges_total = flt(self.grand_total - self.net_total,
|
||||
self.precision("other_charges_total"))
|
||||
self.grand_total_export = flt(self.grand_total / self.conversion_rate) \
|
||||
if self.tax_doclist else self.net_total_export
|
||||
|
||||
self.other_charges_total_export = flt(self.grand_total_export -
|
||||
self.net_total_export + flt(self.discount_amount),
|
||||
self.precision("other_charges_total_export"))
|
||||
self.other_charges_total = flt(self.grand_total - self.net_total, self.precision("other_charges_total"))
|
||||
|
||||
self.other_charges_total_export = flt(self.grand_total_export - self.net_total_export +
|
||||
flt(self.discount_amount), self.precision("other_charges_total_export"))
|
||||
|
||||
self.grand_total = flt(self.grand_total, self.precision("grand_total"))
|
||||
self.grand_total_export = flt(self.grand_total_export, self.precision("grand_total_export"))
|
||||
|
||||
self.rounded_total = rounded(self.grand_total)
|
||||
self.rounded_total_export = rounded(self.grand_total_export)
|
||||
|
||||
@@ -167,7 +167,7 @@ class StockController(AccountsController):
|
||||
else:
|
||||
is_expense_account = frappe.db.get_value("Account",
|
||||
item.get("expense_account"), "report_type")=="Profit and Loss"
|
||||
if self.doctype not in ("Purchase Receipt", "Stock Reconciliation") and not is_expense_account:
|
||||
if self.doctype not in ("Purchase Receipt", "Stock Reconciliation", "Stock Entry") and not is_expense_account:
|
||||
frappe.throw(_("Expense / Difference account ({0}) must be a 'Profit or Loss' account")
|
||||
.format(item.get("expense_account")))
|
||||
if is_expense_account and not item.get("cost_center"):
|
||||
@@ -175,7 +175,7 @@ class StockController(AccountsController):
|
||||
_(self.doctype), self.name, item.get("item_code")))
|
||||
|
||||
def get_sl_entries(self, d, args):
|
||||
sl_dict = {
|
||||
sl_dict = frappe._dict({
|
||||
"item_code": d.get("item_code", None),
|
||||
"warehouse": d.get("warehouse", None),
|
||||
"posting_date": self.posting_date,
|
||||
@@ -192,7 +192,7 @@ class StockController(AccountsController):
|
||||
"serial_no": d.get("serial_no"),
|
||||
"project": d.get("project_name"),
|
||||
"is_cancelled": self.docstatus==2 and "Yes" or "No"
|
||||
}
|
||||
})
|
||||
|
||||
sl_dict.update(args)
|
||||
return sl_dict
|
||||
|
||||
@@ -4,7 +4,7 @@ app_publisher = "Web Notes Technologies Pvt. Ltd. and Contributors"
|
||||
app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
|
||||
app_icon = "icon-th"
|
||||
app_color = "#e74c3c"
|
||||
app_version = "4.7.2"
|
||||
app_version = "4.16.0"
|
||||
|
||||
error_report_email = "support@erpnext.com"
|
||||
|
||||
@@ -47,8 +47,8 @@ doc_events = {
|
||||
"on_update": "erpnext.home.make_comment_feed"
|
||||
},
|
||||
"Stock Entry": {
|
||||
"on_submit": "erpnext.stock.doctype.material_request.material_request.update_completed_qty",
|
||||
"on_cancel": "erpnext.stock.doctype.material_request.material_request.update_completed_qty"
|
||||
"on_submit": "erpnext.stock.doctype.material_request.material_request.update_completed_and_requested_qty",
|
||||
"on_cancel": "erpnext.stock.doctype.material_request.material_request.update_completed_and_requested_qty"
|
||||
},
|
||||
"User": {
|
||||
"validate": "erpnext.hr.doctype.employee.employee.validate_employee_role",
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
{
|
||||
"autoname": "EXP.######",
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-01-10 16:34:14",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
{
|
||||
"default": "EXP",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Series",
|
||||
"no_copy": 1,
|
||||
"options": "EXP",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "Draft",
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
@@ -190,7 +202,7 @@
|
||||
"icon": "icon-money",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-08-27 07:08:48.454580",
|
||||
"modified": "2014-11-24 18:25:53.038826",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Expense Claim",
|
||||
|
||||
@@ -104,9 +104,32 @@ cur_frm.cscript.calculate_total_days = function(doc, dt, dn) {
|
||||
if(cint(doc.half_day) == 1) set_multiple(dt,dn,{total_leave_days:0.5});
|
||||
else{
|
||||
// server call is done to include holidays in leave days calculations
|
||||
return get_server_fields('get_total_leave_days', '', '', doc, dt, dn, 1);
|
||||
return frappe.call({
|
||||
method: 'erpnext.hr.doctype.leave_application.leave_application.get_total_leave_days',
|
||||
args: {leave_app: doc},
|
||||
callback: function(response) {
|
||||
if (response && response.message) {
|
||||
cur_frm.set_value('total_leave_days', response.message.total_leave_days);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.fields_dict.employee.get_query = erpnext.queries.employee;
|
||||
|
||||
frappe.ui.form.on("Leave Application", "leave_approver", function(frm) {
|
||||
frappe.call({
|
||||
"method": "frappe.client.get",
|
||||
args: {
|
||||
doctype: "User",
|
||||
name: frm.doc.leave_approver
|
||||
},
|
||||
callback: function (data) {
|
||||
frappe.model.set_value(frm.doctype, frm.docname, "leave_approver_name",
|
||||
data.message.first_name
|
||||
+ (data.message.last_name ? (" " + data.message.last_name) : ""))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -24,6 +24,13 @@
|
||||
"options": "User",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "leave_approver_name",
|
||||
"fieldtype": "Read Only",
|
||||
"label": "Leave Approver Name",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "leave_type",
|
||||
"fieldtype": "Link",
|
||||
@@ -184,7 +191,7 @@
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"max_attachments": 3,
|
||||
"modified": "2014-09-09 05:35:31.531651",
|
||||
"modified": "2014-12-09 16:33:29.626849",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Leave Application",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import frappe, json
|
||||
from frappe import _
|
||||
|
||||
from frappe.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_url_to_form, \
|
||||
@@ -77,26 +77,10 @@ class LeaveApplication(Document):
|
||||
LeaveDayBlockedError)
|
||||
|
||||
def get_holidays(self):
|
||||
tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2, `tabEmployee` e1
|
||||
where e1.name = %s and h1.parent = h2.name and e1.holiday_list = h2.name
|
||||
and h1.holiday_date between %s and %s""", (self.employee, self.from_date, self.to_date))
|
||||
if not tot_hol:
|
||||
tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2
|
||||
where h1.parent = h2.name and h1.holiday_date between %s and %s
|
||||
and ifnull(h2.is_default,0) = 1 and h2.fiscal_year = %s""",
|
||||
(self.from_date, self.to_date, self.fiscal_year))
|
||||
return tot_hol and flt(tot_hol[0][0]) or 0
|
||||
return get_holidays(self)
|
||||
|
||||
def get_total_leave_days(self):
|
||||
"""Calculates total leave days based on input and holidays"""
|
||||
ret = {'total_leave_days' : 0.5}
|
||||
if not self.half_day:
|
||||
tot_days = date_diff(self.to_date, self.from_date) + 1
|
||||
holidays = self.get_holidays()
|
||||
ret = {
|
||||
'total_leave_days' : flt(tot_days)-flt(holidays)
|
||||
}
|
||||
return ret
|
||||
return get_total_leave_days(self)
|
||||
|
||||
def validate_to_date(self):
|
||||
if self.from_date and self.to_date and \
|
||||
@@ -216,6 +200,35 @@ class LeaveApplication(Document):
|
||||
post(**{"txt": args.message, "contact": args.message_to, "subject": args.subject,
|
||||
"notify": cint(self.follow_via_email)})
|
||||
|
||||
def get_holidays(leave_app):
|
||||
tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2, `tabEmployee` e1
|
||||
where e1.name = %s and h1.parent = h2.name and e1.holiday_list = h2.name
|
||||
and h1.holiday_date between %s and %s""", (leave_app.employee, leave_app.from_date,
|
||||
leave_app.to_date))[0][0]
|
||||
# below line is needed. If an employee hasn't been assigned with any holiday list then above will return 0 rows.
|
||||
if not tot_hol:
|
||||
tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2
|
||||
where h1.parent = h2.name and h1.holiday_date between %s and %s
|
||||
and ifnull(h2.is_default,0) = 1 and h2.fiscal_year = %s""",
|
||||
(leave_app.from_date, leave_app.to_date, leave_app.fiscal_year))[0][0]
|
||||
return tot_hol
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_total_leave_days(leave_app):
|
||||
# Parse Leave Application if neccessary
|
||||
if isinstance(leave_app, str) or isinstance(leave_app, unicode):
|
||||
leave_app = frappe.get_doc(json.loads(leave_app))
|
||||
|
||||
"""Calculates total leave days based on input and holidays"""
|
||||
ret = {'total_leave_days' : 0.5}
|
||||
if not leave_app.half_day:
|
||||
tot_days = date_diff(leave_app.to_date, leave_app.from_date) + 1
|
||||
holidays = leave_app.get_holidays()
|
||||
ret = {
|
||||
'total_leave_days' : flt(tot_days)-flt(holidays)
|
||||
}
|
||||
return ret
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_leave_balance(employee, leave_type, fiscal_year):
|
||||
leave_all = frappe.db.sql("""select total_leaves_allocated
|
||||
|
||||
@@ -156,7 +156,7 @@ class SalarySlip(TransactionBase):
|
||||
/ cint(self.total_days_in_month), 2)
|
||||
elif not self.payment_days:
|
||||
d.e_modified_amount = 0
|
||||
else:
|
||||
elif not d.e_modified_amount:
|
||||
d.e_modified_amount = d.e_amount
|
||||
self.gross_pay += flt(d.e_modified_amount)
|
||||
|
||||
@@ -168,7 +168,7 @@ class SalarySlip(TransactionBase):
|
||||
/ cint(self.total_days_in_month), 2)
|
||||
elif not self.payment_days:
|
||||
d.d_modified_amount = 0
|
||||
else:
|
||||
elif not d.d_modified_amount:
|
||||
d.d_modified_amount = d.d_amount
|
||||
|
||||
self.total_deduction += flt(d.d_modified_amount)
|
||||
@@ -191,9 +191,6 @@ class SalarySlip(TransactionBase):
|
||||
if receiver:
|
||||
subj = 'Salary Slip - ' + cstr(self.month) +'/'+cstr(self.fiscal_year)
|
||||
sendmail([receiver], subject=subj, msg = _("Please see attachment"),
|
||||
attachments=[{
|
||||
"fname": self.name + ".pdf",
|
||||
"fcontent": frappe.get_print_format(self.doctype, self.name, as_pdf = True)
|
||||
}])
|
||||
attachments=[frappe.attach_print(self.doctype, self.name, file_name=self.name)])
|
||||
else:
|
||||
msgprint(_("Company Email ID not found, hence mail not sent"))
|
||||
|
||||
@@ -83,6 +83,7 @@ cur_frm.cscript.hour_rate = function(doc, dt, dn) {
|
||||
|
||||
|
||||
cur_frm.cscript.time_in_mins = cur_frm.cscript.hour_rate;
|
||||
cur_frm.cscript.fixed_cycle_cost = cur_frm.cscript.hour_rate;
|
||||
|
||||
cur_frm.cscript.item_code = function(doc, cdt, cdn) {
|
||||
get_bom_material_detail(doc, cdt, cdn);
|
||||
|
||||
@@ -57,6 +57,9 @@ class BOM(Document):
|
||||
last_purchase_rate, is_manufactured_item
|
||||
from `tabItem` where name=%s""", item_code, as_dict = 1)
|
||||
|
||||
if not item:
|
||||
frappe.throw(_("Item: {0} does not exist in the system").format(item_code))
|
||||
|
||||
return item
|
||||
|
||||
def validate_rm_item(self, item):
|
||||
@@ -285,7 +288,10 @@ class BOM(Document):
|
||||
if not d.hour_rate:
|
||||
d.hour_rate = flt(w[0])
|
||||
|
||||
fixed_cost += flt(w[1])
|
||||
if d.fixed_cycle_cost == None:
|
||||
d.fixed_cycle_cost= flt(w[1])
|
||||
|
||||
fixed_cost += d.fixed_cycle_cost
|
||||
|
||||
if d.hour_rate and d.time_in_mins:
|
||||
d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60.0
|
||||
|
||||
@@ -87,3 +87,6 @@ execute:frappe.delete_doc("DocType", "Purchase Request")
|
||||
execute:frappe.delete_doc("DocType", "Purchase Request Item")
|
||||
erpnext.patches.v4_2.recalculate_bom_cost
|
||||
erpnext.patches.v4_2.fix_gl_entries_for_stock_transactions
|
||||
erpnext.patches.v4_2.update_requested_and_ordered_qty
|
||||
execute:frappe.delete_doc("DocType", "Contact Control")
|
||||
erpnext.patches.v4_2.recalculate_bom_costs
|
||||
|
||||
@@ -6,6 +6,7 @@ import frappe
|
||||
|
||||
def execute():
|
||||
reference_date = guess_reference_date()
|
||||
frappe.reload_doc('accounts', 'doctype', 'journal_voucher_detail')
|
||||
for name in frappe.db.sql_list("""select name from `tabJournal Voucher`
|
||||
where date(creation)>=%s""", reference_date):
|
||||
jv = frappe.get_doc("Journal Voucher", name)
|
||||
|
||||
19
erpnext/patches/v4_2/recalculate_bom_costs.py
Normal file
19
erpnext/patches/v4_2/recalculate_bom_costs.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('manufacturing', 'doctype', 'bom_operation')
|
||||
for d in frappe.db.sql("""select bom.name from `tabBOM` bom where bom.docstatus < 2 and
|
||||
exists(select bom_op.name from `tabBOM Operation` bom_op where
|
||||
bom.name = bom_op.parent and bom_op.fixed_cycle_cost IS NOT NULL)""", as_dict=1):
|
||||
try:
|
||||
bom = frappe.get_doc('BOM', d.name)
|
||||
bom.ignore_validate_update_after_submit = True
|
||||
bom.calculate_cost()
|
||||
bom.save()
|
||||
frappe.db.commit()
|
||||
except:
|
||||
frappe.db.rollback()
|
||||
24
erpnext/patches/v4_2/update_requested_and_ordered_qty.py
Normal file
24
erpnext/patches/v4_2/update_requested_and_ordered_qty.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
from erpnext.utilities.repost_stock import update_bin_qty, get_indented_qty, get_ordered_qty
|
||||
|
||||
count=0
|
||||
for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse from
|
||||
(select item_code, warehouse from tabBin
|
||||
union
|
||||
select item_code, warehouse from `tabStock Ledger Entry`) a"""):
|
||||
try:
|
||||
count += 1
|
||||
update_bin_qty(item_code, warehouse, {
|
||||
"indented_qty": get_indented_qty(item_code, warehouse),
|
||||
"ordered_qty": get_ordered_qty(item_code, warehouse)
|
||||
})
|
||||
if count % 200 == 0:
|
||||
frappe.db.commit()
|
||||
except:
|
||||
frappe.db.rollback()
|
||||
@@ -16,6 +16,15 @@ class TestTimeLog(unittest.TestCase):
|
||||
self.assertRaises(OverlapError, ts.insert)
|
||||
|
||||
frappe.db.sql("delete from `tabTime Log`")
|
||||
|
||||
def test_negative_hours(self):
|
||||
frappe.db.sql("delete from `tabTime Log`")
|
||||
test_time_log = frappe.new_doc("Time Log")
|
||||
test_time_log.activity_type = "Communication"
|
||||
test_time_log.from_time = "2013-01-01 11:00:00.000000"
|
||||
test_time_log.to_time = "2013-01-01 10:00:00.000000"
|
||||
self.assertRaises(frappe.ValidationError, test_time_log.save)
|
||||
frappe.db.sql("delete from `tabTime Log`")
|
||||
|
||||
test_records = frappe.get_test_records('Time Log')
|
||||
test_ignore = ["Time Log Batch", "Sales Invoice"]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"allow_import": 1,
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-04-03 16:38:41",
|
||||
"description": "Log of Activities performed by users against Tasks that can be used for tracking time, billing.",
|
||||
@@ -25,14 +25,6 @@
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "hours",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Hours",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "to_time",
|
||||
"fieldtype": "Datetime",
|
||||
@@ -42,6 +34,14 @@
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "hours",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Hours",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
@@ -151,7 +151,7 @@
|
||||
"icon": "icon-time",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-08-04 05:23:15.740050",
|
||||
"modified": "2014-10-22 16:53:26.993828",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Time Log",
|
||||
|
||||
@@ -19,10 +19,12 @@ class TimeLog(Document):
|
||||
self.set_status()
|
||||
self.validate_overlap()
|
||||
self.calculate_total_hours()
|
||||
|
||||
|
||||
def calculate_total_hours(self):
|
||||
from frappe.utils import time_diff_in_hours
|
||||
self.hours = time_diff_in_hours(self.to_time, self.from_time)
|
||||
if self.hours < 0:
|
||||
frappe.throw(_("'From Time' cannot be later than 'To Time'"))
|
||||
|
||||
def set_status(self):
|
||||
self.status = {
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
"public/js/feature_setup.js",
|
||||
"public/js/utils.js",
|
||||
"public/js/queries.js",
|
||||
"public/js/utils/party.js"
|
||||
"public/js/utils/party.js",
|
||||
"public/js/templates/address_list.html",
|
||||
"public/js/templates/contact_list.html"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
|
||||
// otherwise, only reset values
|
||||
$.each(this.data, function(i, d) {
|
||||
me.reset_item_values(d);
|
||||
d["closing_qty_value"] = 0;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -131,6 +132,7 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
|
||||
|
||||
if(me.is_default("warehouse") ? true : me.warehouse == sl.warehouse) {
|
||||
var item = me.item_by_name[sl.item_code];
|
||||
if(item.closing_qty_value==undefined) item.closing_qty_value = 0;
|
||||
|
||||
if(me.value_or_qty!="Quantity") {
|
||||
var wh = me.get_item_warehouse(sl.warehouse, sl.item_code);
|
||||
|
||||
20
erpnext/public/js/templates/address_list.html
Normal file
20
erpnext/public/js/templates/address_list.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<p><button class="btn btn-sm btn-default btn-address">
|
||||
<i class="icon-plus"></i> New Address</button></p>
|
||||
{% for(var i=0, l=addr_list.length; i<l; i++) { %}
|
||||
<hr>
|
||||
<a href="#Form/Address/{%= addr_list[i].name %}" class="btn btn-sm btn-default pull-right">
|
||||
{%= __("Edit") %}</a>
|
||||
<p><b>{%= i+1 %}. {%= addr_list[i].address_type %}</b></p>
|
||||
<div style="padding-left: 15px;">
|
||||
<div>
|
||||
{% if(addr_list[i].is_primary_address) { %}<span class="label label-info">
|
||||
{%= __("Primary") %}</span>{% } %}
|
||||
{% if(addr_list[i].is_shipping_address) { %}<span class="label label-default">
|
||||
{%= __("Shipping") %}</span>{% } %}
|
||||
</div>
|
||||
<p style="margin-top: 5px;">{%= addr_list[i].display %}</p>
|
||||
</div>
|
||||
{% } %}
|
||||
{% if(!addr_list.length) { %}
|
||||
<p class="text-muted">{%= __("No address added yet.") %}</p>
|
||||
{% } %}
|
||||
28
erpnext/public/js/templates/contact_list.html
Normal file
28
erpnext/public/js/templates/contact_list.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<p><button class="btn btn-sm btn-default btn-contact">
|
||||
<i class="icon-plus"></i> New Contact</button></p>
|
||||
{% for(var i=0, l=contact_list.length; i<l; i++) { %}
|
||||
<hr>
|
||||
<a href="#Form/Contact/{%= contact_list[i].name %}" class="btn btn-sm btn-default pull-right">
|
||||
{%= __("Edit") %}</a>
|
||||
<p><b>{%= i+1 %}. {%= contact_list[i].first_name %} {%= contact_list[i].last_name %}</b></p>
|
||||
<div style="padding-left: 15px;">
|
||||
<div>
|
||||
{% if(contact_list[i].is_primary_contact) { %}<span class="label label-info">
|
||||
{%= __("Primary") %}</span>{% } %}
|
||||
</div>
|
||||
<p style="padding-top: 5px;">
|
||||
{% if(contact_list[i].phone) { %}
|
||||
{%= __("Phone") %}: {%= contact_list[i].phone %}<br>
|
||||
{% } %}
|
||||
{% if(contact_list[i].mobile_no) { %}
|
||||
{%= __("Mobile No.") %}: {%= contact_list[i].mobile_no %}<br>
|
||||
{% } %}
|
||||
{% if(contact_list[i].email_id) { %}
|
||||
{%= __("Email ID") %}: {%= contact_list[i].email_id %}
|
||||
{% } %}
|
||||
</p>
|
||||
</div>
|
||||
{% } %}
|
||||
{% if(!contact_list.length) { %}
|
||||
<p class="text-muted">{%= __("No contacts added yet.") %}</p>
|
||||
{% } %}
|
||||
@@ -402,20 +402,32 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
},
|
||||
|
||||
_set_values_for_item_list: function(children) {
|
||||
var me = this;
|
||||
var price_list_rate_changed = false;
|
||||
$.each(children, function(i, d) {
|
||||
var existing_pricing_rule = frappe.model.get_value(d.doctype, d.name, "pricing_rule");
|
||||
$.each(d, function(k, v) {
|
||||
if (["doctype", "name"].indexOf(k)===-1) {
|
||||
if(k=="price_list_rate") {
|
||||
if(flt(v) != flt(d.price_list_rate)) price_list_rate_changed = true;
|
||||
}
|
||||
frappe.model.set_value(d.doctype, d.name, k, v);
|
||||
}
|
||||
});
|
||||
// if pricing rule set as blank from an existing value, apply price_list
|
||||
if(!me.frm.doc.ignore_pricing_rule && existing_pricing_rule && !d.pricing_rule) {
|
||||
me.apply_price_list(frappe.get_doc(d.doctype, d.name));
|
||||
}
|
||||
|
||||
if(!price_list_rate_changed) me.calculate_taxes_and_totals();
|
||||
});
|
||||
},
|
||||
|
||||
apply_price_list: function() {
|
||||
apply_price_list: function(item) {
|
||||
var me = this;
|
||||
return this.frm.call({
|
||||
method: "erpnext.stock.get_item_details.apply_price_list",
|
||||
args: { args: this._get_args() },
|
||||
args: { args: this._get_args(item) },
|
||||
callback: function(r) {
|
||||
if (!r.exc) {
|
||||
me.in_apply_price_list = true;
|
||||
|
||||
@@ -81,5 +81,28 @@ $.extend(erpnext, {
|
||||
|
||||
d.show();
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
erpnext.utils = {
|
||||
render_address_and_contact: function(frm) {
|
||||
// render address
|
||||
$(frm.fields_dict['address_html'].wrapper)
|
||||
.html(frappe.render(frappe.templates.address_list,
|
||||
cur_frm.doc.__onload))
|
||||
.find(".btn-address").on("click", function() {
|
||||
new_doc("Address");
|
||||
});
|
||||
|
||||
// render contact
|
||||
if(frm.fields_dict['contact_html']) {
|
||||
$(frm.fields_dict['contact_html'].wrapper)
|
||||
.html(frappe.render(frappe.templates.contact_list,
|
||||
cur_frm.doc.__onload))
|
||||
.find(".btn-contact").on("click", function() {
|
||||
new_doc("Contact");
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
{% include 'setup/doctype/contact_control/contact_control.js' %};
|
||||
|
||||
cur_frm.cscript.onload = function(doc, dt, dn) {
|
||||
cur_frm.cscript.load_defaults(doc, dt, dn);
|
||||
}
|
||||
@@ -32,8 +30,8 @@ cur_frm.cscript.refresh = function(doc, dt, dn) {
|
||||
}else{
|
||||
unhide_field(['address_html','contact_html']);
|
||||
// make lists
|
||||
cur_frm.cscript.make_address(doc, dt, dn);
|
||||
cur_frm.cscript.make_contact(doc, dt, dn);
|
||||
|
||||
erpnext.utils.render_address_and_contact(cur_frm)
|
||||
|
||||
cur_frm.communication_view = new frappe.views.CommunicationList({
|
||||
parent: cur_frm.fields_dict.communication_html.wrapper,
|
||||
@@ -79,44 +77,6 @@ cur_frm.cscript.setup_dashboard = function(doc) {
|
||||
});
|
||||
}
|
||||
|
||||
cur_frm.cscript.make_address = function() {
|
||||
if(!cur_frm.address_list) {
|
||||
cur_frm.address_list = new frappe.ui.Listing({
|
||||
parent: cur_frm.fields_dict['address_html'].wrapper,
|
||||
page_length: 5,
|
||||
new_doctype: "Address",
|
||||
get_query: function() {
|
||||
return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where customer='" +
|
||||
cur_frm.doc.name.replace(/'/g, "\\'") + "' and docstatus != 2 order by is_primary_address desc"
|
||||
},
|
||||
as_dict: 1,
|
||||
no_results_message: __('No addresses created'),
|
||||
render_row: cur_frm.cscript.render_address_row,
|
||||
});
|
||||
// note: render_address_row is defined in contact_control.js
|
||||
}
|
||||
cur_frm.address_list.run();
|
||||
}
|
||||
|
||||
cur_frm.cscript.make_contact = function() {
|
||||
if(!cur_frm.contact_list) {
|
||||
cur_frm.contact_list = new frappe.ui.Listing({
|
||||
parent: cur_frm.fields_dict['contact_html'].wrapper,
|
||||
page_length: 5,
|
||||
new_doctype: "Contact",
|
||||
get_query: function() {
|
||||
return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where customer='" +
|
||||
cur_frm.doc.name.replace(/'/g, "\\'") + "' and docstatus != 2 order by is_primary_contact desc"
|
||||
},
|
||||
as_dict: 1,
|
||||
no_results_message: __('No contacts created'),
|
||||
render_row: cur_frm.cscript.render_contact_row,
|
||||
});
|
||||
// note: render_contact_row is defined in contact_control.js
|
||||
}
|
||||
cur_frm.contact_list.run();
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['customer_group'].get_query = function(doc, dt, dn) {
|
||||
return{
|
||||
filters:{'is_group': 'No'}
|
||||
|
||||
@@ -7,11 +7,14 @@ from frappe.model.naming import make_autoname
|
||||
from frappe import msgprint, _
|
||||
import frappe.defaults
|
||||
|
||||
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
from erpnext.utilities.address_and_contact import load_address_and_contact
|
||||
from erpnext.accounts.party import create_party_account
|
||||
|
||||
class Customer(TransactionBase):
|
||||
def onload(self):
|
||||
"""Load address and contacts in `__onload`"""
|
||||
load_address_and_contact(self, "customer")
|
||||
|
||||
def autoname(self):
|
||||
cust_master_name = frappe.defaults.get_global_default('cust_master_name')
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
{% include 'setup/doctype/contact_control/contact_control.js' %};
|
||||
|
||||
frappe.provide("erpnext");
|
||||
erpnext.LeadController = frappe.ui.form.Controller.extend({
|
||||
setup: function() {
|
||||
@@ -42,33 +40,10 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({
|
||||
});
|
||||
|
||||
if(!this.frm.doc.__islocal) {
|
||||
this.make_address_list();
|
||||
erpnext.utils.render_address_and_contact(cur_frm);
|
||||
}
|
||||
},
|
||||
|
||||
make_address_list: function() {
|
||||
var me = this;
|
||||
if(!this.frm.address_list) {
|
||||
this.frm.address_list = new frappe.ui.Listing({
|
||||
parent: this.frm.fields_dict['address_html'].wrapper,
|
||||
page_length: 5,
|
||||
new_doctype: "Address",
|
||||
get_query: function() {
|
||||
return 'select name, address_type, address_line1, address_line2, \
|
||||
city, state, country, pincode, fax, email_id, phone, \
|
||||
is_primary_address, is_shipping_address from tabAddress \
|
||||
where lead="'+me.frm.doc.name+'" and docstatus != 2 \
|
||||
order by is_primary_address, is_shipping_address desc'
|
||||
},
|
||||
as_dict: 1,
|
||||
no_results_message: __('No addresses created'),
|
||||
render_row: this.render_address_row,
|
||||
});
|
||||
// note: render_address_row is defined in contact_control.js
|
||||
}
|
||||
this.frm.address_list.run();
|
||||
},
|
||||
|
||||
create_customer: function() {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.selling.doctype.lead.lead.make_customer",
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"description": "Add to calendar on this date",
|
||||
"fieldname": "contact_date",
|
||||
"fieldtype": "Date",
|
||||
"fieldtype": "Datetime",
|
||||
"in_filter": 1,
|
||||
"label": "Next Contact Date",
|
||||
"no_copy": 1,
|
||||
@@ -368,7 +368,7 @@
|
||||
],
|
||||
"icon": "icon-user",
|
||||
"idx": 1,
|
||||
"modified": "2014-08-12 05:22:18.801092",
|
||||
"modified": "2014-12-01 08:22:23.286314",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Lead",
|
||||
|
||||
@@ -9,11 +9,13 @@ from frappe import session
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
|
||||
from erpnext.controllers.selling_controller import SellingController
|
||||
from erpnext.utilities.address_and_contact import load_address_and_contact
|
||||
|
||||
class Lead(SellingController):
|
||||
def onload(self):
|
||||
customer = frappe.db.get_value("Customer", {"lead_name": self.name})
|
||||
self.get("__onload").is_customer = customer
|
||||
load_address_and_contact(self, "lead")
|
||||
|
||||
def validate(self):
|
||||
self._prev = frappe._dict({
|
||||
@@ -43,6 +45,7 @@ class Lead(SellingController):
|
||||
def add_calendar_event(self, opts=None, force=False):
|
||||
super(Lead, self).add_calendar_event({
|
||||
"owner": self.lead_owner,
|
||||
"starts_on": self.contact_date,
|
||||
"subject": ('Contact ' + cstr(self.lead_name)),
|
||||
"description": ('Contact ' + cstr(self.lead_name)) + \
|
||||
(self.contact_by and ('. By : ' + cstr(self.contact_by)) or '')
|
||||
|
||||
@@ -35,8 +35,6 @@ erpnext.selling.Opportunity = frappe.ui.form.Controller.extend({
|
||||
});
|
||||
}
|
||||
|
||||
if(this.frm.doc.customer && !this.frm.doc.customer_name) cur_frm.cscript.customer(this.frm.doc);
|
||||
|
||||
this.setup_queries();
|
||||
},
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Customer",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "customer",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Customer",
|
||||
@@ -372,7 +373,7 @@
|
||||
{
|
||||
"description": "Your sales person will get a reminder on this date to contact the customer",
|
||||
"fieldname": "contact_date",
|
||||
"fieldtype": "Date",
|
||||
"fieldtype": "Datetime",
|
||||
"label": "Next Contact Date",
|
||||
"oldfieldname": "contact_date",
|
||||
"oldfieldtype": "Date",
|
||||
@@ -416,7 +417,7 @@
|
||||
"icon": "icon-info-sign",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-08-12 05:21:51.282397",
|
||||
"modified": "2014-12-19 10:49:20.695720",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Opportunity",
|
||||
|
||||
@@ -57,6 +57,7 @@ class Opportunity(TransactionBase):
|
||||
opts = frappe._dict()
|
||||
|
||||
opts.description = ""
|
||||
opts.contact_date = self.contact_date
|
||||
|
||||
if self.customer:
|
||||
if self.contact_person:
|
||||
|
||||
@@ -23,7 +23,7 @@ class Quotation(SellingController):
|
||||
self.validate_order_type()
|
||||
self.validate_for_items()
|
||||
self.validate_uom_is_integer("stock_uom", "qty")
|
||||
self.quotation_to = "Customer" if self.customer else "Lead"
|
||||
self.validate_quotation_to()
|
||||
|
||||
def has_sales_order(self):
|
||||
return frappe.db.get_value("Sales Order Item", {"prevdoc_docname": self.name, "docstatus": 1})
|
||||
@@ -54,6 +54,13 @@ class Quotation(SellingController):
|
||||
if is_sales_item == 'No':
|
||||
frappe.throw(_("Item {0} must be Sales Item").format(d.item_code))
|
||||
|
||||
def validate_quotation_to(self):
|
||||
if self.customer:
|
||||
self.quotation_to = "Customer"
|
||||
self.lead = None
|
||||
elif self.lead:
|
||||
self.quotation_to = "Lead"
|
||||
|
||||
def update_opportunity(self):
|
||||
for opportunity in list(set([d.prevdoc_docname for d in self.get("quotation_details")])):
|
||||
if opportunity:
|
||||
@@ -139,8 +146,8 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False):
|
||||
return doclist
|
||||
|
||||
def _make_customer(source_name, ignore_permissions=False):
|
||||
quotation = frappe.db.get_value("Quotation", source_name, ["lead", "order_type"])
|
||||
if quotation and quotation[0]:
|
||||
quotation = frappe.db.get_value("Quotation", source_name, ["lead", "order_type", "customer"])
|
||||
if quotation and quotation[0] and not quotation[2]:
|
||||
lead_name = quotation[0]
|
||||
customer_name = frappe.db.get_value("Customer", {"lead_name": lead_name},
|
||||
["name", "customer_name"], as_dict=True)
|
||||
|
||||
@@ -175,6 +175,7 @@
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"label": "PO No",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "po_no",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
@@ -1020,7 +1021,7 @@
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"modified": "2014-10-08 14:22:44.717108",
|
||||
"modified": "2014-12-16 10:36:47.295144",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order",
|
||||
|
||||
@@ -157,7 +157,7 @@ class SalesOrder(SellingController):
|
||||
|
||||
self.check_credit(self.grand_total)
|
||||
|
||||
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, self.grand_total, self)
|
||||
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, self.company, self.grand_total, self)
|
||||
|
||||
self.update_prevdoc_status('submit')
|
||||
frappe.db.set(self, 'status', 'Submitted')
|
||||
@@ -275,6 +275,14 @@ def make_material_request(source_name, target_doc=None):
|
||||
@frappe.whitelist()
|
||||
def make_delivery_note(source_name, target_doc=None):
|
||||
def set_missing_values(source, target):
|
||||
if source.po_no:
|
||||
if target.po_no:
|
||||
target_po_no = target.po_no.split(", ")
|
||||
target_po_no.append(source.po_no)
|
||||
target.po_no = ", ".join(list(set(target_po_no))) if len(target_po_no) > 1 else target_po_no[0]
|
||||
else:
|
||||
target.po_no = source.po_no
|
||||
|
||||
target.ignore_pricing_rule = 1
|
||||
target.run_method("set_missing_values")
|
||||
target.run_method("calculate_taxes_and_totals")
|
||||
@@ -329,7 +337,7 @@ def make_sales_invoice(source_name, target_doc=None):
|
||||
def update_item(source, target, source_parent):
|
||||
target.amount = flt(source.amount) - flt(source.billed_amt)
|
||||
target.base_amount = target.amount * flt(source_parent.conversion_rate)
|
||||
target.qty = source.rate and target.amount / flt(source.rate) or source.qty
|
||||
target.qty = target.amount / flt(source.rate) if (source.rate and source.billed_amt) else source.qty
|
||||
|
||||
doclist = get_mapped_doc("Sales Order", source_name, {
|
||||
"Sales Order": {
|
||||
@@ -357,17 +365,6 @@ def make_sales_invoice(source_name, target_doc=None):
|
||||
}
|
||||
}, target_doc, postprocess)
|
||||
|
||||
def set_advance_vouchers(source, target):
|
||||
advance_voucher_list = []
|
||||
|
||||
advance_voucher = frappe.db.sql("""
|
||||
select
|
||||
t1.name as voucher_no, t1.posting_date, t1.remark, t2.account,
|
||||
t2.name as voucher_detail_no, {amount_query} as payment_amount, t2.is_advance
|
||||
from
|
||||
`tabJournal Voucher` t1, `tabJournal Voucher Detail` t2
|
||||
""")
|
||||
|
||||
return doclist
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
@@ -341,11 +341,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
var me = this;
|
||||
var tax_count = this.frm.tax_doclist.length;
|
||||
|
||||
this.frm.doc.grand_total = flt(
|
||||
tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
|
||||
precision("grand_total"));
|
||||
this.frm.doc.grand_total_export = flt(this.frm.doc.grand_total / this.frm.doc.conversion_rate,
|
||||
precision("grand_total_export"));
|
||||
this.frm.doc.grand_total = flt(tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total);
|
||||
this.frm.doc.grand_total_export = flt(tax_count ?
|
||||
flt(this.frm.doc.grand_total / this.frm.doc.conversion_rate) : this.frm.doc.net_total_export);
|
||||
|
||||
this.frm.doc.other_charges_total = flt(this.frm.doc.grand_total - this.frm.doc.net_total,
|
||||
precision("other_charges_total"));
|
||||
@@ -353,6 +351,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
this.frm.doc.net_total_export + flt(this.frm.doc.discount_amount),
|
||||
precision("other_charges_total_export"));
|
||||
|
||||
this.frm.doc.grand_total = flt(this.frm.doc.grand_total, precision("grand_total"));
|
||||
this.frm.doc.grand_total_export = flt(this.frm.doc.grand_total_export, precision("grand_total_export"));
|
||||
|
||||
this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total);
|
||||
this.frm.doc.rounded_total_export = Math.round(this.frm.doc.grand_total_export);
|
||||
},
|
||||
@@ -587,16 +588,18 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
});
|
||||
|
||||
frappe.ui.form.on(cur_frm.doctype,"project_name", function(frm) {
|
||||
frappe.call({
|
||||
method:'erpnext.projects.doctype.project.project.get_cost_center_name' ,
|
||||
args: { project_name: frm.doc.project_name },
|
||||
callback: function(r, rt) {
|
||||
if(!r.exc) {
|
||||
$.each(frm.doc[cur_frm.cscript.fname] || [], function(i, row) {
|
||||
frappe.model.set_value(row.doctype, row.name, "cost_center", r.message);
|
||||
msgprint(__("Cost Center For Item with Item Code '"+row.item_name+"' has been Changed to "+ r.message));
|
||||
})
|
||||
if(in_list(["Delivery Note", "Sales Invoice"], frm.doc.doctype)) {
|
||||
frappe.call({
|
||||
method:'erpnext.projects.doctype.project.project.get_cost_center_name' ,
|
||||
args: { project_name: frm.doc.project_name },
|
||||
callback: function(r, rt) {
|
||||
if(!r.exc) {
|
||||
$.each(frm.doc[cur_frm.cscript.fname] || [], function(i, row) {
|
||||
frappe.model.set_value(row.doctype, row.name, "cost_center", r.message);
|
||||
msgprint(__("Cost Center For Item with Item Code '"+row.item_name+"' has been Changed to "+ r.message));
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -98,9 +98,12 @@ class AuthorizationControl(TransactionBase):
|
||||
if doc_obj:
|
||||
price_list_rate, base_rate = 0, 0
|
||||
for d in doc_obj.get(doc_obj.fname):
|
||||
if d.base_price_list_rate and d.base_rate:
|
||||
price_list_rate += flt(d.base_price_list_rate)
|
||||
if d.base_rate:
|
||||
price_list_rate += flt(d.base_price_list_rate) or flt(d.base_rate)
|
||||
base_rate += flt(d.base_rate)
|
||||
if doc_obj.get("discount_amount"):
|
||||
base_rate -= flt(doc_obj.discount_amount)
|
||||
|
||||
if price_list_rate: av_dis = 100 - flt(base_rate * 100 / price_list_rate)
|
||||
|
||||
final_based_on = ['Grand Total','Average Discount','Customerwise Discount','Itemwise Discount']
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
[To deprecate] Common scripts for Contacts.
|
||||
@@ -1 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
@@ -1,161 +0,0 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
if(cur_frm.fields_dict['territory']) {
|
||||
cur_frm.fields_dict['territory'].get_query = function(doc, dt, dn) {
|
||||
return {
|
||||
filters: {
|
||||
'is_group': "No"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.render_contact_row = function(wrapper, data) {
|
||||
// prepare data
|
||||
data.fullname = (data.first_name || '')
|
||||
+ (data.last_name ? ' ' + data.last_name : '');
|
||||
data.primary = data.is_primary_contact ? ' [Primary]' : '';
|
||||
|
||||
// prepare description
|
||||
var description = [];
|
||||
$.each([
|
||||
['phone', 'Tel'],
|
||||
['mobile_no', 'Mobile'],
|
||||
['email_id', 'Email'],
|
||||
['department', 'Department'],
|
||||
['designation', 'Designation']],
|
||||
function(i, v) {
|
||||
if(v[0] && data[v[0]]) {
|
||||
description.push(repl('<h6>%(label)s:</h6> %(value)s', {
|
||||
label: v[1],
|
||||
value: data[v[0]],
|
||||
}));
|
||||
}
|
||||
});
|
||||
data.description = description.join('<br />');
|
||||
|
||||
cur_frm.cscript.render_row_in_wrapper(wrapper, data, 'Contact');
|
||||
}
|
||||
|
||||
cur_frm.cscript.render_address_row = function(wrapper, data) {
|
||||
// prepare data
|
||||
data.fullname = data.address_type;
|
||||
data.primary = '';
|
||||
if (data.is_primary_address) data.primary += ' [Preferred for Billing]';
|
||||
if (data.is_shipping_address) data.primary += ' [Preferred for Shipping]';
|
||||
|
||||
// prepare address
|
||||
var address = [];
|
||||
$.each(['address_line1', 'address_line2', 'city', 'state', 'country', 'pincode'],
|
||||
function(i, v) {
|
||||
if(data[v]) address.push(data[v]);
|
||||
});
|
||||
|
||||
data.address = address.join('<br />');
|
||||
data.address = "<p class='address-list'>" + data.address + "</p>";
|
||||
|
||||
// prepare description
|
||||
var description = [];
|
||||
$.each([
|
||||
['address', 'Address'],
|
||||
['phone', 'Tel'],
|
||||
['fax', 'Fax'],
|
||||
['email_id', 'Email']],
|
||||
function(i, v) {
|
||||
if(data[v[0]]) {
|
||||
description.push(repl('<h6>%(label)s:</h6> %(value)s', {
|
||||
label: v[1],
|
||||
value: data[v[0]],
|
||||
}));
|
||||
}
|
||||
});
|
||||
data.description = description.join('<br />');
|
||||
|
||||
cur_frm.cscript.render_row_in_wrapper(wrapper, data, 'Address');
|
||||
|
||||
$(wrapper).find('p.address-list').css({
|
||||
'padding-left': '10px',
|
||||
'margin-bottom': '-10px'
|
||||
});
|
||||
}
|
||||
|
||||
cur_frm.cscript.render_row_in_wrapper = function(wrapper, data, doctype) {
|
||||
// render
|
||||
var $wrapper = $(wrapper);
|
||||
|
||||
data.doctype = doctype.toLowerCase();
|
||||
|
||||
$wrapper.append(repl("\
|
||||
<h4><a class='link_type'>%(fullname)s</a>%(primary)s</h4>\
|
||||
<div class='description'>\
|
||||
<p>%(description)s</p>\
|
||||
<p><a class='delete link_type'>delete this %(doctype)s</a></p>\
|
||||
</div>", data));
|
||||
|
||||
// make link
|
||||
$wrapper.find('h4 a.link_type').click(function() {
|
||||
loaddoc(doctype, data.name);
|
||||
});
|
||||
|
||||
// css
|
||||
$wrapper.css({ 'margin': '0px' });
|
||||
$wrapper.find('div.description').css({
|
||||
'padding': '5px 2px',
|
||||
'line-height': '150%',
|
||||
});
|
||||
$wrapper.find('h6').css({ 'display': 'inline-block' });
|
||||
|
||||
// show delete
|
||||
var $delete_doc = $wrapper.find('a.delete');
|
||||
if (frappe.model.can_delete(doctype))
|
||||
$delete_doc.toggle(true);
|
||||
else
|
||||
$delete_doc.toggle(false);
|
||||
|
||||
$delete_doc.css({ 'padding-left': '0px' });
|
||||
|
||||
$delete_doc.click(function() {
|
||||
cur_frm.cscript.delete_doc(doctype, data.name);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
cur_frm.cscript.delete_doc = function(doctype, name) {
|
||||
// confirm deletion
|
||||
var go_ahead = confirm(__("Delete {0} {1}?", [doctype, name]));
|
||||
if (!go_ahead) return;
|
||||
|
||||
frappe.model.delete_doc(doctype, name, function(r) {
|
||||
if (!r.exc) {
|
||||
var list_name = doctype.toLowerCase() + '_list';
|
||||
cur_frm[list_name].run();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Render List
|
||||
cur_frm.cscript.render_list = function(doc, doctype, wrapper, ListView, make_new_doc) {
|
||||
frappe.model.with_doctype(doctype, function(r) {
|
||||
if((r && r['403']) || frappe.boot.user.all_read.indexOf(doctype)===-1) {
|
||||
return;
|
||||
}
|
||||
var RecordListView = frappe.views.RecordListView.extend({
|
||||
default_docstatus: ['0', '1', '2'],
|
||||
default_filters: [
|
||||
[doctype, doc.doctype.toLowerCase().replace(" ", "_"), '=', doc.name],
|
||||
],
|
||||
});
|
||||
|
||||
if (make_new_doc) {
|
||||
RecordListView = RecordListView.extend({
|
||||
make_new_doc: make_new_doc,
|
||||
});
|
||||
}
|
||||
|
||||
var record_list_view = new RecordListView(doctype, wrapper, ListView);
|
||||
if (!cur_frm[doctype.toLowerCase().replace(" ", "_") + "_list"]) {
|
||||
cur_frm[doctype.toLowerCase().replace(" ", "_") + "_list"] = record_list_view;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
{
|
||||
"creation": "2012-03-27 14:36:19.000000",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "header",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Header",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "customer_intro",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Customer Intro",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "supplier_intro",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Supplier Intro",
|
||||
"permlevel": 0
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"in_create": 1,
|
||||
"issingle": 1,
|
||||
"modified": "2013-12-20 19:23:02.000000",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Contact Control",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 0,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"role": "System Manager",
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"read_only": 1
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
class ContactControl(Document):
|
||||
pass
|
||||
@@ -1,12 +1,6 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
{% include 'setup/doctype/contact_control/contact_control.js' %};
|
||||
|
||||
cur_frm.cscript.onload = function(doc,dt,dn){
|
||||
|
||||
}
|
||||
|
||||
cur_frm.cscript.refresh = function(doc,dt,dn){
|
||||
|
||||
if(doc.__islocal){
|
||||
@@ -15,8 +9,8 @@ cur_frm.cscript.refresh = function(doc,dt,dn){
|
||||
else{
|
||||
unhide_field(['address_html', 'contact_html']);
|
||||
// make lists
|
||||
cur_frm.cscript.make_address(doc,dt,dn);
|
||||
cur_frm.cscript.make_contact(doc,dt,dn);
|
||||
|
||||
erpnext.utils.render_address_and_contact(cur_frm)
|
||||
|
||||
if (doc.show_in_website) {
|
||||
cur_frm.set_intro(__("Published on website at: {0}",
|
||||
@@ -25,57 +19,6 @@ cur_frm.cscript.refresh = function(doc,dt,dn){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cur_frm.cscript.make_address = function() {
|
||||
if(!cur_frm.address_list) {
|
||||
cur_frm.address_list = new frappe.ui.Listing({
|
||||
parent: cur_frm.fields_dict['address_html'].wrapper,
|
||||
page_length: 2,
|
||||
new_doctype: "Address",
|
||||
custom_new_doc: function(doctype) {
|
||||
var address = frappe.model.make_new_doc_and_get_name('Address');
|
||||
address = locals['Address'][address];
|
||||
address.sales_partner = cur_frm.doc.name;
|
||||
address.address_title = cur_frm.doc.name;
|
||||
address.address_type = "Office";
|
||||
frappe.set_route("Form", "Address", address.name);
|
||||
},
|
||||
get_query: function() {
|
||||
return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where sales_partner='" +
|
||||
cur_frm.doc.name.replace(/'/g, "\\'") + "' and docstatus != 2 order by is_primary_address desc"
|
||||
},
|
||||
as_dict: 1,
|
||||
no_results_message: __('No addresses created'),
|
||||
render_row: cur_frm.cscript.render_address_row,
|
||||
});
|
||||
}
|
||||
cur_frm.address_list.run();
|
||||
}
|
||||
|
||||
cur_frm.cscript.make_contact = function() {
|
||||
if(!cur_frm.contact_list) {
|
||||
cur_frm.contact_list = new frappe.ui.Listing({
|
||||
parent: cur_frm.fields_dict['contact_html'].wrapper,
|
||||
page_length: 2,
|
||||
new_doctype: "Contact",
|
||||
custom_new_doc: function(doctype) {
|
||||
var contact = frappe.model.make_new_doc_and_get_name('Contact');
|
||||
contact = locals['Contact'][contact];
|
||||
contact.sales_partner = cur_frm.doc.name;
|
||||
frappe.set_route("Form", "Contact", contact.name);
|
||||
},
|
||||
get_query: function() {
|
||||
return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where sales_partner='" +
|
||||
cur_frm.doc.name.replace(/'/g, "\\'") + "' and docstatus != 2 order by is_primary_contact desc"
|
||||
},
|
||||
as_dict: 1,
|
||||
no_results_message: __('No contacts created'),
|
||||
render_row: cur_frm.cscript.render_contact_row,
|
||||
});
|
||||
}
|
||||
cur_frm.contact_list.run();
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['partner_target_details'].grid.get_field("item_group").get_query = function(doc, dt, dn) {
|
||||
return{
|
||||
filters:{ 'is_group': "No" }
|
||||
|
||||
@@ -5,11 +5,16 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import cstr, filter_strip_join
|
||||
from frappe.website.website_generator import WebsiteGenerator
|
||||
from erpnext.utilities.address_and_contact import load_address_and_contact
|
||||
|
||||
class SalesPartner(WebsiteGenerator):
|
||||
page_title_field = "partner_name"
|
||||
condition_field = "show_in_website"
|
||||
template = "templates/generators/sales_partner.html"
|
||||
def onload(self):
|
||||
"""Load address and contacts in `__onload`"""
|
||||
load_address_and_contact(self, "sales_partner")
|
||||
|
||||
def autoname(self):
|
||||
self.name = self.partner_name
|
||||
|
||||
|
||||
@@ -59,15 +59,31 @@ frappe.pages['setup-wizard'].onload = function(wrapper) {
|
||||
title: __("Select Your Language"),
|
||||
icon: "icon-globe",
|
||||
fields: [
|
||||
{"fieldname": "language", "label": __("Language"), "fieldtype": "Select",
|
||||
options: ["english", "العربية", "deutsch", "ελληνικά", "español", "français", "हिंदी", "hrvatski",
|
||||
"italiano", "nederlands", "polski", "português brasileiro", "português", "српски", "தமிழ்",
|
||||
"ไทย", "中国(简体)", "中國(繁體)"], reqd:1},
|
||||
{
|
||||
"fieldname": "language", "label": __("Language"), "fieldtype": "Select",
|
||||
reqd:1
|
||||
},
|
||||
],
|
||||
help: __("Welcome to ERPNext. Please select your language to begin the Setup Wizard."),
|
||||
onload: function(slide) {
|
||||
var me = this;
|
||||
|
||||
if (!this.language_list) {
|
||||
frappe.call({
|
||||
method: "erpnext.setup.page.setup_wizard.setup_wizard.load_languages",
|
||||
callback: function(r) {
|
||||
me.language_list = r.message;
|
||||
slide.get_input("language")
|
||||
.add_options(r.message)
|
||||
.val("english");
|
||||
}
|
||||
})
|
||||
} else {
|
||||
slide.get_input("language").add_options(this.language_list);
|
||||
}
|
||||
|
||||
slide.get_input("language").on("change", function() {
|
||||
var lang = $(this).val();
|
||||
var lang = $(this).val() || "english";
|
||||
frappe._messages = {};
|
||||
frappe.call({
|
||||
method: "erpnext.setup.page.setup_wizard.setup_wizard.load_messages",
|
||||
|
||||
@@ -434,4 +434,6 @@ def load_messages(language):
|
||||
send_translations(m)
|
||||
return lang
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def load_languages():
|
||||
return sorted(get_lang_dict().keys())
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
{
|
||||
"fieldname": "po_no",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"hidden": 0,
|
||||
"label": "Customer's Purchase Order No",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "po_no",
|
||||
@@ -1013,7 +1013,7 @@
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-09-09 05:35:30.700911",
|
||||
"modified": "2014-12-22 14:58:19.575566",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Delivery Note",
|
||||
|
||||
@@ -52,11 +52,15 @@ class DeliveryNote(SellingController):
|
||||
else:
|
||||
df.delete_key("__print_hide")
|
||||
|
||||
toggle_print_hide(self.meta, "currency")
|
||||
|
||||
item_meta = frappe.get_meta("Delivery Note Item")
|
||||
for fieldname in ("rate", "amount", "price_list_rate", "discount_percentage"):
|
||||
toggle_print_hide(item_meta, fieldname)
|
||||
print_hide_fields = {
|
||||
"parent": ["grand_total_export", "rounded_total_export", "in_words_export", "currency", "net_total_export"],
|
||||
"items": ["rate", "amount", "price_list_rate", "discount_percentage"]
|
||||
}
|
||||
|
||||
for key, fieldname in print_hide_fields.items():
|
||||
for f in fieldname:
|
||||
toggle_print_hide(self.meta if key == "parent" else item_meta, f)
|
||||
|
||||
def get_portal_page(self):
|
||||
return "shipment" if self.docstatus==1 else None
|
||||
@@ -245,7 +249,7 @@ class DeliveryNote(SellingController):
|
||||
sl_entries = []
|
||||
for d in self.get_item_list():
|
||||
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes" \
|
||||
and d.warehouse:
|
||||
and d.warehouse and flt(d['qty']):
|
||||
self.update_reserved_qty(d)
|
||||
|
||||
sl_entries.append(self.get_sl_entries(d, {
|
||||
@@ -377,7 +381,8 @@ def make_packing_slip(source_name, target_doc=None):
|
||||
"Delivery Note": {
|
||||
"doctype": "Packing Slip",
|
||||
"field_map": {
|
||||
"name": "delivery_note"
|
||||
"name": "delivery_note",
|
||||
"letter_head": "letter_head"
|
||||
},
|
||||
"validation": {
|
||||
"docstatus": ["=", 0]
|
||||
|
||||
@@ -229,7 +229,7 @@ class Item(WebsiteGenerator):
|
||||
if not frappe.db.exists("Item", newdn):
|
||||
frappe.throw(_("Item {0} does not exist").format(newdn))
|
||||
|
||||
field_list = ["stock_uom", "is_stock_item", "has_serial_no", "has_batch_no"]
|
||||
field_list = ["stock_uom", "is_stock_item", "has_serial_no", "has_batch_no", "is_manufactured_item"]
|
||||
new_properties = [cstr(d) for d in frappe.db.get_value("Item", newdn, field_list)]
|
||||
if new_properties != [cstr(self.get(fld)) for fld in field_list]:
|
||||
frappe.throw(_("To merge, following properties must be same for both items")
|
||||
|
||||
@@ -79,30 +79,9 @@ class MaterialRequest(BuyingController):
|
||||
# NOTE: Since Item BOM and FG quantities are combined, using current data, it cannot be validated
|
||||
# Though the creation of Material Request from a Production Plan can be rethought to fix this
|
||||
|
||||
def update_bin(self, is_submit, is_stopped):
|
||||
""" Update Quantity Requested for Purchase in Bin for Material Request of type 'Purchase'"""
|
||||
|
||||
from erpnext.stock.utils import update_bin
|
||||
for d in self.get('indent_details'):
|
||||
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes":
|
||||
if not d.warehouse:
|
||||
frappe.throw(_("Warehouse required for stock Item {0}").format(d.item_code))
|
||||
|
||||
qty =flt(d.qty)
|
||||
if is_stopped:
|
||||
qty = (d.qty > d.ordered_qty) and flt(flt(d.qty) - flt(d.ordered_qty)) or 0
|
||||
|
||||
args = {
|
||||
"item_code": d.item_code,
|
||||
"warehouse": d.warehouse,
|
||||
"indented_qty": (is_submit and 1 or -1) * flt(qty),
|
||||
"posting_date": self.transaction_date
|
||||
}
|
||||
update_bin(args)
|
||||
|
||||
def on_submit(self):
|
||||
frappe.db.set(self, 'status', 'Submitted')
|
||||
self.update_bin(is_submit = 1, is_stopped = 0)
|
||||
self.update_requested_qty()
|
||||
|
||||
def check_modified_date(self):
|
||||
mod_db = frappe.db.sql("""select modified from `tabMaterial Request` where name = %s""",
|
||||
@@ -115,23 +94,18 @@ class MaterialRequest(BuyingController):
|
||||
|
||||
def update_status(self, status):
|
||||
self.check_modified_date()
|
||||
self.update_bin(is_submit = (status == 'Submitted') and 1 or 0, is_stopped = 1)
|
||||
self.update_requested_qty()
|
||||
frappe.db.set(self, 'status', cstr(status))
|
||||
frappe.msgprint(_("Status updated to {0}").format(_(status)))
|
||||
|
||||
def on_cancel(self):
|
||||
# Step 1:=> Get Purchase Common Obj
|
||||
pc_obj = frappe.get_doc('Purchase Common')
|
||||
|
||||
# Step 2:=> Check for stopped status
|
||||
pc_obj.check_for_stopped_status(self.doctype, self.name)
|
||||
|
||||
# Step 3:=> Check if Purchase Order has been submitted against current Material Request
|
||||
pc_obj.check_docstatus(check = 'Next', doctype = 'Purchase Order', docname = self.name, detail_doctype = 'Purchase Order Item')
|
||||
# Step 4:=> Update Bin
|
||||
self.update_bin(is_submit = 0, is_stopped = (cstr(self.status) == 'Stopped') and 1 or 0)
|
||||
|
||||
# Step 5:=> Set Status
|
||||
self.update_requested_qty()
|
||||
|
||||
frappe.db.set(self,'status','Cancelled')
|
||||
|
||||
def update_completed_qty(self, mr_items=None):
|
||||
@@ -162,56 +136,47 @@ class MaterialRequest(BuyingController):
|
||||
self.per_ordered = flt((per_ordered / flt(len(item_doclist))) * 100.0, 2)
|
||||
frappe.db.set_value(self.doctype, self.name, "per_ordered", self.per_ordered)
|
||||
|
||||
def update_completed_qty(doc, method):
|
||||
if doc.doctype == "Stock Entry":
|
||||
def update_requested_qty(self, mr_item_rows=None):
|
||||
"""update requested qty (before ordered_qty is updated)"""
|
||||
from erpnext.stock.utils import get_bin
|
||||
|
||||
def _update_requested_qty(item_code, warehouse):
|
||||
requested_qty = frappe.db.sql("""select sum(mr_item.qty - ifnull(mr_item.ordered_qty, 0))
|
||||
from `tabMaterial Request Item` mr_item, `tabMaterial Request` mr
|
||||
where mr_item.item_code=%s and mr_item.warehouse=%s
|
||||
and mr_item.qty > ifnull(mr_item.ordered_qty, 0) and mr_item.parent=mr.name
|
||||
and mr.status!='Stopped' and mr.docstatus=1""", (item_code, warehouse))
|
||||
|
||||
bin_doc = get_bin(item_code, warehouse)
|
||||
bin_doc.indented_qty = flt(requested_qty[0][0]) if requested_qty else 0
|
||||
bin_doc.save()
|
||||
|
||||
item_wh_list = []
|
||||
for d in self.get("indent_details"):
|
||||
if (not mr_item_rows or d.name in mr_item_rows) and [d.item_code, d.warehouse] not in item_wh_list \
|
||||
and frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes" and d.warehouse:
|
||||
item_wh_list.append([d.item_code, d.warehouse])
|
||||
|
||||
for item_code, warehouse in item_wh_list:
|
||||
_update_requested_qty(item_code, warehouse)
|
||||
|
||||
def update_completed_and_requested_qty(stock_entry, method):
|
||||
if stock_entry.doctype == "Stock Entry":
|
||||
material_request_map = {}
|
||||
|
||||
for d in doc.get("mtn_details"):
|
||||
for d in stock_entry.get("mtn_details"):
|
||||
if d.material_request:
|
||||
material_request_map.setdefault(d.material_request, []).append(d.material_request_item)
|
||||
|
||||
for mr_name, mr_items in material_request_map.items():
|
||||
mr_obj = frappe.get_doc("Material Request", mr_name)
|
||||
for mr, mr_item_rows in material_request_map.items():
|
||||
if mr and mr_item_rows:
|
||||
mr_obj = frappe.get_doc("Material Request", mr)
|
||||
|
||||
if mr_obj.status in ["Stopped", "Cancelled"]:
|
||||
frappe.throw(_("Material Request {0} is cancelled or stopped").format(mr_obj.name),
|
||||
frappe.InvalidStatusError)
|
||||
if mr_obj.status in ["Stopped", "Cancelled"]:
|
||||
frappe.throw(_("Material Request {0} is cancelled or stopped").format(mr), frappe.InvalidStatusError)
|
||||
|
||||
_update_requested_qty(doc, mr_obj, mr_items)
|
||||
|
||||
# update ordered percentage and qty
|
||||
mr_obj.update_completed_qty(mr_items)
|
||||
|
||||
def _update_requested_qty(doc, mr_obj, mr_items):
|
||||
"""update requested qty (before ordered_qty is updated)"""
|
||||
from erpnext.stock.utils import update_bin
|
||||
for mr_item_name in mr_items:
|
||||
mr_item = mr_obj.get("indent_details", {"name": mr_item_name})
|
||||
se_detail = doc.get("mtn_details", {"material_request": mr_obj.name,
|
||||
"material_request_item": mr_item_name})
|
||||
|
||||
if mr_item and se_detail:
|
||||
mr_item = mr_item[0]
|
||||
se_detail = se_detail[0]
|
||||
mr_item.ordered_qty = flt(mr_item.ordered_qty)
|
||||
mr_item.qty = flt(mr_item.qty)
|
||||
se_detail.transfer_qty = flt(se_detail.transfer_qty)
|
||||
|
||||
if se_detail.docstatus == 2 and mr_item.ordered_qty > mr_item.qty \
|
||||
and se_detail.transfer_qty == mr_item.ordered_qty:
|
||||
add_indented_qty = mr_item.qty
|
||||
elif se_detail.docstatus == 1 and \
|
||||
mr_item.ordered_qty + se_detail.transfer_qty > mr_item.qty:
|
||||
add_indented_qty = mr_item.qty - mr_item.ordered_qty
|
||||
else:
|
||||
add_indented_qty = se_detail.transfer_qty
|
||||
|
||||
update_bin({
|
||||
"item_code": se_detail.item_code,
|
||||
"warehouse": se_detail.t_warehouse,
|
||||
"indented_qty": (se_detail.docstatus==2 and 1 or -1) * add_indented_qty,
|
||||
"posting_date": doc.posting_date,
|
||||
})
|
||||
mr_obj.update_completed_qty(mr_item_rows)
|
||||
mr_obj.update_requested_qty(mr_item_rows)
|
||||
|
||||
def set_missing_values(source, target_doc):
|
||||
target_doc.run_method("set_missing_values")
|
||||
@@ -240,7 +205,8 @@ def make_purchase_order(source_name, target_doc=None):
|
||||
["uom", "stock_uom"],
|
||||
["uom", "uom"]
|
||||
],
|
||||
"postprocess": update_item
|
||||
"postprocess": update_item,
|
||||
"condition": lambda doc: doc.ordered_qty < doc.qty
|
||||
}
|
||||
}, target_doc, set_missing_values)
|
||||
|
||||
@@ -278,7 +244,8 @@ def make_purchase_order_based_on_supplier(source_name, target_doc=None):
|
||||
["uom", "stock_uom"],
|
||||
["uom", "uom"]
|
||||
],
|
||||
"postprocess": update_item
|
||||
"postprocess": update_item,
|
||||
"condition": lambda doc: doc.ordered_qty < doc.qty
|
||||
}
|
||||
}, target_doc, postprocess)
|
||||
|
||||
@@ -350,7 +317,8 @@ def make_stock_entry(source_name, target_doc=None):
|
||||
"uom": "stock_uom",
|
||||
"warehouse": "t_warehouse"
|
||||
},
|
||||
"postprocess": update_item
|
||||
"postprocess": update_item,
|
||||
"condition": lambda doc: doc.ordered_qty < doc.qty
|
||||
}
|
||||
}, target_doc, set_missing_values)
|
||||
|
||||
|
||||
@@ -58,12 +58,6 @@ class TestMaterialRequest(unittest.TestCase):
|
||||
self.assertEquals(se.doctype, "Stock Entry")
|
||||
self.assertEquals(len(se.get("mtn_details")), len(mr.get("indent_details")))
|
||||
|
||||
def _test_requested_qty(self, qty1, qty2):
|
||||
self.assertEqual(flt(frappe.db.get_value("Bin", {"item_code": "_Test Item Home Desktop 100",
|
||||
"warehouse": "_Test Warehouse - _TC"}, "indented_qty")), qty1)
|
||||
self.assertEqual(flt(frappe.db.get_value("Bin", {"item_code": "_Test Item Home Desktop 200",
|
||||
"warehouse": "_Test Warehouse - _TC"}, "indented_qty")), qty2)
|
||||
|
||||
def _insert_stock_entry(self, qty1, qty2):
|
||||
se = frappe.get_doc({
|
||||
"company": "_Test Company",
|
||||
@@ -103,7 +97,8 @@ class TestMaterialRequest(unittest.TestCase):
|
||||
se.submit()
|
||||
|
||||
def test_completed_qty_for_purchase(self):
|
||||
frappe.db.sql("""delete from `tabBin`""")
|
||||
existing_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC")
|
||||
existing_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC")
|
||||
|
||||
# submit material request of type Purchase
|
||||
mr = frappe.copy_doc(test_records[0])
|
||||
@@ -115,8 +110,6 @@ class TestMaterialRequest(unittest.TestCase):
|
||||
self.assertEquals(mr.get("indent_details")[0].ordered_qty, 0)
|
||||
self.assertEquals(mr.get("indent_details")[1].ordered_qty, 0)
|
||||
|
||||
self._test_requested_qty(54.0, 3.0)
|
||||
|
||||
# map a purchase order
|
||||
from erpnext.stock.doctype.material_request.material_request import make_purchase_order
|
||||
po_doc = make_purchase_order(mr.name)
|
||||
@@ -149,7 +142,12 @@ class TestMaterialRequest(unittest.TestCase):
|
||||
self.assertEquals(mr.per_ordered, 50)
|
||||
self.assertEquals(mr.get("indent_details")[0].ordered_qty, 27.0)
|
||||
self.assertEquals(mr.get("indent_details")[1].ordered_qty, 1.5)
|
||||
self._test_requested_qty(27.0, 1.5)
|
||||
|
||||
current_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC")
|
||||
current_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC")
|
||||
|
||||
self.assertEquals(current_requested_qty_item1, existing_requested_qty_item1 + 27.0)
|
||||
self.assertEquals(current_requested_qty_item2, existing_requested_qty_item2 + 1.5)
|
||||
|
||||
po.cancel()
|
||||
# check if per complete is as expected
|
||||
@@ -158,11 +156,15 @@ class TestMaterialRequest(unittest.TestCase):
|
||||
self.assertEquals(mr.get("indent_details")[0].ordered_qty, None)
|
||||
self.assertEquals(mr.get("indent_details")[1].ordered_qty, None)
|
||||
|
||||
self._test_requested_qty(54.0, 3.0)
|
||||
current_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC")
|
||||
current_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC")
|
||||
|
||||
self.assertEquals(current_requested_qty_item1, existing_requested_qty_item1 + 54.0)
|
||||
self.assertEquals(current_requested_qty_item2, existing_requested_qty_item2 + 3.0)
|
||||
|
||||
def test_completed_qty_for_transfer(self):
|
||||
frappe.db.sql("""delete from `tabBin`""")
|
||||
frappe.db.sql("""delete from `tabStock Ledger Entry`""")
|
||||
existing_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC")
|
||||
existing_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC")
|
||||
|
||||
# submit material request of type Purchase
|
||||
mr = frappe.copy_doc(test_records[0])
|
||||
@@ -175,7 +177,11 @@ class TestMaterialRequest(unittest.TestCase):
|
||||
self.assertEquals(mr.get("indent_details")[0].ordered_qty, 0)
|
||||
self.assertEquals(mr.get("indent_details")[1].ordered_qty, 0)
|
||||
|
||||
self._test_requested_qty(54.0, 3.0)
|
||||
current_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC")
|
||||
current_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC")
|
||||
|
||||
self.assertEquals(current_requested_qty_item1, existing_requested_qty_item1 + 54.0)
|
||||
self.assertEquals(current_requested_qty_item2, existing_requested_qty_item2 + 3.0)
|
||||
|
||||
from erpnext.stock.doctype.material_request.material_request import make_stock_entry
|
||||
|
||||
@@ -226,7 +232,11 @@ class TestMaterialRequest(unittest.TestCase):
|
||||
self.assertEquals(mr.get("indent_details")[0].ordered_qty, 27.0)
|
||||
self.assertEquals(mr.get("indent_details")[1].ordered_qty, 1.5)
|
||||
|
||||
self._test_requested_qty(27.0, 1.5)
|
||||
current_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC")
|
||||
current_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC")
|
||||
|
||||
self.assertEquals(current_requested_qty_item1, existing_requested_qty_item1 + 27.0)
|
||||
self.assertEquals(current_requested_qty_item2, existing_requested_qty_item2 + 1.5)
|
||||
|
||||
# check if per complete is as expected for Stock Entry cancelled
|
||||
se.cancel()
|
||||
@@ -235,11 +245,15 @@ class TestMaterialRequest(unittest.TestCase):
|
||||
self.assertEquals(mr.get("indent_details")[0].ordered_qty, 0)
|
||||
self.assertEquals(mr.get("indent_details")[1].ordered_qty, 0)
|
||||
|
||||
self._test_requested_qty(54.0, 3.0)
|
||||
current_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC")
|
||||
current_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC")
|
||||
|
||||
self.assertEquals(current_requested_qty_item1, existing_requested_qty_item1 + 54.0)
|
||||
self.assertEquals(current_requested_qty_item2, existing_requested_qty_item2 + 3.0)
|
||||
|
||||
def test_completed_qty_for_over_transfer(self):
|
||||
frappe.db.sql("""delete from `tabBin`""")
|
||||
frappe.db.sql("""delete from `tabStock Ledger Entry`""")
|
||||
existing_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC")
|
||||
existing_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC")
|
||||
|
||||
# submit material request of type Purchase
|
||||
mr = frappe.copy_doc(test_records[0])
|
||||
@@ -252,8 +266,6 @@ class TestMaterialRequest(unittest.TestCase):
|
||||
self.assertEquals(mr.get("indent_details")[0].ordered_qty, 0)
|
||||
self.assertEquals(mr.get("indent_details")[1].ordered_qty, 0)
|
||||
|
||||
self._test_requested_qty(54.0, 3.0)
|
||||
|
||||
# map a stock entry
|
||||
from erpnext.stock.doctype.material_request.material_request import make_stock_entry
|
||||
|
||||
@@ -297,7 +309,12 @@ class TestMaterialRequest(unittest.TestCase):
|
||||
self.assertEquals(mr.per_ordered, 100)
|
||||
self.assertEquals(mr.get("indent_details")[0].ordered_qty, 60.0)
|
||||
self.assertEquals(mr.get("indent_details")[1].ordered_qty, 3.0)
|
||||
self._test_requested_qty(0.0, 0.0)
|
||||
|
||||
current_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC")
|
||||
current_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC")
|
||||
|
||||
self.assertEquals(current_requested_qty_item1, existing_requested_qty_item1)
|
||||
self.assertEquals(current_requested_qty_item2, existing_requested_qty_item2)
|
||||
|
||||
# check if per complete is as expected for Stock Entry cancelled
|
||||
se.cancel()
|
||||
@@ -306,7 +323,11 @@ class TestMaterialRequest(unittest.TestCase):
|
||||
self.assertEquals(mr.get("indent_details")[0].ordered_qty, 0)
|
||||
self.assertEquals(mr.get("indent_details")[1].ordered_qty, 0)
|
||||
|
||||
self._test_requested_qty(54.0, 3.0)
|
||||
current_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC")
|
||||
current_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC")
|
||||
|
||||
self.assertEquals(current_requested_qty_item1, existing_requested_qty_item1 + 54.0)
|
||||
self.assertEquals(current_requested_qty_item2, existing_requested_qty_item2 + 3.0)
|
||||
|
||||
def test_incorrect_mapping_of_stock_entry(self):
|
||||
# submit material request of type Purchase
|
||||
@@ -348,5 +369,9 @@ class TestMaterialRequest(unittest.TestCase):
|
||||
mr.company = "_Test Company 1"
|
||||
self.assertRaises(InvalidWarehouseCompany, mr.insert)
|
||||
|
||||
def _get_requested_qty(self, item_code, warehouse):
|
||||
return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "indented_qty"))
|
||||
|
||||
|
||||
test_dependencies = ["Currency Exchange"]
|
||||
test_records = frappe.get_test_records('Material Request')
|
||||
|
||||
@@ -27,7 +27,7 @@ def get_bin_qty(item, warehouse):
|
||||
where item_code = %s and warehouse = %s""", (item, warehouse), as_dict = 1)
|
||||
return det and det[0] or ''
|
||||
|
||||
def update_packing_list_item(obj, packing_item_code, qty, warehouse, line, packing_list_idx):
|
||||
def update_packing_list_item(obj, packing_item_code, qty, warehouse, line):
|
||||
bin = get_bin_qty(packing_item_code, warehouse)
|
||||
item = get_packing_item_details(packing_item_code)
|
||||
|
||||
@@ -54,9 +54,7 @@ def update_packing_list_item(obj, packing_item_code, qty, warehouse, line, packi
|
||||
pi.warehouse = warehouse
|
||||
if not pi.batch_no:
|
||||
pi.batch_no = cstr(line.get("batch_no"))
|
||||
pi.idx = packing_list_idx
|
||||
|
||||
packing_list_idx += 1
|
||||
|
||||
|
||||
def make_packing_list(obj, item_table_fieldname):
|
||||
@@ -64,13 +62,11 @@ def make_packing_list(obj, item_table_fieldname):
|
||||
|
||||
if obj.get("_action") and obj._action == "update_after_submit": return
|
||||
|
||||
packing_list_idx = 0
|
||||
parent_items = []
|
||||
for d in obj.get(item_table_fieldname):
|
||||
if frappe.db.get_value("Sales BOM", {"new_item_code": d.item_code}):
|
||||
for i in get_sales_bom_items(d.item_code):
|
||||
update_packing_list_item(obj, i['item_code'], flt(i['qty'])*flt(d.qty),
|
||||
d.warehouse, d, packing_list_idx)
|
||||
update_packing_list_item(obj, i['item_code'], flt(i['qty'])*flt(d.qty), d.warehouse, d)
|
||||
|
||||
if [d.item_code, d.name] not in parent_items:
|
||||
parent_items.append([d.item_code, d.name])
|
||||
|
||||
@@ -1,264 +1,281 @@
|
||||
{
|
||||
"autoname": "PS.#######",
|
||||
"creation": "2013-04-11 15:32:24",
|
||||
"description": "Generate packing slips for packages to be delivered. Used to notify package number, package contents and its weight.",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Transaction",
|
||||
"autoname": "PS.#######",
|
||||
"creation": "2013-04-11 15:32:24",
|
||||
"description": "Generate packing slips for packages to be delivered. Used to notify package number, package contents and its weight.",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Transaction",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "packing_slip_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Packing Slip Items",
|
||||
"permlevel": 0,
|
||||
"fieldname": "packing_slip_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Packing Slip Items",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break0",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"fieldname": "column_break0",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "Indicates that the package is a part of this delivery (Only Draft)",
|
||||
"fieldname": "delivery_note",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Delivery Note",
|
||||
"options": "Delivery Note",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"description": "Indicates that the package is a part of this delivery (Only Draft)",
|
||||
"fieldname": "delivery_note",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Delivery Note",
|
||||
"options": "Delivery Note",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Series",
|
||||
"no_copy": 0,
|
||||
"options": "PS-",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Series",
|
||||
"no_copy": 0,
|
||||
"options": "PS-",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break0",
|
||||
"fieldtype": "Section Break",
|
||||
"permlevel": 0,
|
||||
"fieldname": "section_break0",
|
||||
"fieldtype": "Section Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break2",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"fieldname": "column_break2",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "Identification of the package for the delivery (for print)",
|
||||
"fieldname": "from_case_no",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "From Package No.",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1,
|
||||
"description": "Identification of the package for the delivery (for print)",
|
||||
"fieldname": "from_case_no",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "From Package No.",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1,
|
||||
"width": "50px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break3",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"fieldname": "column_break3",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "If more than one package of the same type (for print)",
|
||||
"fieldname": "to_case_no",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "To Package No.",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"description": "If more than one package of the same type (for print)",
|
||||
"fieldname": "to_case_no",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "To Package No.",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"width": "50px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "package_item_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Package Item Details",
|
||||
"permlevel": 0,
|
||||
"fieldname": "package_item_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Package Item Details",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "get_items",
|
||||
"fieldtype": "Button",
|
||||
"label": "Get Items",
|
||||
"fieldname": "get_items",
|
||||
"fieldtype": "Button",
|
||||
"label": "Get Items",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "item_details",
|
||||
"fieldtype": "Table",
|
||||
"label": "Items",
|
||||
"options": "Packing Slip Item",
|
||||
"permlevel": 0,
|
||||
"fieldname": "item_details",
|
||||
"fieldtype": "Table",
|
||||
"label": "Items",
|
||||
"options": "Packing Slip Item",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "package_weight_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Package Weight Details",
|
||||
"permlevel": 0,
|
||||
"fieldname": "package_weight_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Package Weight Details",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "The net weight of this package. (calculated automatically as sum of net weight of items)",
|
||||
"fieldname": "net_weight_pkg",
|
||||
"fieldtype": "Float",
|
||||
"label": "Net Weight",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"description": "The net weight of this package. (calculated automatically as sum of net weight of items)",
|
||||
"fieldname": "net_weight_pkg",
|
||||
"fieldtype": "Float",
|
||||
"label": "Net Weight",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "net_weight_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "Net Weight UOM",
|
||||
"no_copy": 1,
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"fieldname": "net_weight_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "Net Weight UOM",
|
||||
"no_copy": 1,
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break4",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"fieldname": "column_break4",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "The gross weight of the package. Usually net weight + packaging material weight. (for print)",
|
||||
"fieldname": "gross_weight_pkg",
|
||||
"fieldtype": "Float",
|
||||
"label": "Gross Weight",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"description": "The gross weight of the package. Usually net weight + packaging material weight. (for print)",
|
||||
"fieldname": "gross_weight_pkg",
|
||||
"fieldtype": "Float",
|
||||
"label": "Gross Weight",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "gross_weight_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "Gross Weight UOM",
|
||||
"no_copy": 1,
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"fieldname": "gross_weight_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "Gross Weight UOM",
|
||||
"no_copy": 1,
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "misc_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Misc Details",
|
||||
"permlevel": 0,
|
||||
"fieldname": "letter_head_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Letter Head",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"fieldname": "letter_head",
|
||||
"fieldtype": "Link",
|
||||
"label": "Letter Head",
|
||||
"options": "Letter Head",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "misc_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Misc Details",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Amended From",
|
||||
"no_copy": 1,
|
||||
"options": "Packing Slip",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Amended From",
|
||||
"no_copy": 1,
|
||||
"options": "Packing Slip",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"icon": "icon-suitcase",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-05-27 03:49:14.251039",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Packing Slip",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"icon": "icon-suitcase",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-11-13 16:50:50.423299",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Packing Slip",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Material User",
|
||||
"submit": 1,
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Material User",
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Sales User",
|
||||
"submit": 1,
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Sales User",
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Material Master Manager",
|
||||
"submit": 1,
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Material Master Manager",
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Material Manager",
|
||||
"submit": 1,
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Material Manager",
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Sales Manager",
|
||||
"submit": 1,
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Sales Manager",
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"read_only_onload": 1,
|
||||
],
|
||||
"read_only_onload": 1,
|
||||
"search_fields": "delivery_note"
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ from frappe.utils import cstr, flt, cint
|
||||
|
||||
from frappe import _
|
||||
import frappe.defaults
|
||||
from erpnext.stock.utils import update_bin
|
||||
|
||||
from erpnext.controllers.buying_controller import BuyingController
|
||||
|
||||
@@ -157,29 +156,19 @@ class PurchaseReceipt(BuyingController):
|
||||
self.make_sl_entries(sl_entries)
|
||||
|
||||
def update_ordered_qty(self):
|
||||
stock_items = self.get_stock_items()
|
||||
po_map = {}
|
||||
for d in self.get("purchase_receipt_details"):
|
||||
if d.item_code in stock_items and d.warehouse \
|
||||
and cstr(d.prevdoc_doctype) == 'Purchase Order':
|
||||
if d.prevdoc_doctype and d.prevdoc_doctype == "Purchase Order" and d.prevdoc_detail_docname:
|
||||
po_map.setdefault(d.prevdoc_docname, []).append(d.prevdoc_detail_docname)
|
||||
|
||||
already_received_qty = self.get_already_received_qty(d.prevdoc_docname,
|
||||
d.prevdoc_detail_docname)
|
||||
po_qty, ordered_warehouse = self.get_po_qty_and_warehouse(d.prevdoc_detail_docname)
|
||||
for po, po_item_rows in po_map.items():
|
||||
if po and po_item_rows:
|
||||
po_obj = frappe.get_doc("Purchase Order", po)
|
||||
|
||||
if not ordered_warehouse:
|
||||
frappe.throw(_("Warehouse is missing in Purchase Order"))
|
||||
if po_obj.status in ["Stopped", "Cancelled"]:
|
||||
frappe.throw(_("Material Request {0} is cancelled or stopped").format(po), frappe.InvalidStatusError)
|
||||
|
||||
if already_received_qty + d.qty > po_qty:
|
||||
ordered_qty = - (po_qty - already_received_qty) * flt(d.conversion_factor)
|
||||
else:
|
||||
ordered_qty = - flt(d.qty) * flt(d.conversion_factor)
|
||||
|
||||
update_bin({
|
||||
"item_code": d.item_code,
|
||||
"warehouse": ordered_warehouse,
|
||||
"posting_date": self.posting_date,
|
||||
"ordered_qty": flt(ordered_qty) if self.docstatus==1 else -flt(ordered_qty)
|
||||
})
|
||||
po_obj.update_ordered_qty(po_item_rows)
|
||||
|
||||
def get_already_received_qty(self, po, po_detail):
|
||||
qty = frappe.db.sql("""select sum(qty) from `tabPurchase Receipt Item`
|
||||
@@ -265,11 +254,13 @@ class PurchaseReceipt(BuyingController):
|
||||
|
||||
frappe.db.set(self,'status','Cancelled')
|
||||
|
||||
self.update_ordered_qty()
|
||||
|
||||
self.update_stock_ledger()
|
||||
|
||||
self.update_prevdoc_status()
|
||||
|
||||
# Must be called after updating received qty in PO
|
||||
self.update_ordered_qty()
|
||||
|
||||
pc_obj.update_last_purchase_rate(self, 0)
|
||||
|
||||
self.make_gl_entries_on_cancel()
|
||||
|
||||
@@ -253,8 +253,9 @@ def update_serial_nos(sle, item_det):
|
||||
from frappe.model.naming import make_autoname
|
||||
serial_nos = []
|
||||
for i in xrange(cint(sle.actual_qty)):
|
||||
serial_nos.append(make_autoname(item_det.serial_no_series))
|
||||
serial_nos.append(make_autoname(item_det.serial_no_series, "Serial No"))
|
||||
frappe.db.set(sle, "serial_no", "\n".join(serial_nos))
|
||||
validate_serial_no(sle, item_det)
|
||||
|
||||
if sle.serial_no:
|
||||
serial_nos = get_serial_nos(sle.serial_no)
|
||||
|
||||
@@ -39,8 +39,8 @@ class StockLedgerEntry(Document):
|
||||
(self.warehouse, self.item_code, self.batch_no))[0][0])
|
||||
|
||||
if batch_bal_after_transaction < 0:
|
||||
frappe.throw(_("Negative balance in Batch {0} for Item {1} at Warehouse {2} on {3} {4}").format(\
|
||||
batch_bal_after_transaction - self.actual_qty, self.item_code, self.warehouse,
|
||||
frappe.throw(_("Negative balance {0} in Batch {1} for Item {2} at Warehouse {3} on {4} {5}")
|
||||
.format(batch_bal_after_transaction - self.actual_qty, self.batch_no, self.item_code, self.warehouse,
|
||||
formatdate(self.posting_date), self.posting_time))
|
||||
|
||||
def validate_mandatory(self):
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Average "age" of an Item in a particular Warehouse based on First-in-first-out (FIFO).
|
||||
@@ -1 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
@@ -1,183 +0,0 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
frappe.pages['stock-ageing'].onload = function(wrapper) {
|
||||
frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: __('Stock Ageing'),
|
||||
single_column: true
|
||||
});
|
||||
|
||||
new erpnext.StockAgeing(wrapper);
|
||||
|
||||
|
||||
wrapper.appframe.add_module_icon("Stock")
|
||||
|
||||
}
|
||||
|
||||
frappe.require("assets/erpnext/js/stock_grid_report.js");
|
||||
|
||||
erpnext.StockAgeing = erpnext.StockGridReport.extend({
|
||||
init: function(wrapper) {
|
||||
this._super({
|
||||
title: __("Stock Ageing"),
|
||||
page: wrapper,
|
||||
parent: $(wrapper).find('.layout-main'),
|
||||
appframe: wrapper.appframe,
|
||||
doctypes: ["Item", "Warehouse", "Stock Ledger Entry", "Item Group", "Brand", "Serial No"],
|
||||
})
|
||||
},
|
||||
setup_columns: function() {
|
||||
this.columns = [
|
||||
{id: "name", name: __("Item"), field: "name", width: 300,
|
||||
link_formatter: {
|
||||
open_btn: true,
|
||||
doctype: '"Item"'
|
||||
}},
|
||||
{id: "item_name", name: __("Item Name"), field: "item_name",
|
||||
width: 100, formatter: this.text_formatter},
|
||||
{id: "description", name: __("Description"), field: "description",
|
||||
width: 200, formatter: this.text_formatter},
|
||||
{id: "brand", name: __("Brand"), field: "brand", width: 100},
|
||||
{id: "average_age", name: __("Average Age"), field: "average_age",
|
||||
formatter: this.currency_formatter},
|
||||
{id: "earliest", name: __("Earliest"), field: "earliest",
|
||||
formatter: this.currency_formatter},
|
||||
{id: "latest", name: __("Latest"), field: "latest",
|
||||
formatter: this.currency_formatter},
|
||||
{id: "stock_uom", name: "UOM", field: "stock_uom", width: 100},
|
||||
];
|
||||
},
|
||||
filters: [
|
||||
{fieldtype:"Select", label: __("Warehouse"), link:"Warehouse",
|
||||
default_value: "Select Warehouse..."},
|
||||
{fieldtype:"Select", label: __("Brand"), link:"Brand",
|
||||
default_value: "Select Brand...", filter: function(val, item, opts) {
|
||||
return val == opts.default_value || item.brand == val;
|
||||
}, link_formatter: {filter_input: "brand"}},
|
||||
{fieldtype:"Select", label: __("Plot By"),
|
||||
options: ["Average Age", "Earliest", "Latest"]},
|
||||
{fieldtype:"Date", label: __("To Date")},
|
||||
{fieldtype:"Button", label: __("Refresh"), icon:"icon-refresh icon-white"},
|
||||
{fieldtype:"Button", label: __("Reset Filters"), icon: "icon-filter"}
|
||||
],
|
||||
setup_filters: function() {
|
||||
var me = this;
|
||||
this._super();
|
||||
this.trigger_refresh_on_change(["warehouse", "plot_by", "brand"]);
|
||||
this.show_zero_check();
|
||||
},
|
||||
init_filter_values: function() {
|
||||
this._super();
|
||||
this.filter_inputs.to_date.val(dateutil.obj_to_user(new Date()));
|
||||
},
|
||||
prepare_data: function() {
|
||||
var me = this;
|
||||
|
||||
if(!this.data) {
|
||||
me._data = frappe.report_dump.data["Item"];
|
||||
me.item_by_name = me.make_name_map(me._data);
|
||||
}
|
||||
|
||||
this.data = [].concat(this._data);
|
||||
|
||||
this.serialized_buying_rates = this.get_serialized_buying_rates();
|
||||
|
||||
$.each(this.data, function(i, d) {
|
||||
me.reset_item_values(d);
|
||||
});
|
||||
|
||||
this.prepare_balances();
|
||||
|
||||
// filter out brand
|
||||
this.data = $.map(this.data, function(d) {
|
||||
return me.apply_filter(d, "brand") ? d : null;
|
||||
});
|
||||
|
||||
// filter out rows with zero values
|
||||
this.data = $.map(this.data, function(d) {
|
||||
return me.apply_zero_filter(null, d, null, me) ? d : null;
|
||||
});
|
||||
},
|
||||
prepare_balances: function() {
|
||||
var me = this;
|
||||
var to_date = dateutil.str_to_obj(this.to_date);
|
||||
var data = frappe.report_dump.data["Stock Ledger Entry"];
|
||||
|
||||
this.item_warehouse = {};
|
||||
|
||||
for(var i=0, j=data.length; i<j; i++) {
|
||||
var sl = data[i];
|
||||
var posting_date = dateutil.str_to_obj(sl.posting_date);
|
||||
|
||||
if(me.is_default("warehouse") ? true : me.warehouse == sl.warehouse) {
|
||||
var wh = me.get_item_warehouse(sl.warehouse, sl.item_code);
|
||||
|
||||
// call diff to build fifo stack in item_warehouse
|
||||
var diff = me.get_value_diff(wh, sl, true);
|
||||
|
||||
if(posting_date > to_date)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$.each(me.data, function(i, item) {
|
||||
var full_fifo_stack = [];
|
||||
if(me.is_default("warehouse")) {
|
||||
$.each(me.item_warehouse[item.name] || {}, function(i, wh) {
|
||||
full_fifo_stack = full_fifo_stack.concat(wh.fifo_stack || [])
|
||||
});
|
||||
} else {
|
||||
full_fifo_stack = me.get_item_warehouse(me.warehouse, item.name).fifo_stack || [];
|
||||
}
|
||||
|
||||
var age_qty = total_qty = 0.0;
|
||||
var min_age = max_age = null;
|
||||
|
||||
$.each(full_fifo_stack, function(i, batch) {
|
||||
var batch_age = dateutil.get_diff(me.to_date, batch[2]);
|
||||
age_qty += batch_age * batch[0];
|
||||
total_qty += batch[0];
|
||||
max_age = Math.max(max_age, batch_age);
|
||||
if(min_age===null) min_age=batch_age;
|
||||
else min_age = Math.min(min_age, batch_age);
|
||||
});
|
||||
|
||||
item.average_age = total_qty.toFixed(2)==0.0 ? 0
|
||||
: (age_qty / total_qty).toFixed(2);
|
||||
item.earliest = max_age || 0.0;
|
||||
item.latest = min_age || 0.0;
|
||||
});
|
||||
|
||||
this.data = this.data.sort(function(a, b) {
|
||||
var sort_by = me.plot_by.replace(" ", "_").toLowerCase();
|
||||
return b[sort_by] - a[sort_by];
|
||||
});
|
||||
},
|
||||
get_plot_data: function() {
|
||||
var data = [];
|
||||
var me = this;
|
||||
|
||||
data.push({
|
||||
label: me.plot_by,
|
||||
data: $.map(me.data, function(item, idx) {
|
||||
return [[idx+1, item[me.plot_by.replace(" ", "_").toLowerCase() ]]]
|
||||
}),
|
||||
bars: {show: true},
|
||||
});
|
||||
|
||||
return data.length ? data : false;
|
||||
},
|
||||
get_plot_options: function() {
|
||||
var me = this;
|
||||
return {
|
||||
grid: { hoverable: true, clickable: true },
|
||||
xaxis: {
|
||||
ticks: $.map(me.data, function(item, idx) { return [[idx+1, item.name]] }),
|
||||
max: 15
|
||||
},
|
||||
series: { downsample: { threshold: 1000 } }
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"creation": "2012-09-21 20:15:14.000000",
|
||||
"docstatus": 0,
|
||||
"doctype": "Page",
|
||||
"icon": "icon-table",
|
||||
"idx": 1,
|
||||
"modified": "2013-07-11 14:44:08.000000",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "stock-ageing",
|
||||
"owner": "Administrator",
|
||||
"page_name": "stock-ageing",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Analytics"
|
||||
},
|
||||
{
|
||||
"role": "Material Manager"
|
||||
}
|
||||
],
|
||||
"standard": "Yes",
|
||||
"title": "Stock Ageing"
|
||||
}
|
||||
@@ -42,13 +42,12 @@ def get_columns():
|
||||
|
||||
def get_fifo_queue(filters):
|
||||
item_details = {}
|
||||
prev_qty = 0.0
|
||||
for d in get_stock_ledger_entries(filters):
|
||||
item_details.setdefault(d.name, {"details": d, "fifo_queue": []})
|
||||
fifo_queue = item_details[d.name]["fifo_queue"]
|
||||
|
||||
if d.voucher_type == "Stock Reconciliation":
|
||||
d.actual_qty = flt(d.qty_after_transaction) - flt(prev_qty)
|
||||
d.actual_qty = flt(d.qty_after_transaction) - flt(item_details[d.name].get("qty_after_transaction", 0))
|
||||
|
||||
if d.actual_qty > 0:
|
||||
fifo_queue.append([d.actual_qty, d.posting_date])
|
||||
@@ -66,7 +65,7 @@ def get_fifo_queue(filters):
|
||||
batch[0] -= qty_to_pop
|
||||
qty_to_pop = 0
|
||||
|
||||
prev_qty = d.qty_after_transaction
|
||||
item_details[d.name]["qty_after_transaction"] = d.qty_after_transaction
|
||||
|
||||
return item_details
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ def make_sl_entries(sl_entries, is_amended=None):
|
||||
if sle.get('is_cancelled') == 'Yes':
|
||||
sle['actual_qty'] = -flt(sle['actual_qty'])
|
||||
|
||||
if sle.get("actual_qty") or sle.voucher_type=="Stock Reconciliation":
|
||||
if sle.get("actual_qty") or sle.get("voucher_type")=="Stock Reconciliation":
|
||||
sle_id = make_entry(sle)
|
||||
|
||||
args = sle.copy()
|
||||
|
||||
@@ -100,7 +100,7 @@ def get_fifo_rate(previous_stock_queue, qty):
|
||||
"""get FIFO (average) Rate from Queue"""
|
||||
if qty >= 0:
|
||||
total = sum(f[0] for f in previous_stock_queue)
|
||||
return total and sum(f[0] * f[1] for f in previous_stock_queue) / flt(total) or 0.0
|
||||
return sum(flt(f[0]) * flt(f[1]) for f in previous_stock_queue) / flt(total) if total else 0.0
|
||||
else:
|
||||
available_qty_for_outgoing, outgoing_cost = 0, 0
|
||||
qty_to_pop = abs(qty)
|
||||
|
||||
@@ -51,9 +51,14 @@ cur_frm.fields_dict['serial_no'].get_query = function(doc, cdt, cdn) {
|
||||
['Serial No', 'docstatus', '!=', 2],
|
||||
['Serial No', 'status', '=', "Delivered"]
|
||||
];
|
||||
if(doc.item_code) cond = ['Serial No', 'item_code', '=', doc.item_code];
|
||||
if(doc.customer) cond = ['Serial No', 'customer', '=', doc.customer];
|
||||
filter.push(cond);
|
||||
if(doc.item_code) {
|
||||
cond = ['Serial No', 'item_code', '=', doc.item_code];
|
||||
filter.push(cond);
|
||||
}
|
||||
if(doc.customer) {
|
||||
cond = ['Serial No', 'customer', '=', doc.customer];
|
||||
filter.push(cond);
|
||||
}
|
||||
return{
|
||||
filters:filter
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="col-xs-5 text-right">
|
||||
<label>{{ charge.get_formatted("description") }}</label></div>
|
||||
<div class="col-xs-7 text-right">
|
||||
{{ frappe.format_value(charge.tax_amount / doc.conversion_rate,
|
||||
{{ frappe.format_value(frappe.utils.flt(charge.tax_amount) / doc.conversion_rate,
|
||||
table_meta.get_field("tax_amount"), doc, currency=doc.currency) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,7 @@ A Supplier exists with same name,وهناك مورد موجود مع نفس ال
|
||||
A symbol for this currency. For e.g. $,رمزا لهذه العملة. على سبيل المثال ل$
|
||||
AMC Expiry Date,AMC تاريخ انتهاء الاشتراك
|
||||
Abbr,ابر
|
||||
Abbreviation cannot have more than 5 characters,اختصار لا يمكن أن يكون أكثر من 5 أحرف
|
||||
Abbreviation cannot have more than 5 characters,الاختصار لا يمكن أن يكون أكثر من 5 أحرف
|
||||
Above Value,فوق القيمة
|
||||
Absent,غائب
|
||||
Acceptance Criteria,معايير القبول
|
||||
@@ -69,7 +69,7 @@ Account {0} cannot be a Group,حساب {0} لا يمكن أن يكون مجمو
|
||||
Account {0} does not belong to Company {1},حساب {0} لا ينتمي إلى شركة {1}
|
||||
Account {0} does not belong to company: {1},حساب {0} لا تنتمي إلى الشركة: {1}
|
||||
Account {0} does not exist,حساب {0} غير موجود
|
||||
Account {0} has been entered more than once for fiscal year {1},حساب {0} تم إدخال أكثر من مرة للعام المالي {1}
|
||||
Account {0} has been entered more than once for fiscal year {1},تم إدخال حساب {0} أكثر من مرة للعام المالي {1}
|
||||
Account {0} is frozen,حساب {0} مجمد
|
||||
Account {0} is inactive,حساب {0} غير نشط
|
||||
Account {0} is not valid,حساب {0} غير صالح
|
||||
@@ -85,8 +85,8 @@ Accounting,المحاسبة
|
||||
"Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",قيد محاسبي المجمدة تصل إلى هذا التاريخ، لا أحد يمكن أن تفعل / تعديل إدخال باستثناء دور المحددة أدناه.
|
||||
Accounting journal entries.,المحاسبة إدخالات دفتر اليومية.
|
||||
Accounts,حسابات
|
||||
Accounts Browser,متصفح الحسابات
|
||||
Accounts Frozen Upto,حسابات مجمدة لغاية
|
||||
Accounts Browser,متصفح الحسابات
|
||||
Accounts Frozen Upto,حسابات مجمدة حتي
|
||||
Accounts Payable,ذمم دائنة
|
||||
Accounts Receivable,حسابات القبض
|
||||
Accounts Settings,إعدادات الحسابات
|
||||
@@ -94,7 +94,7 @@ Active,نشط
|
||||
Active: Will extract emails from ,نشط: سيتم استخراج رسائل البريد الإلكتروني من
|
||||
Activity,نشاط
|
||||
Activity Log,سجل النشاط
|
||||
Activity Log:,النشاط المفتاح:
|
||||
Activity Log:,:سجل النشاط
|
||||
Activity Type,نوع النشاط
|
||||
Actual,فعلي
|
||||
Actual Budget,الميزانية الفعلية
|
||||
@@ -253,8 +253,8 @@ Approving Role,الموافقة على دور
|
||||
Approving Role cannot be same as role the rule is Applicable To,الموافقة دور لا يمكن أن يكون نفس دور القاعدة تنطبق على
|
||||
Approving User,الموافقة العضو
|
||||
Approving User cannot be same as user the rule is Applicable To,الموافقة العضو لا يمكن أن يكون نفس المستخدم القاعدة تنطبق على
|
||||
Are you sure you want to STOP ,
|
||||
Are you sure you want to UNSTOP ,
|
||||
Are you sure you want to STOP ,Are you sure you want to STOP
|
||||
Are you sure you want to UNSTOP ,Are you sure you want to UNSTOP
|
||||
Arrear Amount,متأخرات المبلغ
|
||||
"As Production Order can be made for this item, it must be a stock item.",كما يمكن أن يتم ترتيب الإنتاج لهذا البند، يجب أن يكون بند الأوراق المالية .
|
||||
As per Stock UOM,وفقا للأوراق UOM
|
||||
@@ -283,7 +283,7 @@ Auto Accounting For Stock Settings,السيارات المحاسبة المال
|
||||
Auto Material Request,السيارات مادة طلب
|
||||
Auto-raise Material Request if quantity goes below re-order level in a warehouse,لصناعة السيارات في رفع طلب المواد إذا كمية يذهب دون مستوى إعادة الطلب في مستودع
|
||||
Automatically compose message on submission of transactions.,يؤلف تلقائيا رسالة على تقديم المعاملات.
|
||||
Automatically extract Job Applicants from a mail box ,
|
||||
Automatically extract Job Applicants from a mail box ,Automatically extract Job Applicants from a mail box
|
||||
Automatically extract Leads from a mail box e.g.,استخراج الشراء تلقائيا من صندوق البريد على سبيل المثال
|
||||
Automatically updated via Stock Entry of type Manufacture/Repack,تحديثها تلقائيا عن طريق إدخال الأسهم الصنع نوع / أعد حزم
|
||||
Automotive,السيارات
|
||||
@@ -410,16 +410,16 @@ Buying Settings,إعدادات الشراء
|
||||
"Buying must be checked, if Applicable For is selected as {0}",يجب أن يتم التحقق الشراء، إذا تم تحديد مطبق للك {0}
|
||||
C-Form,نموذج C-
|
||||
C-Form Applicable,C-نموذج قابل للتطبيق
|
||||
C-Form Invoice Detail,C-نموذج تفاصيل الفاتورة
|
||||
C-Form No,C-الاستمارة رقم
|
||||
C-Form records,سجلات نموذج C-
|
||||
C-Form Invoice Detail, تفاصيل الفاتورة نموذج - س
|
||||
C-Form No,رقم النموذج - س
|
||||
C-Form records,سجلات النموذج - س
|
||||
CENVAT Capital Goods,CENVAT السلع الرأسمالية
|
||||
CENVAT Edu Cess,CENVAT ايدو سيس
|
||||
CENVAT SHE Cess,CENVAT SHE سيس
|
||||
CENVAT Service Tax,CENVAT ضريبة الخدمة
|
||||
CENVAT Service Tax Cess 1,خدمة CENVAT ضريبة سيس 1
|
||||
CENVAT Service Tax Cess 2,خدمة CENVAT ضريبة سيس 2
|
||||
Calculate Based On,حساب الربح بناء على
|
||||
Calculate Based On,إحسب الربح بناء على
|
||||
Calculate Total Score,حساب النتيجة الإجمالية
|
||||
Calendar Events,الأحداث
|
||||
Call,دعوة
|
||||
@@ -510,8 +510,8 @@ Clearance Date,إزالة التاريخ
|
||||
Clearance Date not mentioned,إزالة التاريخ لم يرد ذكرها
|
||||
Clearance date cannot be before check date in row {0},تاريخ التخليص لا يمكن أن يكون قبل تاريخ الاختيار في الصف {0}
|
||||
Click on 'Make Sales Invoice' button to create a new Sales Invoice.,انقر على 'جعل مبيعات الفاتورة "الزر لإنشاء فاتورة مبيعات جديدة.
|
||||
Click on a link to get options to expand get options ,
|
||||
Client,عميل
|
||||
Click on a link to get options to expand get options ,Click on a link to get options to expand get options
|
||||
Client,عميل
|
||||
Close Balance Sheet and book Profit or Loss.,وثيقة الميزانية العمومية و كتاب الربح أو الخسارة .
|
||||
Closed,مغلق
|
||||
Closing (Cr),إغلاق (الكروم)
|
||||
@@ -538,7 +538,7 @@ Commission on Sales,عمولة على المبيعات
|
||||
Commission rate cannot be greater than 100,معدل العمولة لا يمكن أن يكون أكبر من 100
|
||||
Communication,اتصالات
|
||||
Communication HTML,الاتصالات HTML
|
||||
Communication History,الاتصال التاريخ
|
||||
Communication History,تاريخ الاتصال
|
||||
Communication log.,سجل الاتصالات.
|
||||
Communications,الاتصالات
|
||||
Company,شركة
|
||||
@@ -840,13 +840,13 @@ Distributor,موزع
|
||||
Divorced,المطلقات
|
||||
Do Not Contact,عدم الاتصال
|
||||
Do not show any symbol like $ etc next to currencies.,لا تظهر أي رمز مثل $ الخ بجانب العملات.
|
||||
Do really want to unstop production order: ,
|
||||
Do you really want to STOP ,
|
||||
Do really want to unstop production order: ,Do really want to unstop production order:
|
||||
Do you really want to STOP ,Do you really want to STOP
|
||||
Do you really want to STOP this Material Request?,هل تريد حقا لوقف هذا طلب المواد ؟
|
||||
Do you really want to Submit all Salary Slip for month {0} and year {1},هل تريد حقا لتقديم كل زلة الرواتب ل شهر {0} و السنة {1}
|
||||
Do you really want to UNSTOP ,
|
||||
Do you really want to UNSTOP ,Do you really want to UNSTOP
|
||||
Do you really want to UNSTOP this Material Request?,هل تريد حقا أن نزع السدادة هذا طلب المواد ؟
|
||||
Do you really want to stop production order: ,
|
||||
Do you really want to stop production order: ,Do you really want to stop production order:
|
||||
Doc Name,اسم الوثيقة
|
||||
Doc Type,نوع الوثيقة
|
||||
Document Description,وصف الوثيقة
|
||||
@@ -898,7 +898,7 @@ Electronics,إلكترونيات
|
||||
Email,البريد الإلكتروني
|
||||
Email Digest,البريد الإلكتروني دايجست
|
||||
Email Digest Settings,البريد الإلكتروني إعدادات دايجست
|
||||
Email Digest: ,
|
||||
Email Digest: ,Email Digest:
|
||||
Email Id,البريد الإلكتروني معرف
|
||||
"Email Id where a job applicant will email e.g. ""jobs@example.com""",معرف البريد الإلكتروني حيث طالب العمل سوف البريد الإلكتروني على سبيل المثال "jobs@example.com"
|
||||
Email Notifications,إشعارات البريد الإلكتروني
|
||||
@@ -958,7 +958,7 @@ Enter url parameter for receiver nos,أدخل عنوان URL لمعلمة NOS ا
|
||||
Entertainment & Leisure,الترفيه وترفيهية
|
||||
Entertainment Expenses,مصاريف الترفيه
|
||||
Entries,مقالات
|
||||
Entries against ,
|
||||
Entries against ,Entries against
|
||||
Entries are not allowed against this Fiscal Year if the year is closed.,لا يسمح مقالات ضد السنة المالية الحالية إذا تم إغلاق السنة.
|
||||
Equity,إنصاف
|
||||
Error: {0} > {1},الخطأ: {0} > {1}
|
||||
@@ -1573,7 +1573,7 @@ Maintenance Visit Purpose,صيانة زيارة الغرض
|
||||
Maintenance Visit {0} must be cancelled before cancelling this Sales Order,صيانة زيارة {0} يجب أن يتم إلغاء هذا الأمر قبل إلغاء المبيعات
|
||||
Maintenance start date can not be before delivery date for Serial No {0},صيانة تاريخ بداية لا يمكن أن يكون قبل تاريخ التسليم لل رقم المسلسل {0}
|
||||
Major/Optional Subjects,الرئيسية / اختياري الموضوعات
|
||||
Make ,
|
||||
Make ,Make
|
||||
Make Accounting Entry For Every Stock Movement,جعل الدخول المحاسبة للحصول على كل حركة الأسهم
|
||||
Make Bank Voucher,جعل قسيمة البنك
|
||||
Make Credit Note,جعل الائتمان ملاحظة
|
||||
@@ -1722,7 +1722,7 @@ Net Weight UOM,الوزن الصافي UOM
|
||||
Net Weight of each Item,الوزن الصافي لكل بند
|
||||
Net pay cannot be negative,صافي الأجور لا يمكن أن تكون سلبية
|
||||
Never,أبدا
|
||||
New ,
|
||||
New ,New
|
||||
New Account,حساب جديد
|
||||
New Account Name,اسم الحساب الجديد
|
||||
New BOM,BOM جديدة
|
||||
@@ -2448,7 +2448,7 @@ Rounded Off,تقريبها
|
||||
Rounded Total,تقريب إجمالي
|
||||
Rounded Total (Company Currency),المشاركات تقريب (العملة الشركة)
|
||||
Row # ,الصف #
|
||||
Row # {0}: ,
|
||||
Row # {0}: ,Row # {0}:
|
||||
Row #{0}: Ordered qty can not less than item's minimum order qty (defined in item master).,الصف # {0}: الكمية المطلوبة لا يمكن أن أقل من الحد الأدنى الكمية النظام القطعة (المحددة في البند الرئيسي).
|
||||
Row #{0}: Please specify Serial No for Item {1},الصف # {0}: يرجى تحديد رقم التسلسلي للتاريخ {1}
|
||||
Row {0}: Account does not match with \ Purchase Invoice Credit To account,الصف {0}: الحساب لا يتطابق مع \ شراء فاتورة الائتمان لحساب
|
||||
@@ -2750,7 +2750,7 @@ Stock Ageing,الأسهم شيخوخة
|
||||
Stock Analytics,الأسهم تحليلات
|
||||
Stock Assets,الموجودات الأسهم
|
||||
Stock Balance,الأسهم الرصيد
|
||||
Stock Entries already created for Production Order ,
|
||||
Stock Entries already created for Production Order ,Stock Entries already created for Production Order
|
||||
Stock Entry,الأسهم الدخول
|
||||
Stock Entry Detail,الأسهم إدخال التفاصيل
|
||||
Stock Expenses,مصاريف الأسهم
|
||||
@@ -3300,24 +3300,24 @@ website page link,الموقع رابط الصفحة
|
||||
{0} budget for Account {1} against Cost Center {2} will exceed by {3},{0} ميزانية الحساب {1} ضد مركز التكلفة {2} سيتجاوز التي كتبها {3}
|
||||
{0} can not be negative,{0} لا يمكن أن تكون سلبية
|
||||
{0} created,{0} خلق
|
||||
{0} does not belong to Company {1},{0} لا تنتمي إلى شركة {1}
|
||||
{0} does not belong to Company {1},{0} {لا تنتمي إلى شركة {1
|
||||
{0} entered twice in Item Tax,{0} دخلت مرتين في ضريبة المدينة
|
||||
{0} is an invalid email address in 'Notification Email Address',"{0} هو عنوان بريد إلكتروني غير صالح في ' عنوان البريد الإلكتروني إعلام """
|
||||
{0} is mandatory,{0} إلزامي
|
||||
{0} is mandatory for Item {1},{0} إلزامي القطعة ل {1}
|
||||
{0} is mandatory for Item {1},{0} {إلزامي القطعة ل {1
|
||||
{0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2}.,{0} إلزامي. ربما لا يتم إنشاء سجل سعر صرف العملة ل{1} إلى {2}.
|
||||
{0} is not a stock Item,{0} ليس الأسهم الإغلاق
|
||||
{0} is not a valid Batch Number for Item {1},{0} ليس رقم الدفعة صالحة لل تفاصيل {1}
|
||||
{0} is not a valid Leave Approver. Removing row #{1}.,{0} ليس صحيحا اترك الموافق. إزالة الصف # {1}.
|
||||
{0} is not a valid Leave Approver. Removing row #{1}.,{0} {ليس صحيحا اترك الموافق. إزالة الصف # {1.
|
||||
{0} is not a valid email id,{0} ليس معرف بريد إلكتروني صحيح
|
||||
{0} is now the default Fiscal Year. Please refresh your browser for the change to take effect.,{0} الآن الافتراضي السنة المالية. يرجى تحديث المتصفح ل التغيير نافذ المفعول .
|
||||
{0} is required,{0} مطلوب
|
||||
{0} must be a Purchased or Sub-Contracted Item in row {1},{0} يجب أن يكون البند شراؤها أو التعاقد الفرعي في الصف {1}
|
||||
{0} must be reduced by {1} or you should increase overflow tolerance,{0} يجب تخفيض كتبها {1} أو يجب زيادة الفائض التسامح
|
||||
{0} must have role 'Leave Approver',{0} يجب أن يكون دور ' اترك الموافق '
|
||||
{0} valid serial nos for Item {1},{0} غ المسلسل صالحة لل تفاصيل {1}
|
||||
{0} {1} against Bill {2} dated {3},{0} {1} ضد بيل {2} بتاريخ {3}
|
||||
{0} {1} against Invoice {2},{0} {1} ضد الفاتورة {2}
|
||||
{0} valid serial nos for Item {1},{0} {غ المسلسل صالحة لل تفاصيل {1
|
||||
{0} {1} against Bill {2} dated {3},{0} {1} {ضد بيل {2} بتاريخ {3
|
||||
{0} {1} against Invoice {2},{0} {1} {ضد الفاتورة {2
|
||||
{0} {1} has already been submitted,{0} {1} وقد تم بالفعل قدمت
|
||||
{0} {1} has been modified. Please refresh.,{0} {1} تم تعديل . يرجى تحديث.
|
||||
{0} {1} is not submitted,{0} {1} لا تقدم
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -36,20 +36,20 @@
|
||||
"<h4>Default Template</h4><p>Uses <a href=""http://jinja.pocoo.org/docs/templates/"">Jinja Templating</a> and all the fields of Address (including Custom Fields if any) will be available</p><pre><code>{{ address_line1 }}<br>{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}{{ city }}<br>{% if state %}{{ state }}<br>{% endif -%}{% if pincode %} PIN: {{ pincode }}<br>{% endif -%}{{ country }}<br>{% if phone %}Phone: {{ phone }}<br>{% endif -%}{% if fax %}Fax: {{ fax }}<br>{% endif -%}{% if email_id %}Email: {{ email_id }}<br>{% endif -%}</code></pre>","<h4> Προεπιλογή Πρότυπο </ h4> <p> Χρήσεις <a href=""http://jinja.pocoo.org/docs/templates/""> Jinja Templating </ a> και όλα τα πεδία της Διεύθυνσης ( συμπεριλαμβανομένων των προσαρμοσμένων πεδίων, αν υπάρχουν) θα είναι διαθέσιμο </ p> <pre> <code> {{}} address_line1 <br> {% εάν address_line2%} {{}} address_line2 <br> { endif% -%} {{}} πόλη <br> {% αν το κράτος%} {{}} κατάσταση <br> {endif% -%} {% εάν pincode%} PIN: {{}} pincode <br> {endif% -%} {{}} χώρα <br> {% αν το τηλέφωνο%} Τηλέφωνο: {{}} τηλέφωνο <br> { endif% -%} {% εάν φαξ%} Fax: {{}} fax <br> {endif% -%} {% εάν email_id%} Email: {{}} email_id <br> ? {endif% -%} </ code> </ pre>"
|
||||
A Customer Group exists with same name please change the Customer name or rename the Customer Group,Μια ομάδα πελατών υπάρχει με το ίδιο όνομα παρακαλούμε να αλλάξετε το όνομα του Πελάτη ή να μετονομάσετε την ομάδα πελατών
|
||||
A Customer exists with same name,Ένας πελάτης υπάρχει με το ίδιο όνομα
|
||||
A Lead with this email id should exist,Μια μολύβδου με αυτή την ταυτότητα ηλεκτρονικού ταχυδρομείου θα πρέπει να υπάρχει
|
||||
A Lead with this email id should exist,Μια επαφή με αυτή τη διεύθυνση ηλεκτρονικού ταχυδρομείου θα πρέπει να υπάρχει
|
||||
A Product or Service,Ένα Προϊόν ή Υπηρεσία
|
||||
A Supplier exists with same name,Ένας προμηθευτής υπάρχει με το ίδιο όνομα
|
||||
A symbol for this currency. For e.g. $,Ένα σύμβολο για το νόμισμα αυτό. Για παράδειγμα $
|
||||
AMC Expiry Date,AMC Ημερομηνία Λήξης
|
||||
Abbr,Συντ.
|
||||
Abbreviation cannot have more than 5 characters,Μια συντομογραφία δεν μπορεί να έχει περισσότερα από 5 χαρακτήρες
|
||||
Abbreviation cannot have more than 5 characters,Μια συντομογραφία δεν μπορεί να έχει περισσότερους από 5 χαρακτήρες
|
||||
Above Value,Πάνω Value
|
||||
Absent,Απών
|
||||
Acceptance Criteria,Κριτήρια αποδοχής
|
||||
Acceptance Criteria,Αποδοχή κριτήρίων
|
||||
Accepted,Δεκτός
|
||||
Accepted + Rejected Qty must be equal to Received quantity for Item {0},Αποδεκτές + Απορρίπτεται Ποσότητα πρέπει να είναι ίση με Ελήφθη ποσότητα για τη θέση {0}
|
||||
Accepted Quantity,ΠΟΣΟΤΗΤΑ
|
||||
Accepted Warehouse,Αποδεκτές αποθήκη
|
||||
Accepted + Rejected Qty must be equal to Received quantity for Item {0},Η Αποδεκτή + η Απορριπτέα ποσότητα πρέπει να είναι ίση με ληφθήσα ποσότητα για τη θέση {0}
|
||||
Accepted Quantity,Αποδεκτή ποσότητα
|
||||
Accepted Warehouse,Αποδεκτή Aποθήκη
|
||||
Account,Λογαριασμός
|
||||
Account Balance,Υπόλοιπο Λογαριασμού
|
||||
Account Created: {0},Ο λογαριασμός δημιουργήθηκε : {0}
|
||||
@@ -57,8 +57,8 @@ Account Details,Στοιχεία Λογαριασμού
|
||||
Account Head,Επικεφαλής λογαριασμού
|
||||
Account Name,Όνομα λογαριασμού
|
||||
Account Type,Είδος Λογαριασμού
|
||||
"Account balance already in Credit, you are not allowed to set 'Balance Must Be' as 'Debit'","Το υπόλοιπο του λογαριασμού ήδη Credit, δεν σας επιτρέπεται να θέσει «Υπόλοιπο Must Be» ως «χρεωστικές»"
|
||||
"Account balance already in Debit, you are not allowed to set 'Balance Must Be' as 'Credit'","Το υπόλοιπο του λογαριασμού ήδη Debit, δεν μπορείτε να ρυθμίσετε το 'Υπόλοιπο Must Be »ως« Δάνειο »"
|
||||
"Account balance already in Credit, you are not allowed to set 'Balance Must Be' as 'Debit'","Το υπόλοιπο του λογαριασμού είναι ήδη πιστωτικό, δεν επιτρέπεται να ρυθμίσετε το «Υπόλοιπο πρέπει να είναι χρεωστικό»"
|
||||
"Account balance already in Debit, you are not allowed to set 'Balance Must Be' as 'Credit'","Το υπόλοιπο του λογαριασμού ήδη χρεωστικό, δεν μπορείτε να ρυθμίσετε το 'Υπόλοιπο πρέπει να είναι ως Δάνειο »"
|
||||
Account for the warehouse (Perpetual Inventory) will be created under this Account.,Λογαριασμός για την αποθήκη ( Perpetual Απογραφή ) θα δημιουργηθεί στο πλαίσιο του παρόντος λογαριασμού.
|
||||
Account head {0} created,Κεφάλι Λογαριασμός {0} δημιουργήθηκε
|
||||
Account must be a balance sheet account,Ο λογαριασμός πρέπει να είναι λογαριασμός του ισολογισμού
|
||||
@@ -214,8 +214,8 @@ Amended From,Τροποποίηση Από
|
||||
Amount,Ποσό
|
||||
Amount (Company Currency),Ποσό (νόμισμα της Εταιρείας)
|
||||
Amount Paid,Ποσό Αμειβόμενος
|
||||
Amount to Bill,Ανέρχονται σε Bill
|
||||
An Customer exists with same name,Υπάρχει ένα πελάτη με το ίδιο όνομα
|
||||
Amount to Bill,Χρεώσιμο Ποσό
|
||||
An Customer exists with same name,Υπάρχει πελάτης με το ίδιο όνομα
|
||||
"An Item Group exists with same name, please change the item name or rename the item group","Ένα σημείο της ομάδας υπάρχει με το ίδιο όνομα , μπορείτε να αλλάξετε το όνομα του στοιχείου ή να μετονομάσετε την ομάδα στοιχείου"
|
||||
"An item exists with same name ({0}), please change the item group name or rename the item","Ένα στοιχείο υπάρχει με το ίδιο όνομα ( {0} ) , παρακαλούμε να αλλάξετε το όνομα της ομάδας στοιχείου ή να μετονομάσετε το στοιχείο"
|
||||
Analyst,αναλυτής
|
||||
@@ -254,14 +254,14 @@ Approving Role,Έγκριση Ρόλος
|
||||
Approving Role cannot be same as role the rule is Applicable To,"Έγκριση ρόλος δεν μπορεί να είναι ίδιο με το ρόλο , ο κανόνας είναι να εφαρμόζεται"
|
||||
Approving User,Έγκριση χρήστη
|
||||
Approving User cannot be same as user the rule is Applicable To,Την έγκριση του χρήστη δεν μπορεί να είναι ίδιο με το χρήστη ο κανόνας ισχύει για
|
||||
Are you sure you want to STOP ,
|
||||
Are you sure you want to UNSTOP ,
|
||||
Are you sure you want to STOP ,Είσαστε σίγουροι πως θέλετε να σταματήσετε
|
||||
Are you sure you want to UNSTOP ,Are you sure you want to UNSTOP
|
||||
Arrear Amount,Καθυστερήσεις Ποσό
|
||||
"As Production Order can be made for this item, it must be a stock item.","Όπως μπορεί να γίνει Παραγωγής παραγγελίας για το συγκεκριμένο προϊόν , θα πρέπει να είναι ένα στοιχείο υλικού."
|
||||
As per Stock UOM,Όπως ανά Διαθέσιμο UOM
|
||||
"As there are existing stock transactions for this item, you can not change the values of 'Has Serial No', 'Is Stock Item' and 'Valuation Method'","Δεδομένου ότι υπάρχουν χρηματιστηριακές συναλλαγές για αυτό το στοιχείο , δεν μπορείτε να αλλάξετε τις τιμές των « Έχει Αύξων αριθμός », « Είναι Stock σημείο » και « Μέθοδος αποτίμησης»"
|
||||
Asset,προσόν
|
||||
Assistant,βοηθός
|
||||
Assistant,Βοηθός
|
||||
Associate,Συνεργάτης
|
||||
Atleast one of the Selling or Buying must be selected,Πρέπει να επιλεγεί τουλάχιστον μία από τις πωλήσεις ή την αγορά
|
||||
Atleast one warehouse is mandatory,"Τουλάχιστον, μια αποθήκη είναι υποχρεωτική"
|
||||
@@ -270,27 +270,27 @@ Attach Letterhead,Συνδέστε επιστολόχαρτο
|
||||
Attach Logo,Συνδέστε Logo
|
||||
Attach Your Picture,Προσαρμόστε την εικόνα σας
|
||||
Attendance,Παρουσία
|
||||
Attendance Date,Ημερομηνία Συμμετοχή
|
||||
Attendance Details,Λεπτομέρειες Συμμετοχή
|
||||
Attendance Date,Ημερομηνία Συμμετοχής
|
||||
Attendance Details,Λεπτομέρειες Συμμετοχής
|
||||
Attendance From Date,Συμμετοχή Από Ημερομηνία
|
||||
Attendance From Date and Attendance To Date is mandatory,Συμμετοχή Από Ημερομηνία και φοίτηση μέχρι σήμερα είναι υποχρεωτική
|
||||
Attendance To Date,Συμμετοχή σε Ημερομηνία
|
||||
Attendance From Date and Attendance To Date is mandatory,Η συμμετοχή Από και Μέχρι είναι υποχρεωτική
|
||||
Attendance To Date,Προσέλευση μέχρι Ημερομηνία
|
||||
Attendance can not be marked for future dates,Συμμετοχή δεν μπορεί να επιλεγεί για τις μελλοντικές ημερομηνίες
|
||||
Attendance for employee {0} is already marked,Συμμετοχή των εργαζομένων για {0} έχει ήδη σημειώνονται
|
||||
Attendance record.,Ρεκόρ προσέλευσης.
|
||||
Authorization Control,Έλεγχος της χορήγησης αδειών
|
||||
Authorization Rule,Κανόνας Εξουσιοδότηση
|
||||
Attendance for employee {0} is already marked,Συμμετοχή για εργαζομένο {0} έχει ήδη σημειώθει
|
||||
Attendance record.,Καταχωρήσεις Προσέλευσης.
|
||||
Authorization Control,Έλεγχος Εξουσιοδότησης
|
||||
Authorization Rule,Κανόνας Εξουσιοδότησης
|
||||
Auto Accounting For Stock Settings,Auto Λογιστικά Για Ρυθμίσεις Χρηματιστήριο
|
||||
Auto Material Request,Αυτόματη Αίτηση Υλικό
|
||||
Auto-raise Material Request if quantity goes below re-order level in a warehouse,Auto-raise Αίτηση Υλικό εάν η ποσότητα πέσει κάτω εκ νέου για το επίπεδο σε μια αποθήκη
|
||||
Automatically compose message on submission of transactions.,Αυτόματη συνθέτουν το μήνυμα για την υποβολή των συναλλαγών .
|
||||
Automatically extract Job Applicants from a mail box ,
|
||||
Automatically extract Job Applicants from a mail box ,Automatically extract Job Applicants from a mail box
|
||||
Automatically extract Leads from a mail box e.g.,"Αυτόματη εξαγωγή οδηγεί από ένα κουτί αλληλογραφίας , π.χ."
|
||||
Automatically updated via Stock Entry of type Manufacture/Repack,Αυτόματη ενημέρωση μέσω είσοδο στα αποθέματα Κατασκευή Τύπος / Repack
|
||||
Automotive,Αυτοκίνητο
|
||||
Autoreply when a new mail is received,Autoreply όταν λαμβάνονται νέα μηνύματα
|
||||
Available,Διαθέσιμος
|
||||
Available Qty at Warehouse,Διαθέσιμο Ποσότητα σε αποθήκη
|
||||
Available Qty at Warehouse,Διαθέσιμο Ποσότητα στην Αποθήκη
|
||||
Available Stock for Packing Items,Διαθέσιμο Διαθέσιμο για είδη συσκευασίας
|
||||
"Available in BOM, Delivery Note, Purchase Invoice, Production Order, Purchase Order, Purchase Receipt, Sales Invoice, Sales Order, Stock Entry, Timesheet","Διατίθεται σε BOM , Δελτίο Αποστολής , Τιμολόγιο Αγοράς , Παραγωγής Τάξης, Παραγγελία Αγοράς, Αγορά Παραλαβή , Πωλήσεις Τιμολόγιο , Πωλήσεις Τάξης , Stock Έναρξη , φύλλο κατανομής χρόνου"
|
||||
Average Age,Μέσος όρος ηλικίας
|
||||
@@ -511,7 +511,7 @@ Clearance Date,Ημερομηνία Εκκαθάριση
|
||||
Clearance Date not mentioned,Εκκαθάριση Ημερομηνία που δεν αναφέρονται
|
||||
Clearance date cannot be before check date in row {0},Ημερομηνία εκκαθάρισης δεν μπορεί να είναι πριν από την ημερομηνία άφιξης στη γραμμή {0}
|
||||
Click on 'Make Sales Invoice' button to create a new Sales Invoice.,Κάντε κλικ στο «Κάνε Πωλήσεις Τιμολόγιο» για να δημιουργηθεί μια νέα τιμολογίου πώλησης.
|
||||
Click on a link to get options to expand get options ,
|
||||
Click on a link to get options to expand get options ,Click on a link to get options to expand get options
|
||||
Client,Πελάτης
|
||||
Close Balance Sheet and book Profit or Loss.,Κλείσιμο Ισολογισμού και των Αποτελεσμάτων βιβλίο ή απώλεια .
|
||||
Closed,Κλειστό
|
||||
@@ -841,13 +841,13 @@ Distributor,Διανομέας
|
||||
Divorced,Διαζευγμένος
|
||||
Do Not Contact,Μην Επικοινωνία
|
||||
Do not show any symbol like $ etc next to currencies.,Να μην εμφανίζεται κανένα σύμβολο όπως $ κλπ δίπλα σε νομίσματα.
|
||||
Do really want to unstop production order: ,
|
||||
Do you really want to STOP ,
|
||||
Do really want to unstop production order: ,Do really want to unstop production order:
|
||||
Do you really want to STOP ,Do you really want to STOP
|
||||
Do you really want to STOP this Material Request?,Θέλετε πραγματικά να σταματήσει αυτό το υλικό την Αίτηση Συμμετοχής;
|
||||
Do you really want to Submit all Salary Slip for month {0} and year {1},Θέλετε πραγματικά να υποβληθούν όλα τα Slip Μισθός για το μήνα {0} και {1 χρόνο }
|
||||
Do you really want to UNSTOP ,
|
||||
Do you really want to UNSTOP ,Do you really want to UNSTOP
|
||||
Do you really want to UNSTOP this Material Request?,Θέλετε πραγματικά να ξεβουλώνω αυτό Υλικό Αίτηση Συμμετοχής;
|
||||
Do you really want to stop production order: ,
|
||||
Do you really want to stop production order: ,Do you really want to stop production order:
|
||||
Doc Name,Doc Name
|
||||
Doc Type,Doc Τύπος
|
||||
Document Description,Περιγραφή εγγράφου
|
||||
@@ -899,7 +899,7 @@ Electronics,ηλεκτρονική
|
||||
Email,Email
|
||||
Email Digest,Email Digest
|
||||
Email Digest Settings,Email Digest Ρυθμίσεις
|
||||
Email Digest: ,
|
||||
Email Digest: ,Email Digest:
|
||||
Email Id,Id Email
|
||||
"Email Id where a job applicant will email e.g. ""jobs@example.com""","Email Id, όπου ένας υποψήφιος θα e-mail π.χ. "jobs@example.com""
|
||||
Email Notifications,Ειδοποιήσεις μέσω ηλεκτρονικού ταχυδρομείου
|
||||
@@ -959,7 +959,7 @@ Enter url parameter for receiver nos,Εισάγετε παράμετρο url γ
|
||||
Entertainment & Leisure,Διασκέδαση & Leisure
|
||||
Entertainment Expenses,Έξοδα Ψυχαγωγία
|
||||
Entries,Καταχωρήσεις
|
||||
Entries against ,
|
||||
Entries against ,Entries against
|
||||
Entries are not allowed against this Fiscal Year if the year is closed.,"Οι συμμετοχές δεν επιτρέπεται κατά το τρέχον οικονομικό έτος, εάν το έτος είναι κλειστή."
|
||||
Equity,δικαιοσύνη
|
||||
Error: {0} > {1},Σφάλμα : {0} > {1}
|
||||
@@ -1480,18 +1480,18 @@ Language,Γλώσσα
|
||||
Last Name,Επώνυμο
|
||||
Last Purchase Rate,Τελευταία Τιμή Αγοράς
|
||||
Latest,αργότερο
|
||||
Lead,Μόλυβδος
|
||||
Lead Details,Μόλυβδος Λεπτομέρειες
|
||||
Lead Id,Μόλυβδος Id
|
||||
Lead Name,Μόλυβδος Name
|
||||
Lead Owner,Μόλυβδος Ιδιοκτήτης
|
||||
Lead Source,Μόλυβδος Πηγή
|
||||
Lead Status,Lead Κατάσταση
|
||||
Lead Time Date,Μόλυβδος Ημερομηνία Ώρα
|
||||
Lead Time Days,Μόλυβδος Ημέρες Ώρα
|
||||
Lead Time days is number of days by which this item is expected in your warehouse. This days is fetched in Material Request when you select this item.,"Μόλυβδος μέρες είναι ο αριθμός των ημερών κατά τον οποίο το στοιχείο αυτό αναμένεται στην αποθήκη σας. Αυτό μέρες είναι παρατραβηγμένο σε αίτημα αφορά υλικό, όταν επιλέξετε αυτό το στοιχείο."
|
||||
Lead Type,Μόλυβδος Τύπος
|
||||
Lead must be set if Opportunity is made from Lead,Ο μόλυβδος πρέπει να οριστεί αν Ευκαιρία είναι κατασκευασμένο από μόλυβδο
|
||||
Lead,Επαφή
|
||||
Lead Details,Λεπτομέρειες Επαφής
|
||||
Lead Id,Id Επαφής
|
||||
Lead Name,Όνομα Επαφής
|
||||
Lead Owner,Ιδιοκτήτης Επαφής
|
||||
Lead Source,Από που προήρθε η Επαφή
|
||||
Lead Status,Κατάσταση Επαφής
|
||||
Lead Time Date,Ημερομηνία Ώρα Επαφής
|
||||
Lead Time Days,Ημέρα Ώρα Επαφής
|
||||
Lead Time days is number of days by which this item is expected in your warehouse. This days is fetched in Material Request when you select this item.,"Ο χρόνος παράδοσης σε ημέρες είναι ο αριθμός των ημερών κατά τον οποίο το στοιχείο αυτό αναμένεται στην αποθήκη σας. Αυτές οι μέρες αναφέρεται σε αίτημα που αφορά υλικό, όταν επιλέξετε αυτό το στοιχείο."
|
||||
Lead Type,Τύπος Επαφής
|
||||
Lead must be set if Opportunity is made from Lead,Η Επαφή πρέπει να οριστεί αν η Ευκαιρία προέρχεται από επαφή
|
||||
Leave Allocation,Αφήστε Κατανομή
|
||||
Leave Allocation Tool,Αφήστε το εργαλείο Κατανομή
|
||||
Leave Application,Αφήστε Εφαρμογή
|
||||
@@ -1574,7 +1574,7 @@ Maintenance Visit Purpose,Σκοπός Συντήρηση Επίσκεψη
|
||||
Maintenance Visit {0} must be cancelled before cancelling this Sales Order,Συντήρηση Επίσκεψη {0} πρέπει να ακυρωθεί πριν από την ακύρωση αυτής της παραγγελίας πώλησης
|
||||
Maintenance start date can not be before delivery date for Serial No {0},Ημερομηνία έναρξης συντήρησης δεν μπορεί να είναι πριν από την ημερομηνία παράδοσης Αύξων αριθμός {0}
|
||||
Major/Optional Subjects,Σημαντικές / προαιρετικά μαθήματα
|
||||
Make ,
|
||||
Make ,Make
|
||||
Make Accounting Entry For Every Stock Movement,Κάντε Λογιστική καταχώρηση για κάθε Κίνημα Χρηματιστήριο
|
||||
Make Bank Voucher,Κάντε Voucher Bank
|
||||
Make Credit Note,Κάντε Πιστωτικό Σημείωμα
|
||||
@@ -1723,7 +1723,7 @@ Net Weight UOM,Καθαρό Βάρος UOM
|
||||
Net Weight of each Item,Καθαρό βάρος κάθε είδους
|
||||
Net pay cannot be negative,Καθαρή αμοιβή δεν μπορεί να είναι αρνητική
|
||||
Never,Ποτέ
|
||||
New ,
|
||||
New ,New
|
||||
New Account,Νέος λογαριασμός
|
||||
New Account Name,Νέο Όνομα λογαριασμού
|
||||
New BOM,Νέα BOM
|
||||
@@ -2449,7 +2449,7 @@ Rounded Off,στρογγυλοποιηθεί
|
||||
Rounded Total,Στρογγυλεμένες Σύνολο
|
||||
Rounded Total (Company Currency),Στρογγυλεμένες Σύνολο (νόμισμα της Εταιρείας)
|
||||
Row # ,Row #
|
||||
Row # {0}: ,
|
||||
Row # {0}: ,Row # {0}:
|
||||
Row #{0}: Ordered qty can not less than item's minimum order qty (defined in item master).,Σειρά # {0}: Διέταξε ποσότητα δεν μπορεί να μικρότερη από την ελάχιστη ποσότητα σειρά στοιχείου (όπως ορίζεται στο σημείο master).
|
||||
Row #{0}: Please specify Serial No for Item {1},Σειρά # {0}: Παρακαλείστε να προσδιορίσετε Αύξων αριθμός για τη θέση {1}
|
||||
Row {0}: Account does not match with \ Purchase Invoice Credit To account,Σειρά {0}: Ο λογαριασμός δεν ταιριάζει με \ τιμολογίου αγοράς πίστωση του λογαριασμού
|
||||
@@ -3277,8 +3277,8 @@ Your support email id - must be a valid email - this is where your emails will c
|
||||
[Select],[ Επιλέξτε ]
|
||||
`Freeze Stocks Older Than` should be smaller than %d days.,` Τα αποθέματα Πάγωμα Παλαιότερο από ` θα πρέπει να είναι μικρότερη από % d ημέρες .
|
||||
and,και
|
||||
are not allowed.,δεν επιτρέπονται .
|
||||
assigned by,ανατεθεί από
|
||||
are not allowed.,δεν επιτρέπονται.
|
||||
assigned by,Ανατέθηκε από
|
||||
cannot be greater than 100,δεν μπορεί να είναι μεγαλύτερη από 100
|
||||
"e.g. ""Build tools for builders""","π.χ. «Χτίστε εργαλεία για τους κατασκευαστές """
|
||||
"e.g. ""MC""","π.χ. "" MC """
|
||||
@@ -3317,7 +3317,7 @@ website page link,Ιστοσελίδα link της σελίδας
|
||||
{0} must be reduced by {1} or you should increase overflow tolerance,{0} πρέπει να μειωθεί κατά {1} ή θα πρέπει να αυξήσει την ανοχή υπερχείλισης
|
||||
{0} must have role 'Leave Approver',{0} πρέπει να έχει ρόλο « Αφήστε Έγκρισης »
|
||||
{0} valid serial nos for Item {1},{0} έγκυρο σειριακό nos για τη θέση {1}
|
||||
{0} {1} against Bill {2} dated {3},{0} {1} εναντίον Bill {2} { 3 με ημερομηνία }
|
||||
{0} {1} against Bill {2} dated {3},{0} {1} εναντίον Bill {2} {3} με ημερομηνία
|
||||
{0} {1} against Invoice {2},{0} {1} κατά Τιμολόγιο {2}
|
||||
{0} {1} has already been submitted,{0} {1} έχει ήδη υποβληθεί
|
||||
{0} {1} has been modified. Please refresh.,{0} {1} έχει τροποποιηθεί . Παρακαλώ ανανεώσετε .
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user