Merge branch 'develop'
This commit is contained in:
commit
54938d431c
@ -1,5 +1,9 @@
|
||||
# Contributing to Frappe / ERPNext
|
||||
|
||||
### Update 16-Sep-14
|
||||
|
||||
Please send pull requests to branch v5.0
|
||||
|
||||
## Reporting issues
|
||||
|
||||
We only accept issues that are bug reports or feature requests. Bugs must be isolated and reproducible problems. Please read the following guidelines before opening any issue.
|
||||
|
@ -1 +1 @@
|
||||
__version__ = '4.3.0'
|
||||
__version__ = '4.4.0'
|
||||
|
@ -169,15 +169,13 @@ class Account(Document):
|
||||
|
||||
def validate_due_date(self, posting_date, due_date):
|
||||
credit_days = (self.credit_days or frappe.db.get_value("Company", self.company, "credit_days"))
|
||||
if credit_days is None:
|
||||
return
|
||||
|
||||
posting_date, due_date = getdate(posting_date), getdate(due_date)
|
||||
diff = (due_date - posting_date).days
|
||||
|
||||
if diff < 0:
|
||||
frappe.throw(_("Due Date cannot be before Posting Date"))
|
||||
elif diff > credit_days:
|
||||
|
||||
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()
|
||||
|
||||
|
@ -17,15 +17,19 @@ class CForm(Document):
|
||||
inv = frappe.db.sql("""select c_form_applicable, c_form_no from
|
||||
`tabSales Invoice` where name = %s and docstatus = 1""", d.invoice_no)
|
||||
|
||||
if inv[0][0] != 'Yes':
|
||||
if inv and inv[0][0] != 'Yes':
|
||||
frappe.throw("C-form is not applicable for Invoice: %s" % d.invoice_no)
|
||||
|
||||
elif inv[0][1] and inv[0][1] != self.name:
|
||||
elif inv and inv[0][1] and inv[0][1] != self.name:
|
||||
frappe.throw("""Invoice %s is tagged in another C-form: %s.
|
||||
If you want to change C-form no for this invoice,
|
||||
please remove invoice no from the previous c-form and then try again""" %
|
||||
(d.invoice_no, inv[0][1]))
|
||||
|
||||
elif not inv:
|
||||
frappe.throw("Row %s: Invoice %s is invalid, it might be cancelled / does not exist. \
|
||||
Please enter a valid Invoice" % d.idx, d.invoice_no)
|
||||
|
||||
def on_update(self):
|
||||
""" Update C-Form No on invoices"""
|
||||
self.set_total_invoiced_amount()
|
||||
|
@ -25,7 +25,8 @@ class GLEntry(Document):
|
||||
validate_balance_type(self.account, adv_adj)
|
||||
|
||||
# Update outstanding amt on against voucher
|
||||
if self.against_voucher and update_outstanding == 'Yes':
|
||||
if self.against_voucher_type in ['Journal Voucher', 'Sales Invoice', 'Purchase Invoice'] \
|
||||
and self.against_voucher and update_outstanding == 'Yes':
|
||||
update_outstanding_amt(self.account, self.against_voucher_type,
|
||||
self.against_voucher)
|
||||
|
||||
|
@ -339,6 +339,7 @@
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"fieldname": "letter_head",
|
||||
"fieldtype": "Link",
|
||||
"label": "Letter Head",
|
||||
@ -446,7 +447,7 @@
|
||||
"icon": "icon-file-text",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-08-14 01:37:14.822939",
|
||||
"modified": "2014-09-09 05:35:31.217863",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Voucher",
|
||||
|
@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.utils import cint, cstr, flt, fmt_money, formatdate, getdate
|
||||
from frappe import msgprint, _
|
||||
from frappe import msgprint, _, scrub
|
||||
from erpnext.setup.utils import get_company_currency
|
||||
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
@ -35,18 +35,35 @@ class JournalVoucher(AccountsController):
|
||||
self.create_remarks()
|
||||
self.set_aging_date()
|
||||
self.set_print_format_fields()
|
||||
self.validate_against_sales_order()
|
||||
self.validate_against_purchase_order()
|
||||
|
||||
def on_submit(self):
|
||||
if self.voucher_type in ['Bank Voucher', 'Contra Voucher', 'Journal Entry']:
|
||||
self.check_credit_days()
|
||||
self.make_gl_entries()
|
||||
self.check_credit_limit()
|
||||
self.update_advance_paid()
|
||||
|
||||
def update_advance_paid(self):
|
||||
advance_paid = frappe._dict()
|
||||
for d in self.get("entries"):
|
||||
if d.is_advance:
|
||||
if d.against_sales_order:
|
||||
advance_paid.setdefault("Sales Order", []).append(d.against_sales_order)
|
||||
elif d.against_purchase_order:
|
||||
advance_paid.setdefault("Purchase Order", []).append(d.against_purchase_order)
|
||||
|
||||
for voucher_type, order_list in advance_paid.items():
|
||||
for voucher_no in list(set(order_list)):
|
||||
frappe.get_doc(voucher_type, voucher_no).set_total_advance_paid()
|
||||
|
||||
def on_cancel(self):
|
||||
from erpnext.accounts.utils import remove_against_link_from_jv
|
||||
remove_against_link_from_jv(self.doctype, self.name, "against_jv")
|
||||
|
||||
self.make_gl_entries(1)
|
||||
self.update_advance_paid()
|
||||
|
||||
def validate_cheque_info(self):
|
||||
if self.voucher_type in ['Bank Voucher']:
|
||||
@ -64,7 +81,8 @@ class JournalVoucher(AccountsController):
|
||||
master_type = frappe.db.get_value("Account", d.account, "master_type")
|
||||
if (master_type == 'Customer' and flt(d.credit) > 0) or \
|
||||
(master_type == 'Supplier' and flt(d.debit) > 0):
|
||||
msgprint(_("Please check 'Is Advance' against Account {0} if this is an advance entry.").format(d.account))
|
||||
msgprint(_("Row {0}: Please check 'Is Advance' against Account {1} if this \
|
||||
is an advance entry.").format(d.idx, d.account))
|
||||
|
||||
def validate_against_jv(self):
|
||||
for d in self.get('entries'):
|
||||
@ -90,24 +108,86 @@ class JournalVoucher(AccountsController):
|
||||
.format(d.against_jv, dr_or_cr))
|
||||
|
||||
def validate_against_sales_invoice(self):
|
||||
for d in self.get("entries"):
|
||||
if d.against_invoice:
|
||||
if d.debit > 0:
|
||||
frappe.throw(_("Row {0}: Debit entry can not be linked with a Sales Invoice")
|
||||
.format(d.idx))
|
||||
if frappe.db.get_value("Sales Invoice", d.against_invoice, "debit_to") != d.account:
|
||||
frappe.throw(_("Row {0}: Account does not match with \
|
||||
Sales Invoice Debit To account").format(d.idx, d.account))
|
||||
payment_against_voucher = self.validate_account_in_against_voucher("against_invoice", "Sales Invoice")
|
||||
self.validate_against_invoice_fields("Sales Invoice", payment_against_voucher)
|
||||
|
||||
def validate_against_purchase_invoice(self):
|
||||
payment_against_voucher = self.validate_account_in_against_voucher("against_voucher", "Purchase Invoice")
|
||||
self.validate_against_invoice_fields("Purchase Invoice", payment_against_voucher)
|
||||
|
||||
def validate_against_sales_order(self):
|
||||
payment_against_voucher = self.validate_account_in_against_voucher("against_sales_order", "Sales Order")
|
||||
self.validate_against_order_fields("Sales Order", payment_against_voucher)
|
||||
|
||||
def validate_against_purchase_order(self):
|
||||
payment_against_voucher = self.validate_account_in_against_voucher("against_purchase_order", "Purchase Order")
|
||||
self.validate_against_order_fields("Purchase Order", payment_against_voucher)
|
||||
|
||||
def validate_account_in_against_voucher(self, against_field, doctype):
|
||||
payment_against_voucher = frappe._dict()
|
||||
field_dict = {'Sales Invoice': "Debit To",
|
||||
'Purchase Invoice': "Credit To",
|
||||
'Sales Order': "Customer",
|
||||
'Purchase Order': "Supplier"
|
||||
}
|
||||
|
||||
for d in self.get("entries"):
|
||||
if d.against_voucher:
|
||||
if flt(d.credit) > 0:
|
||||
frappe.throw(_("Row {0}: Credit entry can not be linked with a Purchase Invoice")
|
||||
.format(d.idx))
|
||||
if frappe.db.get_value("Purchase Invoice", d.against_voucher, "credit_to") != d.account:
|
||||
frappe.throw(_("Row {0}: Account does not match with \
|
||||
Purchase Invoice Credit To account").format(d.idx, d.account))
|
||||
if d.get(against_field):
|
||||
dr_or_cr = "credit" if against_field in ["against_invoice", "against_sales_order"] \
|
||||
else "debit"
|
||||
if against_field in ["against_invoice", "against_sales_order"] \
|
||||
and flt(d.debit) > 0:
|
||||
frappe.throw(_("Row {0}: Debit entry can not be linked with a {1}").format(d.idx, doctype))
|
||||
|
||||
if against_field in ["against_voucher", "against_purchase_order"] \
|
||||
and flt(d.credit) > 0:
|
||||
frappe.throw(_("Row {0}: Credit entry can not be linked with a {1}").format(d.idx, doctype))
|
||||
|
||||
voucher_account = frappe.db.get_value(doctype, d.get(against_field), \
|
||||
scrub(field_dict.get(doctype)))
|
||||
|
||||
account_master_name = frappe.db.get_value("Account", d.account, "master_name")
|
||||
|
||||
if against_field in ["against_invoice", "against_voucher"] \
|
||||
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") \
|
||||
.format(d.idx, d.account, doctype, field_dict.get(doctype)))
|
||||
elif d.is_advance == "Yes":
|
||||
payment_against_voucher.setdefault(d.get(against_field), []).append(flt(d.get(dr_or_cr)))
|
||||
|
||||
return payment_against_voucher
|
||||
|
||||
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,
|
||||
["docstatus", "outstanding_amount"])
|
||||
|
||||
if voucher_properties[0] != 1:
|
||||
frappe.throw(_("{0} {1} is not submitted").format(doctype, voucher_no))
|
||||
|
||||
if flt(voucher_properties[1]) < flt(sum(payment_list)):
|
||||
frappe.throw(_("Payment against {0} {1} cannot be greater \
|
||||
than Outstanding Amount {2}").format(doctype, voucher_no, voucher_properties[1]))
|
||||
|
||||
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,
|
||||
["docstatus", "per_billed", "advance_paid", "grand_total"])
|
||||
|
||||
if voucher_properties[0] != 1:
|
||||
frappe.throw(_("{0} {1} is not submitted").format(doctype, voucher_no))
|
||||
|
||||
if flt(voucher_properties[1]) >= 100:
|
||||
frappe.throw(_("{0} {1} is fully billed").format(doctype, voucher_no))
|
||||
|
||||
if flt(voucher_properties[3]) < flt(voucher_properties[2]) + flt(sum(payment_list)):
|
||||
frappe.throw(_("Advance paid against {0} {1} cannot be greater \
|
||||
than Grand Total {2}").format(doctype, voucher_no, voucher_properties[3]))
|
||||
|
||||
def set_against_account(self):
|
||||
accounts_debited, accounts_credited = [], []
|
||||
@ -147,7 +227,13 @@ class JournalVoucher(AccountsController):
|
||||
for d in self.get('entries'):
|
||||
if d.against_invoice and d.credit:
|
||||
currency = frappe.db.get_value("Sales Invoice", d.against_invoice, "currency")
|
||||
r.append(_("{0} {1} against Invoice {2}").format(currency, fmt_money(flt(d.credit)), d.against_invoice))
|
||||
r.append(_("{0} against Sales Invoice {1}").format(fmt_money(flt(d.credit), currency = currency), \
|
||||
d.against_invoice))
|
||||
|
||||
if d.against_sales_order and d.credit:
|
||||
currency = frappe.db.get_value("Sales Order", d.against_sales_order, "currency")
|
||||
r.append(_("{0} against Sales Order {1}").format(fmt_money(flt(d.credit), currency = currency), \
|
||||
d.against_sales_order))
|
||||
|
||||
if d.against_voucher and d.debit:
|
||||
bill_no = frappe.db.sql("""select bill_no, bill_date, currency
|
||||
@ -158,13 +244,17 @@ class JournalVoucher(AccountsController):
|
||||
fmt_money(flt(d.debit)), bill_no[0][0],
|
||||
bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d'))))
|
||||
|
||||
if d.against_purchase_order and d.debit:
|
||||
currency = frappe.db.get_value("Purchase Order", d.against_purchase_order, "currency")
|
||||
r.append(_("{0} against Purchase Order {1}").format(fmt_money(flt(d.credit), currency = currency), \
|
||||
d.against_purchase_order))
|
||||
|
||||
if self.user_remark:
|
||||
r.append(_("Note: {0}").format(self.user_remark))
|
||||
|
||||
if r:
|
||||
self.remark = ("\n").join(r)
|
||||
else:
|
||||
frappe.msgprint(_("User Remarks is mandatory"), raise_exception=frappe.MandatoryError)
|
||||
self.remark = ("\n").join(r) #User Remarks is not mandatory
|
||||
|
||||
|
||||
def set_aging_date(self):
|
||||
if self.is_opening != 'Yes':
|
||||
@ -264,14 +354,18 @@ class JournalVoucher(AccountsController):
|
||||
"against": d.against_account,
|
||||
"debit": flt(d.debit, self.precision("debit", "entries")),
|
||||
"credit": flt(d.credit, self.precision("credit", "entries")),
|
||||
"against_voucher_type": ((d.against_voucher and "Purchase Invoice")
|
||||
or (d.against_invoice and "Sales Invoice")
|
||||
or (d.against_jv and "Journal Voucher")),
|
||||
"against_voucher": d.against_voucher or d.against_invoice or d.against_jv,
|
||||
"against_voucher_type": (("Purchase Invoice" if d.against_voucher else None)
|
||||
or ("Sales Invoice" if d.against_invoice else None)
|
||||
or ("Journal Voucher" if d.against_jv else None)
|
||||
or ("Sales Order" if d.against_sales_order else None)
|
||||
or ("Purchase Order" if d.against_purchase_order else None)),
|
||||
"against_voucher": d.against_voucher or d.against_invoice or d.against_jv
|
||||
or d.against_sales_order or d.against_purchase_order,
|
||||
"remarks": self.remark,
|
||||
"cost_center": d.cost_center
|
||||
})
|
||||
)
|
||||
|
||||
if gl_map:
|
||||
make_gl_entries(gl_map, cancel=cancel, adv_adj=adv_adj)
|
||||
|
||||
|
@ -1,41 +1,88 @@
|
||||
# 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 unittest
|
||||
import frappe
|
||||
import unittest, frappe
|
||||
from frappe.utils import flt
|
||||
|
||||
class TestJournalVoucher(unittest.TestCase):
|
||||
def test_journal_voucher_with_against_jv(self):
|
||||
self.clear_account_balance()
|
||||
|
||||
jv_invoice = frappe.copy_doc(test_records[2])
|
||||
jv_invoice.insert()
|
||||
jv_invoice.submit()
|
||||
base_jv = frappe.copy_doc(test_records[0])
|
||||
self.jv_against_voucher_testcase(base_jv, jv_invoice)
|
||||
|
||||
self.assertTrue(frappe.db.sql("""select name from `tabJournal Voucher Detail`
|
||||
where account = %s and docstatus = 1 and parent = %s""",
|
||||
("_Test Customer - _TC", jv_invoice.name)))
|
||||
def test_jv_against_sales_order(self):
|
||||
from erpnext.selling.doctype.sales_order.test_sales_order \
|
||||
import test_records as so_test_records
|
||||
|
||||
sales_order = frappe.copy_doc(so_test_records[0])
|
||||
base_jv = frappe.copy_doc(test_records[0])
|
||||
self.jv_against_voucher_testcase(base_jv, sales_order)
|
||||
|
||||
def test_jv_against_purchase_order(self):
|
||||
from erpnext.buying.doctype.purchase_order.test_purchase_order \
|
||||
import test_records as po_test_records
|
||||
|
||||
purchase_order = frappe.copy_doc(po_test_records[0])
|
||||
base_jv = frappe.copy_doc(test_records[1])
|
||||
self.jv_against_voucher_testcase(base_jv, purchase_order)
|
||||
|
||||
def jv_against_voucher_testcase(self, base_jv, test_voucher):
|
||||
dr_or_cr = "credit" if test_voucher.doctype in ["Sales Order", "Journal Voucher"] else "debit"
|
||||
field_dict = {'Journal Voucher': "against_jv",
|
||||
'Sales Order': "against_sales_order",
|
||||
'Purchase Order': "against_purchase_order"
|
||||
}
|
||||
|
||||
self.clear_account_balance()
|
||||
test_voucher.insert()
|
||||
test_voucher.submit()
|
||||
|
||||
if test_voucher.doctype == "Journal Voucher":
|
||||
self.assertTrue(frappe.db.sql("""select name from `tabJournal Voucher Detail`
|
||||
where account = %s and docstatus = 1 and parent = %s""",
|
||||
("_Test Customer - _TC", test_voucher.name)))
|
||||
|
||||
self.assertTrue(not frappe.db.sql("""select name from `tabJournal Voucher Detail`
|
||||
where against_jv=%s""", jv_invoice.name))
|
||||
where %s=%s""" % (field_dict.get(test_voucher.doctype), '%s'), (test_voucher.name)))
|
||||
|
||||
jv_payment = frappe.copy_doc(test_records[0])
|
||||
jv_payment.get("entries")[0].against_jv = jv_invoice.name
|
||||
jv_payment.insert()
|
||||
jv_payment.submit()
|
||||
base_jv.get("entries")[0].is_advance = "Yes" if (test_voucher.doctype in ["Sales Order", "Purchase Order"]) else "No"
|
||||
base_jv.get("entries")[0].set(field_dict.get(test_voucher.doctype), test_voucher.name)
|
||||
base_jv.insert()
|
||||
base_jv.submit()
|
||||
|
||||
submitted_voucher = frappe.get_doc(test_voucher.doctype, test_voucher.name)
|
||||
|
||||
self.assertTrue(frappe.db.sql("""select name from `tabJournal Voucher Detail`
|
||||
where against_jv=%s""", jv_invoice.name))
|
||||
where %s=%s""" % (field_dict.get(test_voucher.doctype), '%s'), (submitted_voucher.name)))
|
||||
|
||||
self.assertTrue(frappe.db.sql("""select name from `tabJournal Voucher Detail`
|
||||
where against_jv=%s and credit=400""", jv_invoice.name))
|
||||
where %s=%s and %s=400""" % (field_dict.get(submitted_voucher.doctype), '%s', dr_or_cr), (submitted_voucher.name)))
|
||||
|
||||
# cancel jv_invoice
|
||||
jv_invoice.cancel()
|
||||
if base_jv.get("entries")[0].is_advance == "Yes":
|
||||
self.advance_paid_testcase(base_jv, submitted_voucher, dr_or_cr)
|
||||
self.cancel_against_voucher_testcase(submitted_voucher)
|
||||
|
||||
self.assertTrue(not frappe.db.sql("""select name from `tabJournal Voucher Detail`
|
||||
where against_jv=%s""", jv_invoice.name))
|
||||
def advance_paid_testcase(self, base_jv, test_voucher, dr_or_cr):
|
||||
#Test advance paid field
|
||||
advance_paid = frappe.db.sql("""select advance_paid from `tab%s`
|
||||
where name=%s""" % (test_voucher.doctype, '%s'), (test_voucher.name))
|
||||
payment_against_order = base_jv.get("entries")[0].get(dr_or_cr)
|
||||
|
||||
self.assertTrue(flt(advance_paid[0][0]) == flt(payment_against_order))
|
||||
|
||||
def cancel_against_voucher_testcase(self, test_voucher):
|
||||
if test_voucher.doctype == "Journal Voucher":
|
||||
# if test_voucher is a Journal Voucher, test cancellation of test_voucher
|
||||
test_voucher.cancel()
|
||||
self.assertTrue(not frappe.db.sql("""select name from `tabJournal Voucher Detail`
|
||||
where against_jv=%s""", test_voucher.name))
|
||||
|
||||
elif test_voucher.doctype in ["Sales Order", "Purchase Order"]:
|
||||
# if test_voucher is a Sales Order/Purchase Order, test error on cancellation of test_voucher
|
||||
submitted_voucher = frappe.get_doc(test_voucher.doctype, test_voucher.name)
|
||||
self.assertRaises(frappe.LinkExistsError, submitted_voucher.cancel)
|
||||
|
||||
def test_jv_against_stock_account(self):
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||
|
@ -117,11 +117,6 @@
|
||||
"print_hide": 0,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break3",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "against_jv",
|
||||
"fieldtype": "Link",
|
||||
@ -135,6 +130,25 @@
|
||||
"print_hide": 0,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break3",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "against_sales_order",
|
||||
"fieldtype": "Link",
|
||||
"label": "Against Sales Order",
|
||||
"options": "Sales Order",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "against_purchase_order",
|
||||
"fieldtype": "Link",
|
||||
"label": "Against Purchase Order",
|
||||
"options": "Purchase Order",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "is_advance",
|
||||
"fieldtype": "Select",
|
||||
@ -160,7 +174,7 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-07-25 03:16:51.149899",
|
||||
"modified": "2014-08-20 12:19:55.049973",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Journal Voucher Detail",
|
||||
|
@ -36,8 +36,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>';
|
||||
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);
|
||||
},
|
||||
|
||||
|
0
erpnext/accounts/doctype/payment_tool/__init__.py
Normal file
0
erpnext/accounts/doctype/payment_tool/__init__.py
Normal file
217
erpnext/accounts/doctype/payment_tool/payment_tool.js
Normal file
217
erpnext/accounts/doctype/payment_tool/payment_tool.js
Normal file
@ -0,0 +1,217 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.provide("erpnext.payment_tool");
|
||||
|
||||
// Help content
|
||||
frappe.ui.form.on("Payment Tool", "onload", function(frm) {
|
||||
frm.set_value("make_jv_help", '<i class="icon-hand-right"></i> '
|
||||
+ __("Note: If payment is not made against any reference, make Journal Voucher manually."));
|
||||
|
||||
frm.set_query("payment_account", function() {
|
||||
return {
|
||||
filters: [
|
||||
['Account', 'account_type', 'in', 'Bank, Cash'],
|
||||
['Account', 'group_or_ledger', '=', 'Ledger'],
|
||||
['Account', 'company', '=', frm.doc.company]
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query("against_voucher_type", "payment_tool_details", function() {
|
||||
return {
|
||||
filters: {"name": ["in", ["Sales Invoice", "Purchase Invoice", "Journal Voucher", "Sales Order", "Purchase Order"]]}
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Payment Tool", "refresh", function(frm) {
|
||||
frappe.ui.form.trigger("Payment Tool", "party_type");
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Payment Tool", "party_type", function(frm) {
|
||||
frm.toggle_reqd("customer", frm.doc.party_type == "Customer");
|
||||
frm.toggle_reqd("supplier", frm.doc.party_type == "Supplier");
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Payment Tool", "company", function(frm) {
|
||||
erpnext.payment_tool.check_mandatory_to_set_button(frm);
|
||||
});
|
||||
|
||||
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);
|
||||
erpnext.payment_tool.check_mandatory_to_set_button(frm);
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Payment Tool", "supplier", function(frm) {
|
||||
erpnext.payment_tool.set_party_account(frm);
|
||||
erpnext.payment_tool.check_mandatory_to_set_button(frm);
|
||||
});
|
||||
|
||||
erpnext.payment_tool.check_mandatory_to_set_button = function(frm) {
|
||||
if (frm.doc.company && frm.doc.party_type && frm.doc.received_or_paid && (frm.doc.customer || frm.doc.supplier)) {
|
||||
frm.fields_dict.get_outstanding_vouchers.$input.addClass("btn-primary");
|
||||
}
|
||||
}
|
||||
|
||||
//Set Button color
|
||||
erpnext.payment_tool.set_party_account = function(frm) {
|
||||
if(frm.doc.party_type == "Customer") {
|
||||
var party_name = frm.doc.customer;
|
||||
} else {
|
||||
var party_name = frm.doc.supplier;
|
||||
}
|
||||
return frappe.call({
|
||||
method: 'erpnext.accounts.doctype.payment_tool.payment_tool.get_party_account',
|
||||
args: {
|
||||
party_type: frm.doc.party_type,
|
||||
party_name: party_name
|
||||
},
|
||||
callback: function(r, rt) {
|
||||
if(!r.exc) {
|
||||
frm.set_value("party_account", r.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Get outstanding vouchers
|
||||
frappe.ui.form.on("Payment Tool", "get_outstanding_vouchers", function(frm) {
|
||||
erpnext.payment_tool.check_mandatory_to_fetch(frm.doc);
|
||||
|
||||
frm.set_value("payment_tool_details", []);
|
||||
|
||||
return frappe.call({
|
||||
method: 'erpnext.accounts.doctype.payment_tool.payment_tool.get_outstanding_vouchers',
|
||||
args: {
|
||||
args: {
|
||||
"company": frm.doc.company,
|
||||
"party_type": frm.doc.party_type,
|
||||
"received_or_paid": frm.doc.received_or_paid,
|
||||
"party_name": frm.doc.party_type == "Customer" ? frm.doc.customer : frm.doc.supplier,
|
||||
"party_account": frm.doc.party_account
|
||||
}
|
||||
},
|
||||
callback: function(r, rt) {
|
||||
if(r.message) {
|
||||
frm.fields_dict.get_outstanding_vouchers.$input.removeClass("btn-primary");
|
||||
frm.fields_dict.make_journal_voucher.$input.addClass("btn-primary");
|
||||
|
||||
frappe.model.clear_table(frm.doc, "payment_tool_details");
|
||||
$.each(r.message, function(i, d) {
|
||||
var invoice_detail = frappe.model.add_child(frm.doc, "Payment Tool Detail", "payment_tool_details");
|
||||
invoice_detail.against_voucher_type = d.voucher_type;
|
||||
invoice_detail.against_voucher_no = d.voucher_no;
|
||||
invoice_detail.total_amount = d.invoice_amount;
|
||||
invoice_detail.outstanding_amount = d.outstanding_amount;
|
||||
});
|
||||
}
|
||||
refresh_field("payment_tool_details");
|
||||
erpnext.payment_tool.set_total_payment_amount(frm);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// validate against_voucher_type
|
||||
frappe.ui.form.on("Payment Tool Detail", "against_voucher_type", function(frm) {
|
||||
erpnext.payment_tool.validate_against_voucher(frm);
|
||||
});
|
||||
|
||||
erpnext.payment_tool.validate_against_voucher = function(frm) {
|
||||
$.each(frm.doc.payment_tool_details || [], function(i, row) {
|
||||
if(frm.doc.party_type=="Customer"
|
||||
&& !in_list(["Sales Order", "Sales Invoice", "Journal Voucher"], row.against_voucher_type)) {
|
||||
frappe.model.set_value(row.doctype, row.name, "against_voucher_type", "");
|
||||
frappe.throw(__("Against Voucher Type must be one of Sales Order, Sales Invoice or Journal Voucher"))
|
||||
}
|
||||
|
||||
if(frm.doc.party_type=="Supplier"
|
||||
&& !in_list(["Purchase Order", "Purchase Invoice", "Journal Voucher"], row.against_voucher_type)) {
|
||||
frappe.model.set_value(row.doctype, row.name, "against_voucher_type", "");
|
||||
frappe.throw(__("Against Voucher Type must be one of Purchase Order, Purchase Invoice or Journal Voucher"))
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
// validate against_voucher_type
|
||||
frappe.ui.form.on("Payment Tool Detail", "against_voucher_no", function(frm, cdt, cdn) {
|
||||
var row = locals[cdt][cdn];
|
||||
frappe.call({
|
||||
method: 'erpnext.accounts.doctype.payment_tool.payment_tool.get_against_voucher_amount',
|
||||
args: {
|
||||
"against_voucher_type": row.against_voucher_type,
|
||||
"against_voucher_no": row.against_voucher_no
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
$.each(r.message, function(k, v) {
|
||||
frappe.model.set_value(cdt, cdn, k, v);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Set total payment amount
|
||||
frappe.ui.form.on("Payment Tool Detail", "payment_amount", function(frm) {
|
||||
erpnext.payment_tool.set_total_payment_amount(frm);
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Payment Tool Detail", "payment_tool_details_remove", function(frm) {
|
||||
erpnext.payment_tool.set_total_payment_amount(frm);
|
||||
});
|
||||
|
||||
erpnext.payment_tool.set_total_payment_amount = function(frm) {
|
||||
var total_amount = 0.00;
|
||||
$.each(frm.doc.payment_tool_details || [], function(i, row) {
|
||||
if (row.payment_amount && (row.payment_amount <= row.outstanding_amount)) {
|
||||
total_amount = total_amount + row.payment_amount;
|
||||
} else {
|
||||
if(row.payment_amount < 0)
|
||||
msgprint(__("Row {0}: Payment amount can not be negative", [row.idx]));
|
||||
else if(row.payment_amount >= row.outstanding_amount)
|
||||
msgprint(__("Row {0}: Payment Amount cannot be greater than Outstanding Amount", [__(row.idx)]));
|
||||
|
||||
frappe.model.set_value(row.doctype, row.name, "payment_amount", 0.0);
|
||||
}
|
||||
});
|
||||
frm.set_value("total_payment_amount", total_amount);
|
||||
}
|
||||
|
||||
|
||||
// Make Journal voucher
|
||||
frappe.ui.form.on("Payment Tool", "make_journal_voucher", function(frm) {
|
||||
erpnext.payment_tool.check_mandatory_to_fetch(frm.doc);
|
||||
|
||||
return frappe.call({
|
||||
method: 'make_journal_voucher',
|
||||
doc: frm.doc,
|
||||
callback: function(r) {
|
||||
frm.fields_dict.make_journal_voucher.$input.addClass("btn-primary");
|
||||
var doclist = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
erpnext.payment_tool.check_mandatory_to_fetch = function(doc) {
|
||||
var check_fields = [
|
||||
['Company', doc.company],
|
||||
['Party Type', doc.party_type],
|
||||
['Received Or Paid', doc.received_or_paid],
|
||||
['Customer / Supplier', doc.party_type == "Customer" ? doc.customer : doc.supplier]
|
||||
];
|
||||
|
||||
$.each(check_fields, function(i, v) {
|
||||
if(!v[1]) frappe.throw(__("Please select {0} first", [v[0]]));
|
||||
});
|
||||
}
|
381
erpnext/accounts/doctype/payment_tool/payment_tool.json
Normal file
381
erpnext/accounts/doctype/payment_tool/payment_tool.json
Normal file
@ -0,0 +1,381 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"creation": "2014-07-23 15:12:27.746665",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "sec_break1",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Party Details",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"default": "Customer",
|
||||
"fieldname": "party_type",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Party Type",
|
||||
"no_copy": 0,
|
||||
"options": "Customer\nSupplier",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"depends_on": "eval:(doc.party_type == 'Customer')",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Customer",
|
||||
"no_copy": 0,
|
||||
"options": "Customer",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"depends_on": "eval:(doc.party_type == 'Supplier')",
|
||||
"fieldname": "supplier",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Supplier",
|
||||
"no_copy": 0,
|
||||
"options": "Supplier",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "party_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"label": "Party Account",
|
||||
"no_copy": 1,
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "received_or_paid",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Received Or Paid",
|
||||
"no_copy": 0,
|
||||
"options": "Received\nPaid",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "get_outstanding_vouchers",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Get Outstanding Vouchers",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Column Break 1",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "payment_mode",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Payment Mode",
|
||||
"no_copy": 0,
|
||||
"options": "Mode of Payment",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "payment_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Payment Account",
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "reference_no",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Reference No",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "reference_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Reference Date",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"depends_on": "eval:(doc.company && doc.party_type && doc.received_or_paid && (doc.customer || doc.supplier))",
|
||||
"fieldname": "sec_break3",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Against Voucher",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "payment_tool_details",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Payment Tool Details",
|
||||
"no_copy": 0,
|
||||
"options": "Payment Tool Detail",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:(doc.company && doc.party_type && doc.received_or_paid && (doc.customer || doc.supplier))",
|
||||
"fieldname": "section_break_19",
|
||||
"fieldtype": "Section Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "total_payment_amount",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Total Payment Amount",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "make_journal_voucher",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Make Journal Voucher",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "data_22",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:(doc.company && doc.party_type && doc.received_or_paid && (doc.customer || doc.supplier))",
|
||||
"fieldname": "section_break_21",
|
||||
"fieldtype": "Section Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "make_jv_help",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 1,
|
||||
"icon": "icon-magic",
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"modified": "2014-09-12 04:43:05.963218",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Tool",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "Accounts User",
|
||||
"set_user_permissions": 0,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
118
erpnext/accounts/doctype/payment_tool/payment_tool.py
Normal file
118
erpnext/accounts/doctype/payment_tool/payment_tool.py
Normal file
@ -0,0 +1,118 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _, scrub
|
||||
from frappe.utils import flt
|
||||
from frappe.model.document import Document
|
||||
import json
|
||||
|
||||
class PaymentTool(Document):
|
||||
def make_journal_voucher(self):
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
total_payment_amount = 0.00
|
||||
invoice_voucher_type = {
|
||||
'Sales Invoice': 'against_invoice',
|
||||
'Purchase Invoice': 'against_voucher',
|
||||
'Journal Voucher': 'against_jv',
|
||||
'Sales Order': 'against_sales_order',
|
||||
'Purchase Order': 'against_purchase_order',
|
||||
}
|
||||
|
||||
jv = frappe.new_doc('Journal Voucher')
|
||||
jv.voucher_type = 'Journal Entry'
|
||||
jv.company = self.company
|
||||
jv.cheque_no = self.reference_no
|
||||
jv.cheque_date = self.reference_date
|
||||
|
||||
if not self.total_payment_amount:
|
||||
frappe.throw(_("Please enter Payment Amount in atleast one row"))
|
||||
|
||||
for v in self.get("payment_tool_details"):
|
||||
if not frappe.db.get_value(v.against_voucher_type, {"name": v.against_voucher_no}):
|
||||
frappe.throw(_("Row {0}: {1} is not a valid {2}").format(v.idx, v.against_voucher_no,
|
||||
v.against_voucher_type))
|
||||
|
||||
if v.payment_amount:
|
||||
d1 = jv.append("entries")
|
||||
d1.account = self.party_account
|
||||
d1.balance = get_balance_on(self.party_account)
|
||||
d1.set("debit" if self.received_or_paid=="Paid" else "credit", flt(v.payment_amount))
|
||||
d1.set(invoice_voucher_type.get(v.against_voucher_type), v.against_voucher_no)
|
||||
d1.set('is_advance', 'Yes' if v.against_voucher_type in ['Sales Order', 'Purchase Order'] else 'No')
|
||||
total_payment_amount = flt(total_payment_amount) + flt(d1.debit) - flt(d1.credit)
|
||||
|
||||
d2 = jv.append("entries")
|
||||
d2.account = self.payment_account
|
||||
d2.set('debit' if total_payment_amount < 0 else 'credit', abs(total_payment_amount))
|
||||
if self.payment_account:
|
||||
d2.balance = get_balance_on(self.payment_account)
|
||||
|
||||
return jv.as_dict()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_party_account(party_type, party_name):
|
||||
return frappe.db.get_value("Account", {"master_type": party_type, "master_name": party_name})
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_outstanding_vouchers(args):
|
||||
from erpnext.accounts.utils import get_outstanding_invoices
|
||||
|
||||
if not frappe.has_permission("Payment Tool"):
|
||||
frappe.throw(_("No permission to use Payment Tool"), frappe.PermissionError)
|
||||
|
||||
args = json.loads(args)
|
||||
|
||||
if args.get("party_type") == "Customer" and args.get("received_or_paid") == "Received":
|
||||
amount_query = "ifnull(debit, 0) - ifnull(credit, 0)"
|
||||
elif args.get("party_type") == "Supplier" and args.get("received_or_paid") == "Paid":
|
||||
amount_query = "ifnull(credit, 0) - ifnull(debit, 0)"
|
||||
else:
|
||||
frappe.throw(_("Please enter the Against Vouchers manually"))
|
||||
|
||||
# Get all outstanding sales /purchase invoices
|
||||
outstanding_invoices = get_outstanding_invoices(amount_query, args.get("party_account"))
|
||||
|
||||
# Get all SO / PO which are not fully billed or aginst which full advance not paid
|
||||
orders_to_be_billed = get_orders_to_be_billed(args.get("party_type"), args.get("party_name"))
|
||||
return outstanding_invoices + orders_to_be_billed
|
||||
|
||||
def get_orders_to_be_billed(party_type, party_name):
|
||||
voucher_type = 'Sales Order' if party_type == "Customer" else 'Purchase Order'
|
||||
orders = frappe.db.sql("""
|
||||
select
|
||||
name as voucher_no,
|
||||
ifnull(grand_total, 0) as invoice_amount,
|
||||
(ifnull(grand_total, 0) - ifnull(advance_paid, 0)) as outstanding_amount,
|
||||
transaction_date as posting_date
|
||||
from
|
||||
`tab%s`
|
||||
where
|
||||
%s = %s
|
||||
and docstatus = 1
|
||||
and ifnull(grand_total, 0) > ifnull(advance_paid, 0)
|
||||
and ifnull(per_billed, 0) < 100.0
|
||||
""" % (voucher_type, 'customer' if party_type == "Customer" else 'supplier', '%s'),
|
||||
party_name, as_dict = True)
|
||||
|
||||
order_list = []
|
||||
for d in orders:
|
||||
d["voucher_type"] = voucher_type
|
||||
order_list.append(d)
|
||||
|
||||
return order_list
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_against_voucher_amount(against_voucher_type, against_voucher_no):
|
||||
if against_voucher_type in ["Sales Order", "Purchase Order"]:
|
||||
select_cond = "grand_total as total_amount, ifnull(grand_total, 0) - ifnull(advance_paid, 0) as outstanding_amount"
|
||||
elif against_voucher_type in ["Sales Invoice", "Purchase Invoice"]:
|
||||
select_cond = "grand_total as total_amount, outstanding_amount"
|
||||
elif against_voucher_type == "Journal Voucher":
|
||||
select_cond = "total_debit as total_amount"
|
||||
|
||||
details = frappe.db.sql("""select {0} from `tab{1}` where name = %s"""
|
||||
.format(select_cond, against_voucher_type), against_voucher_no, as_dict=1)
|
||||
|
||||
return details[0] if details else {}
|
193
erpnext/accounts/doctype/payment_tool/test_payment_tool.py
Normal file
193
erpnext/accounts/doctype/payment_tool/test_payment_tool.py
Normal file
@ -0,0 +1,193 @@
|
||||
# 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 unittest, frappe, json
|
||||
from frappe.utils import flt
|
||||
|
||||
test_dependencies = ["Item"]
|
||||
|
||||
class TestPaymentTool(unittest.TestCase):
|
||||
def test_make_journal_voucher(self):
|
||||
from erpnext.accounts.doctype.journal_voucher.test_journal_voucher \
|
||||
import test_records as jv_test_records
|
||||
from erpnext.selling.doctype.sales_order.test_sales_order \
|
||||
import test_records as so_test_records
|
||||
from erpnext.buying.doctype.purchase_order.test_purchase_order \
|
||||
import test_records as po_test_records
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice \
|
||||
import test_records as si_test_records
|
||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice \
|
||||
import test_records as pi_test_records
|
||||
|
||||
self.clear_table_entries()
|
||||
|
||||
base_customer_jv = self.create_against_jv(jv_test_records[2], { "account": "_Test Customer 3 - _TC"})
|
||||
base_supplier_jv = self.create_against_jv(jv_test_records[1], { "account": "_Test Supplier 1 - _TC"})
|
||||
|
||||
|
||||
#Create SO with partial outstanding
|
||||
so1 = self.create_voucher(so_test_records[0], {
|
||||
"customer": "_Test Customer 3"
|
||||
})
|
||||
|
||||
jv_against_so1 = self.create_against_jv(jv_test_records[0], {
|
||||
"account": "_Test Customer 3 - _TC",
|
||||
"against_sales_order": so1.name
|
||||
})
|
||||
|
||||
|
||||
#Create SO with no outstanding
|
||||
so2 = self.create_voucher(so_test_records[0], {
|
||||
"customer": "_Test Customer 3"
|
||||
})
|
||||
|
||||
jv_against_so2 = self.create_against_jv(jv_test_records[0], {
|
||||
"account": "_Test Customer 3 - _TC",
|
||||
"against_sales_order": so2.name,
|
||||
"credit": 1000
|
||||
})
|
||||
po = self.create_voucher(po_test_records[1], {
|
||||
"supplier": "_Test Supplier 1"
|
||||
})
|
||||
|
||||
#Create SI with partial outstanding
|
||||
si1 = self.create_voucher(si_test_records[0], {
|
||||
"customer": "_Test Customer 3",
|
||||
"debit_to": "_Test Customer 3 - _TC"
|
||||
})
|
||||
|
||||
jv_against_si1 = self.create_against_jv(jv_test_records[0], {
|
||||
"account": "_Test Customer 3 - _TC",
|
||||
"against_invoice": si1.name
|
||||
})
|
||||
#Create SI with no outstanding
|
||||
si2 = self.create_voucher(si_test_records[0], {
|
||||
"customer": "_Test Customer 3",
|
||||
"debit_to": "_Test Customer 3 - _TC"
|
||||
})
|
||||
|
||||
jv_against_si2 = self.create_against_jv(jv_test_records[0], {
|
||||
"account": "_Test Customer 3 - _TC",
|
||||
"against_invoice": si2.name,
|
||||
"credit": 561.80
|
||||
})
|
||||
|
||||
pi = self.create_voucher(pi_test_records[0], {
|
||||
"supplier": "_Test Supplier 1",
|
||||
"credit_to": "_Test Supplier 1 - _TC"
|
||||
})
|
||||
|
||||
#Create a dict containing properties and expected values
|
||||
expected_outstanding = {
|
||||
"Journal Voucher" : [base_customer_jv.name, 400.00],
|
||||
"Sales Invoice" : [si1.name, 161.80],
|
||||
"Purchase Invoice" : [pi.name, 1512.30],
|
||||
"Sales Order" : [so1.name, 600.00],
|
||||
"Purchase Order" : [po.name, 5000.00]
|
||||
}
|
||||
|
||||
args = {
|
||||
"company": "_Test Company",
|
||||
"party_type": "Customer",
|
||||
"received_or_paid": "Received",
|
||||
"customer": "_Test Customer",
|
||||
"party_account": "_Test Customer 3 - _TC",
|
||||
"payment_mode": "Cheque",
|
||||
"payment_account": "_Test Account Bank Account - _TC",
|
||||
"reference_no": "123456",
|
||||
"reference_date": "2013-02-14"
|
||||
}
|
||||
|
||||
self.make_voucher_for_party(args, expected_outstanding)
|
||||
|
||||
args.update({
|
||||
"party_type": "Supplier",
|
||||
"received_or_paid": "Paid",
|
||||
"supplier": "_Test Supplier 1",
|
||||
"party_account": "_Test Supplier 1 - _TC"
|
||||
})
|
||||
expected_outstanding["Journal Voucher"] = [base_supplier_jv.name, 400.00]
|
||||
self.make_voucher_for_party(args, expected_outstanding)
|
||||
|
||||
def create_voucher(self, test_record, args):
|
||||
doc = frappe.copy_doc(test_record)
|
||||
doc.update(args)
|
||||
doc.insert()
|
||||
doc.submit()
|
||||
return doc
|
||||
|
||||
def create_against_jv(self, test_record, args):
|
||||
jv = frappe.copy_doc(test_record)
|
||||
jv.get("entries")[0].update(args)
|
||||
if args.get("debit"):
|
||||
jv.get("entries")[1].credit = args["debit"]
|
||||
elif args.get("credit"):
|
||||
jv.get("entries")[1].debit = args["credit"]
|
||||
|
||||
jv.insert()
|
||||
jv.submit()
|
||||
return jv
|
||||
|
||||
def make_voucher_for_party(self, args, expected_outstanding):
|
||||
#Make Journal Voucher for Party
|
||||
payment_tool_doc = frappe.new_doc("Payment Tool")
|
||||
|
||||
for k, v in args.items():
|
||||
payment_tool_doc.set(k, v)
|
||||
|
||||
self.check_outstanding_vouchers(payment_tool_doc, args, expected_outstanding)
|
||||
|
||||
|
||||
def check_outstanding_vouchers(self, doc, args, expected_outstanding):
|
||||
from erpnext.accounts.doctype.payment_tool.payment_tool import get_outstanding_vouchers
|
||||
|
||||
outstanding_entries = get_outstanding_vouchers(json.dumps(args))
|
||||
|
||||
for d in outstanding_entries:
|
||||
self.assertEquals(flt(d.get("outstanding_amount"), 2), expected_outstanding.get(d.get("voucher_type"))[1])
|
||||
|
||||
self.check_jv_entries(doc, outstanding_entries, expected_outstanding)
|
||||
|
||||
def check_jv_entries(self, paytool, outstanding_entries, expected_outstanding):
|
||||
for e in outstanding_entries:
|
||||
d1 = paytool.append("payment_tool_details")
|
||||
d1.against_voucher_type = e.get("voucher_type")
|
||||
d1.against_voucher_no = e.get("voucher_no")
|
||||
d1.total_amount = e.get("invoice_amount")
|
||||
d1.outstanding_amount = e.get("outstanding_amount")
|
||||
d1.payment_amount = 100.00
|
||||
paytool.total_payment_amount = 300
|
||||
|
||||
new_jv = paytool.make_journal_voucher()
|
||||
|
||||
#Create a list of expected values as [party account, payment against, against_jv, against_invoice,
|
||||
#against_voucher, against_sales_order, against_purchase_order]
|
||||
expected_values = [
|
||||
[paytool.party_account, 100.00, expected_outstanding.get("Journal Voucher")[0], None, None, None, None],
|
||||
[paytool.party_account, 100.00, None, expected_outstanding.get("Sales Invoice")[0], None, None, None],
|
||||
[paytool.party_account, 100.00, None, None, expected_outstanding.get("Purchase Invoice")[0], None, None],
|
||||
[paytool.party_account, 100.00, None, None, None, expected_outstanding.get("Sales Order")[0], None],
|
||||
[paytool.party_account, 100.00, None, None, None, None, expected_outstanding.get("Purchase Order")[0]]
|
||||
]
|
||||
|
||||
for jv_entry in new_jv.get("entries"):
|
||||
if paytool.party_account == jv_entry.get("account"):
|
||||
row = [
|
||||
jv_entry.get("account"),
|
||||
jv_entry.get("debit" if paytool.party_type=="Supplier" else "credit"),
|
||||
jv_entry.get("against_jv"),
|
||||
jv_entry.get("against_invoice"),
|
||||
jv_entry.get("against_voucher"),
|
||||
jv_entry.get("against_sales_order"),
|
||||
jv_entry.get("against_purchase_order"),
|
||||
]
|
||||
self.assertTrue(row in expected_values)
|
||||
|
||||
self.assertEquals(new_jv.get("cheque_no"), paytool.reference_no)
|
||||
self.assertEquals(new_jv.get("cheque_date"), paytool.reference_date)
|
||||
|
||||
def clear_table_entries(self):
|
||||
frappe.db.sql("""delete from `tabGL Entry` where (account = "_Test Customer 3 - _TC" or account = "_Test Supplier 1 - _TC")""")
|
||||
frappe.db.sql("""delete from `tabSales Order` where customer_name = "_Test Customer 3" """)
|
||||
frappe.db.sql("""delete from `tabPurchase Order` where supplier_name = "_Test Supplier 1" """)
|
@ -0,0 +1,130 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"creation": "2014-08-11 14:27:54.463897",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "against_voucher_type",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Against Voucher Type",
|
||||
"no_copy": 0,
|
||||
"options": "DocType",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_width": "",
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"width": ""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "against_voucher_no",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Against Voucher No",
|
||||
"no_copy": 0,
|
||||
"options": "against_voucher_type",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "total_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Total Amount",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "outstanding_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Outstanding Amount",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "payment_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Payment Amount",
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2014-09-11 08:55:34.384017",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Tool Detail",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class PaymentToolDetail(Document):
|
||||
pass
|
@ -171,6 +171,7 @@
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"fieldname": "letter_head",
|
||||
"fieldtype": "Link",
|
||||
"label": "Letter Head",
|
||||
@ -192,6 +193,7 @@
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"fieldname": "select_print_heading",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 0,
|
||||
@ -205,7 +207,7 @@
|
||||
],
|
||||
"icon": "icon-cog",
|
||||
"idx": 1,
|
||||
"modified": "2014-06-23 16:40:59.510132",
|
||||
"modified": "2014-09-09 05:35:31.969193",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Setting",
|
||||
|
10
erpnext/accounts/doctype/pos_setting/test_pos_setting.py
Normal file
10
erpnext/accounts/doctype/pos_setting/test_pos_setting.py
Normal file
@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and Contributors
|
||||
# See license.txt
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
test_records = frappe.get_test_records('POS Setting')
|
||||
|
||||
class TestPOSSetting(unittest.TestCase):
|
||||
pass
|
1
erpnext/accounts/doctype/pos_setting/test_records.json
Normal file
1
erpnext/accounts/doctype/pos_setting/test_records.json
Normal file
@ -0,0 +1 @@
|
||||
[]
|
File diff suppressed because it is too large
Load Diff
@ -399,7 +399,7 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-09-08 08:06:30.027289",
|
||||
"modified": "2014-09-09 05:35:35.712453",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Item",
|
||||
|
@ -1,5 +1,4 @@
|
||||
{
|
||||
"allow_attach": 1,
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-05-24 19:29:05",
|
||||
@ -1193,7 +1192,7 @@
|
||||
"icon": "icon-file-text",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-08-28 11:21:00.726344",
|
||||
"modified": "2014-09-09 05:35:34.121045",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
@ -71,7 +71,9 @@ class SalesInvoice(SellingController):
|
||||
self.is_opening = 'No'
|
||||
|
||||
self.set_aging_date()
|
||||
|
||||
frappe.get_doc("Account", self.debit_to).validate_due_date(self.posting_date, self.due_date)
|
||||
|
||||
self.set_against_income_account()
|
||||
self.validate_c_form()
|
||||
self.validate_time_logs_are_submitted()
|
||||
@ -101,7 +103,6 @@ class SalesInvoice(SellingController):
|
||||
if not cint(self.is_pos) == 1:
|
||||
self.update_against_document_in_jv()
|
||||
|
||||
self.update_c_form()
|
||||
self.update_time_log_batch(self.name)
|
||||
convert_to_recurring(self, "RECINV.#####", self.posting_date)
|
||||
|
||||
@ -120,6 +121,7 @@ class SalesInvoice(SellingController):
|
||||
self.update_status_updater_args()
|
||||
self.update_prevdoc_status()
|
||||
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
||||
self.validate_c_form_on_cancel()
|
||||
|
||||
self.make_gl_entries_on_cancel()
|
||||
|
||||
@ -147,6 +149,10 @@ class SalesInvoice(SellingController):
|
||||
validate_recurring_document(self)
|
||||
convert_to_recurring(self, "RECINV.#####", self.posting_date)
|
||||
|
||||
def before_recurring(self):
|
||||
self.aging_date = None
|
||||
self.due_date = None
|
||||
|
||||
def get_portal_page(self):
|
||||
return "invoice" if self.docstatus==1 else None
|
||||
|
||||
@ -376,6 +382,12 @@ class SalesInvoice(SellingController):
|
||||
|
||||
frappe.db.set(self, 'c_form_no', '')
|
||||
|
||||
def validate_c_form_on_cancel(self):
|
||||
""" Display message if C-Form no exists on cancellation of Sales Invoice"""
|
||||
if self.c_form_applicable == 'Yes' and self.c_form_no:
|
||||
msgprint(_("Please remove this Invoice {0} from C-Form {1}")
|
||||
.format(self.name, self.c_form_no), raise_exception = 1)
|
||||
|
||||
def update_current_stock(self):
|
||||
for d in self.get('entries'):
|
||||
if d.item_code and d.warehouse:
|
||||
@ -584,14 +596,6 @@ class SalesInvoice(SellingController):
|
||||
})
|
||||
)
|
||||
|
||||
def update_c_form(self):
|
||||
"""Update amended id in C-form"""
|
||||
if self.c_form_no and self.amended_from:
|
||||
frappe.db.sql("""update `tabC-Form Invoice Detail` set invoice_no = %s,
|
||||
invoice_date = %s, territory = %s, net_total = %s,
|
||||
grand_total = %s where invoice_no = %s and parent = %s""",
|
||||
(self.name, self.amended_from, self.c_form_no))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_bank_cash_account(mode_of_payment):
|
||||
val = frappe.db.get_value("Mode of Payment", mode_of_payment, "default_account")
|
||||
|
@ -439,7 +439,7 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-09-08 08:06:30.382092",
|
||||
"modified": "2014-09-09 05:35:36.019576",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Item",
|
||||
|
@ -45,7 +45,7 @@ pscript['onload_Accounts Browser'] = function(wrapper){
|
||||
'icon-plus');
|
||||
}
|
||||
|
||||
wrapper.appframe.set_title_right('Refresh', function() {
|
||||
wrapper.appframe.set_title_right(__('Refresh'), function() {
|
||||
wrapper.$company_select.change();
|
||||
});
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
frappe.pages['pos'].onload = function(wrapper) {
|
||||
frappe.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: 'Start POS',
|
||||
title: __('Start POS'),
|
||||
single_column: true
|
||||
});
|
||||
|
||||
|
@ -163,7 +163,7 @@ def create_party_account(party, party_type, company):
|
||||
|
||||
company_details = frappe.db.get_value("Company", company,
|
||||
["abbr", "receivables_group", "payables_group"], as_dict=True)
|
||||
if not frappe.db.exists("Account", (party + " - " + company_details.abbr)):
|
||||
if not frappe.db.exists("Account", (party.strip() + " - " + company_details.abbr)):
|
||||
parent_account = company_details.receivables_group \
|
||||
if party_type=="Customer" else company_details.payables_group
|
||||
if not parent_account:
|
||||
|
@ -67,12 +67,12 @@ def execute(filters=None):
|
||||
|
||||
def get_columns(supplier_naming_by):
|
||||
columns = [
|
||||
"Posting Date:Date:80", "Account:Link/Account:150", "Voucher Type::110",
|
||||
"Voucher No::120", "::30", "Due Date:Date:80", "Bill No::80", "Bill Date:Date:80",
|
||||
"Invoiced Amount:Currency:100", "Paid Amount: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",
|
||||
"Supplier:Link/Supplier:150"
|
||||
_("Posting Date") + ":Date:80", _("Account") + ":Link/Account:150", _("Voucher Type") + "::110",
|
||||
_("Voucher No") + "::120", "::30", _("Due Date") + ":Date:80", _("Bill No") + "::80", _("Bill Date") + ":Date:80",
|
||||
_("Invoiced Amount") + ":Currency:100", _("Paid Amount") + ":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",
|
||||
_("Supplier") + ":Link/Supplier:150"
|
||||
]
|
||||
|
||||
if supplier_naming_by == "Naming Series":
|
||||
|
@ -20,13 +20,13 @@ class AccountsReceivableReport(object):
|
||||
|
||||
def get_columns(self, customer_naming_by):
|
||||
columns = [
|
||||
"Posting Date:Date:80", "Account:Link/Account:150",
|
||||
"Voucher Type::110", "Voucher No::120", "::30",
|
||||
"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"
|
||||
_("Posting Date") + ":Date:80", _("Account") + ":Link/Account:150",
|
||||
_("Voucher Type") + "::110", _("Voucher No") + "::120", "::30",
|
||||
_("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"
|
||||
]
|
||||
|
||||
if customer_naming_by == "Naming Series":
|
||||
|
@ -14,9 +14,9 @@ def execute(filters=None):
|
||||
return columns, data
|
||||
|
||||
def get_columns():
|
||||
return ["Journal Voucher:Link/Journal Voucher:140", "Account:Link/Account:140",
|
||||
"Posting Date:Date:100", "Clearance Date:Date:110", "Against Account:Link/Account:200",
|
||||
"Debit:Currency:120", "Credit:Currency:120"
|
||||
return [_("Journal Voucher") + ":Link/Journal Voucher:140", _("Account") + ":Link/Account:140",
|
||||
_("Posting Date") + ":Date:100", _("Clearance Date") + ":Date:110", _("Against Account") + ":Link/Account:200",
|
||||
_("Debit") + ":Currency:120", _("Credit") + ":Currency:120"
|
||||
]
|
||||
|
||||
def get_conditions(filters):
|
||||
|
@ -16,31 +16,31 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for(var i=0, l=data.length; i<l; i++) { %}
|
||||
{% if (data[i].posting_date) { %}
|
||||
{% if (data[i][__("Posting Date")]) { %}
|
||||
<tr>
|
||||
<td>{%= dateutil.str_to_user(data[i].posting_date) %}</td>
|
||||
<td>{%= data[i].journal_voucher %}</td>
|
||||
<td>{%= __("Against") %}: {%= data[i].against_account %}
|
||||
{% if (data[i].reference) { %}
|
||||
<br>{%= __("Reference") %}: {%= data[i].reference %}
|
||||
{% if (data[i].ref_date) { %}
|
||||
<br>{%= __("Reference Date") %}: {%= dateutil.str_to_user(data[i].ref_date) %}
|
||||
<td>{%= dateutil.str_to_user(data[i][__("Posting Date")]) %}</td>
|
||||
<td>{%= data[i][__("Journal Voucher")] %}</td>
|
||||
<td>{%= __("Against") %}: {%= data[i][__("Against Account")] %}
|
||||
{% if (data[i][__("Reference")]) { %}
|
||||
<br>{%= __("Reference") %}: {%= data[i][__("Reference")] %}
|
||||
{% if (data[i][__("Ref Date")]) { %}
|
||||
<br>{%= __("Reference Date") %}: {%= dateutil.str_to_user(data[i][__("Ref Date")]) %}
|
||||
{% } %}
|
||||
{% } %}
|
||||
{% if (data[i].clearance_date) { %}
|
||||
<br>{%= __("Clearance Date") %}: {%= dateutil.str_to_user(data[i].clearance_date) %}
|
||||
{% if (data[i][__("Clearance Date")]) { %}
|
||||
<br>{%= __("Clearance Date") %}: {%= dateutil.str_to_user(data[i][__("Clearance Date")]) %}
|
||||
{% } %}
|
||||
</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i].debit) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i].credit) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("Debit")]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("Credit")]) %}</td>
|
||||
</tr>
|
||||
{% } else { %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>{%= data[i].journal_voucher %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i].debit) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i].credit) %}</td>
|
||||
<td>{%= data[i][__("Journal Voucher")] %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("Debit")]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("Credit")]) %}</td>
|
||||
</tr>
|
||||
{% } %}
|
||||
{% } %}
|
||||
|
@ -26,7 +26,7 @@ def execute(filters=None):
|
||||
amounts_not_reflected_in_system = frappe.db.sql("""select sum(ifnull(jvd.debit, 0) - ifnull(jvd.credit, 0))
|
||||
from `tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv
|
||||
where jvd.parent = jv.name and jv.docstatus=1 and jvd.account=%s
|
||||
and jv.posting_date > %s and jv.clearance_date <= %s
|
||||
and jv.posting_date > %s and jv.clearance_date <= %s and ifnull(jv.is_opening, 'No') = 'No'
|
||||
""", (filters["account"], filters["report_date"], filters["report_date"]))
|
||||
|
||||
amounts_not_reflected_in_system = flt(amounts_not_reflected_in_system[0][0]) \
|
||||
@ -47,9 +47,9 @@ def execute(filters=None):
|
||||
return columns, data
|
||||
|
||||
def get_columns():
|
||||
return ["Posting Date:Date:100", "Journal Voucher:Link/Journal Voucher:220",
|
||||
"Debit:Currency:120", "Credit:Currency:120",
|
||||
"Against Account:Link/Account:200", "Reference::100", "Ref Date:Date:110", "Clearance Date:Date:110"
|
||||
return [_("Posting Date") + ":Date:100", _("Journal Voucher") + ":Link/Journal Voucher:220",
|
||||
_("Debit") + ":Currency:120", _("Credit") + ":Currency:120",
|
||||
_("Against Account") + ":Link/Account:200", _("Reference") + "::100", _("Ref Date") + ":Date:110", _("Clearance Date") + ":Date:110"
|
||||
]
|
||||
|
||||
def get_entries(filters):
|
||||
@ -61,6 +61,7 @@ def get_entries(filters):
|
||||
where jvd.parent = jv.name and jv.docstatus=1
|
||||
and jvd.account = %(account)s and jv.posting_date <= %(report_date)s
|
||||
and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s
|
||||
and ifnull(jv.is_opening, 'No') = 'No'
|
||||
order by jv.name DESC""", filters, as_list=1)
|
||||
|
||||
return entries
|
||||
|
@ -5,6 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _, msgprint
|
||||
from frappe.utils import flt
|
||||
from frappe.utils import formatdate
|
||||
import time
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
from erpnext.controllers.trends import get_period_date_ranges, get_period_month_ranges
|
||||
@ -44,21 +45,21 @@ def get_columns(filters):
|
||||
msgprint(_("Please specify") + ": " + label,
|
||||
raise_exception=True)
|
||||
|
||||
columns = ["Cost Center:Link/Cost Center:120", "Account:Link/Account:120"]
|
||||
columns = [_("Cost Center") + ":Link/Cost Center:120", _("Account") + ":Link/Account:120"]
|
||||
|
||||
group_months = False if filters["period"] == "Monthly" else True
|
||||
|
||||
for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]):
|
||||
for label in ["Target (%s)", "Actual (%s)", "Variance (%s)"]:
|
||||
for label in [_("Target") + " (%s)", _("Actual") + " (%s)", _("Variance") + " (%s)"]:
|
||||
if group_months:
|
||||
label = label % (from_date.strftime("%b") + " - " + to_date.strftime("%b"))
|
||||
label = label % (formatdate(from_date, format_string="MMM") + " - " + formatdate(from_date, format_string="MMM"))
|
||||
else:
|
||||
label = label % from_date.strftime("%b")
|
||||
label = label % formatdate(from_date, format_string="MMM")
|
||||
|
||||
columns.append(label+":Float:120")
|
||||
|
||||
return columns + ["Total Target:Float:120", "Total Actual:Float:120",
|
||||
"Total Variance:Float:120"]
|
||||
return columns + [_("Total Target") + ":Float:120", _("Total Actual") + ":Float:120",
|
||||
_("Total Variance") + ":Float:120"]
|
||||
|
||||
#Get cost center & target details
|
||||
def get_costcenter_target_details(filters):
|
||||
|
@ -22,23 +22,23 @@
|
||||
<tbody>
|
||||
{% for(var i=0, l=data.length; i<l; i++) { %}
|
||||
<tr>
|
||||
{% if(data[i].posting_date) { %}
|
||||
<td>{%= dateutil.str_to_user(data[i].posting_date) %}</td>
|
||||
<td>{%= data[i].voucher_type%}
|
||||
<br>{%= data[i].voucher_no %}</td>
|
||||
<td>{%= data[i].account %}
|
||||
<br>{%= __("Against") %}: {%= data[i].against_account %}
|
||||
<br>{%= __("Remarks") %}: {%= data[i].remarks %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i].debit) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i].credit) %}</td>
|
||||
{% if(data[i][__("Posting Date")]) { %}
|
||||
<td>{%= dateutil.str_to_user(data[i][__("Posting Date")]) %}</td>
|
||||
<td>{%= data[i][__("Voucher Type")] %}
|
||||
<br>{%= data[i][__("Voucher No")] %}</td>
|
||||
<td>{%= data[i][__("Account")] %}
|
||||
<br>{%= __("Against") %}: {%= data[i][__("Against Account")] %}
|
||||
<br>{%= __("Remarks") %}: {%= data[i][__("Remarks")] %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("Debit")]) %}</td>
|
||||
<td style="text-align: right">{%= format_currency(data[i][__("Credit")]) %}</td>
|
||||
{% } else { %}
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td><b>{%= data[i].account || " " %}</b></td>
|
||||
<td><b>{%= data[i][__("Account")] || " " %}</b></td>
|
||||
<td style="text-align: right">
|
||||
{%= data[i].account && format_currency(data[i].debit) %}</td>
|
||||
{%= data[i][__("Account")] && format_currency(data[i][__("Debit")]) %}</td>
|
||||
<td style="text-align: right">
|
||||
{%= data[i].account && format_currency(data[i].credit) %}</td>
|
||||
{%= data[i][__("Account")] && format_currency(data[i][__("Credit")]) %}</td>
|
||||
{% } %}
|
||||
</tr>
|
||||
{% } %}
|
||||
|
@ -34,9 +34,9 @@ def validate_filters(filters, account_details):
|
||||
frappe.throw(_("From Date must be before To Date"))
|
||||
|
||||
def get_columns():
|
||||
return ["Posting Date:Date:100", "Account:Link/Account:200", "Debit:Float:100",
|
||||
"Credit:Float:100", "Voucher Type::120", "Voucher No::160", "Link::20",
|
||||
"Against Account::120", "Cost Center:Link/Cost Center:100", "Remarks::400"]
|
||||
return [_("Posting Date") + ":Date:100", _("Account") + ":Link/Account:200", _("Debit") + ":Float:100",
|
||||
_("Credit") + ":Float:100", _("Voucher Type") + "::120", _("Voucher No") + "::160", _("Link") + "::20",
|
||||
_("Against Account") + "::120", _("Cost Center") + ":Link/Cost Center:100", _("Remarks") + "::400"]
|
||||
|
||||
def get_result(filters, account_details):
|
||||
gl_entries = get_gl_entries(filters)
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
from erpnext.stock.utils import get_buying_amount, get_sales_bom_buying_amount
|
||||
|
||||
@ -13,11 +14,11 @@ def execute(filters=None):
|
||||
source = get_source_data(filters)
|
||||
item_sales_bom = get_item_sales_bom()
|
||||
|
||||
columns = ["Delivery Note/Sales Invoice::120", "Link::30", "Posting Date:Date", "Posting Time",
|
||||
"Item Code:Link/Item", "Item Name", "Description", "Warehouse:Link/Warehouse",
|
||||
"Qty:Float", "Selling Rate:Currency", "Avg. Buying Rate:Currency",
|
||||
"Selling Amount:Currency", "Buying Amount:Currency",
|
||||
"Gross Profit:Currency", "Gross Profit %:Percent", "Project:Link/Project"]
|
||||
columns = [__("Delivery Note/Sales Invoice") + "::120", _("Link") + "::30", _("Posting Date") + ":Date", _("Posting Time"),
|
||||
_("Item Code") + ":Link/Item", _("Item Name"), _("Description"), _("Warehouse") + ":Link/Warehouse",
|
||||
_("Qty") + ":Float", _("Selling Rate") + ":Currency", _("Avg. Buying Rate") + ":Currency",
|
||||
_("Selling Amount") + ":Currency", _("Buying Amount") + ":Currency",
|
||||
_("Gross Profit") + ":Currency", _("Gross Profit %") + ":Percent", _("Project") + ":Link/Project"]
|
||||
data = []
|
||||
for row in source:
|
||||
selling_amount = flt(row.base_amount)
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import msgprint, _
|
||||
from frappe.utils import flt
|
||||
|
||||
def execute(filters=None):
|
||||
@ -33,12 +34,12 @@ def execute(filters=None):
|
||||
|
||||
|
||||
def get_columns():
|
||||
return ["Item Code:Link/Item:120", "Item Name::120", "Item Group:Link/Item Group:100",
|
||||
"Invoice:Link/Purchase Invoice:120", "Posting Date:Date:80", "Supplier:Link/Customer:120",
|
||||
"Supplier Account:Link/Account:120", "Project:Link/Project:80", "Company:Link/Company:100",
|
||||
"Purchase Order:Link/Purchase Order:100", "Purchase Receipt:Link/Purchase Receipt:100",
|
||||
"Expense Account:Link/Account:140", "Qty:Float:120", "Rate:Currency:120",
|
||||
"Amount:Currency:120"]
|
||||
return [_("Item Code") + ":Link/Item:120", _("Item Name") + "::120", _("Item Group") + ":Link/Item Group:100",
|
||||
_("Invoice") + ":Link/Purchase Invoice:120", _("Posting Date") + ":Date:80", _("Supplier") + ":Link/Customer:120",
|
||||
_("Supplier Account") + ":Link/Account:120", _("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100",
|
||||
_("Purchase Order") + ":Link/Purchase Order:100", _("Purchase Receipt") + ":Link/Purchase Receipt:100",
|
||||
_("Expense Account") + ":Link/Account:140", _("Qty") + ":Float:120", _("Rate") + ":Currency:120",
|
||||
_("Amount") + ":Currency:120"]
|
||||
|
||||
def get_conditions(filters):
|
||||
conditions = ""
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import msgprint, _
|
||||
from frappe.utils import flt
|
||||
|
||||
def execute(filters=None):
|
||||
@ -32,12 +33,12 @@ def execute(filters=None):
|
||||
|
||||
def get_columns():
|
||||
return [
|
||||
"Item Code:Link/Item:120", "Item Name::120", "Item Group:Link/Item Group:100",
|
||||
"Invoice:Link/Sales Invoice:120", "Posting Date:Date:80", "Customer:Link/Customer:120",
|
||||
"Customer Account:Link/Account:120", "Territory:Link/Territory:80",
|
||||
"Project:Link/Project:80", "Company:Link/Company:100", "Sales Order:Link/Sales Order:100",
|
||||
"Delivery Note:Link/Delivery Note:100", "Income Account:Link/Account:140",
|
||||
"Qty:Float:120", "Rate:Currency:120", "Amount:Currency:120"
|
||||
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120", _("Item Group") + ":Link/Item Group:100",
|
||||
_("Invoice") + ":Link/Sales Invoice:120", _("Posting Date") + ":Date:80", _("Customer") + ":Link/Customer:120",
|
||||
_("Customer Account") + ":Link/Account:120", _("Territory") + ":Link/Territory:80",
|
||||
_("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100", _("Sales Order") + ":Link/Sales Order:100",
|
||||
_("Delivery Note") + ":Link/Delivery Note:100", _("Income Account") + ":Link/Account:140",
|
||||
_("Qty") + ":Float:120", _("Rate") + ":Currency:120", _("Amount") + ":Currency:120"
|
||||
]
|
||||
|
||||
def get_conditions(filters):
|
||||
|
@ -37,11 +37,11 @@ def execute(filters=None):
|
||||
return columns, data
|
||||
|
||||
def get_columns():
|
||||
return ["Journal Voucher:Link/Journal Voucher:140", "Account:Link/Account:140",
|
||||
"Posting Date:Date:100", "Against Invoice:Link/Purchase Invoice:130",
|
||||
"Against Invoice Posting Date:Date:130", "Debit:Currency:120", "Credit:Currency:120",
|
||||
"Reference No::100", "Reference Date:Date:100", "Remarks::150", "Age:Int:40",
|
||||
"0-30:Currency:100", "30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100"
|
||||
return [_("Journal Voucher") + ":Link/Journal Voucher:140", _("Account") + ":Link/Account:140",
|
||||
_("Posting Date") + ":Date:100", _("Against Invoice") + ":Link/Purchase Invoice:130",
|
||||
_("Against Invoice Posting Date") + ":Date:130", _("Debit") + ":Currency:120", _("Credit") + ":Currency:120",
|
||||
_("Reference No") + "::100", _("Reference Date") + ":Date:100", _("Remarks") + "::150", _("Age") +":Int:40",
|
||||
"0-30:Currency:100", "30-60:Currency:100", "60-90:Currency:100", _("90-Above") + ":Currency:100"
|
||||
]
|
||||
|
||||
def get_conditions(filters):
|
||||
|
@ -63,11 +63,11 @@ def execute(filters=None):
|
||||
def get_columns(invoice_list):
|
||||
"""return columns based on filters"""
|
||||
columns = [
|
||||
"Invoice:Link/Purchase Invoice:120", "Posting Date:Date:80", "Supplier Id::120",
|
||||
"Supplier Name::120", "Supplier Account:Link/Account:120",
|
||||
"Account Group:LInk/Account:120", "Project:Link/Project:80", "Bill No::120",
|
||||
"Bill Date:Date:80", "Remarks::150",
|
||||
"Purchase Order:Link/Purchase Order:100", "Purchase Receipt:Link/Purchase Receipt:100"
|
||||
_("Invoice") + ":Link/Purchase Invoice:120", _("Posting Date") + ":Date:80", _("Supplier Id") + "::120",
|
||||
_("Supplier Name") + "::120", _("Supplier Account") + ":Link/Account:120",
|
||||
_("Account Group") + ":Link/Account:120", _("Project") + ":Link/Project:80", _("Bill No") + "::120",
|
||||
_("Bill Date") + ":Date:80", _("Remarks") + "::150",
|
||||
_("Purchase Order") + ":Link/Purchase Order:100", _("Purchase Receipt") + ":Link/Purchase Receipt:100"
|
||||
]
|
||||
expense_accounts = tax_accounts = expense_columns = tax_columns = []
|
||||
|
||||
|
@ -63,10 +63,10 @@ def execute(filters=None):
|
||||
def get_columns(invoice_list):
|
||||
"""return columns based on filters"""
|
||||
columns = [
|
||||
"Invoice:Link/Sales Invoice:120", "Posting Date:Date:80", "Customer Id::120",
|
||||
"Customer Name::120", "Customer Account:Link/Account:120", "Account Group:LInk/Account:120",
|
||||
"Territory:Link/Territory:80", "Project:Link/Project:80", "Remarks::150",
|
||||
"Sales Order:Link/Sales Order:100", "Delivery Note:Link/Delivery Note:100"
|
||||
_("Invoice") + ":Link/Sales Invoice:120", _("Posting Date") + ":Date:80", _("Customer Id") + "::120",
|
||||
_("Customer Name") + "::120", _("Customer Account") + ":Link/Account:120", _("Account Group") + ":Link/Account:120",
|
||||
_("Territory") + ":Link/Territory:80", _("Project") + ":Link/Project:80", _("Remarks") + "::150",
|
||||
_("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100"
|
||||
]
|
||||
|
||||
income_accounts = tax_accounts = income_columns = tax_columns = []
|
||||
|
@ -391,3 +391,42 @@ def get_stock_rbnb_difference(posting_date, company):
|
||||
|
||||
# Amount should be credited
|
||||
return flt(stock_rbnb) + flt(sys_bal)
|
||||
|
||||
def get_outstanding_invoices(amount_query, account):
|
||||
all_outstanding_vouchers = []
|
||||
outstanding_voucher_list = frappe.db.sql("""
|
||||
select
|
||||
voucher_no, voucher_type, posting_date,
|
||||
ifnull(sum({amount_query}), 0) as invoice_amount
|
||||
from
|
||||
`tabGL Entry`
|
||||
where
|
||||
account = %s and {amount_query} > 0
|
||||
group by voucher_type, voucher_no
|
||||
""".format(amount_query = amount_query), account, as_dict = True)
|
||||
|
||||
for d in outstanding_voucher_list:
|
||||
payment_amount = frappe.db.sql("""
|
||||
select ifnull(sum(ifnull({amount_query}, 0)), 0)
|
||||
from
|
||||
`tabGL Entry`
|
||||
where
|
||||
account = %s and {amount_query} < 0
|
||||
and against_voucher_type = %s and ifnull(against_voucher, '') = %s
|
||||
""".format(**{
|
||||
"amount_query": amount_query
|
||||
}), (account, d.voucher_type, d.voucher_no))
|
||||
|
||||
payment_amount = -1*payment_amount[0][0] if payment_amount else 0
|
||||
|
||||
if d.invoice_amount > payment_amount:
|
||||
|
||||
all_outstanding_vouchers.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
|
||||
})
|
||||
|
||||
return all_outstanding_vouchers
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -238,6 +238,11 @@ def make_purchase_receipt(source_name, target_doc=None):
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_purchase_invoice(source_name, target_doc=None):
|
||||
def postprocess(source, target):
|
||||
set_missing_values(source, target)
|
||||
#Get the advance paid Journal Vouchers in Purchase Invoice Advance
|
||||
target.get_advances()
|
||||
|
||||
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)
|
||||
@ -263,6 +268,6 @@ def make_purchase_invoice(source_name, target_doc=None):
|
||||
"doctype": "Purchase Taxes and Charges",
|
||||
"add_if_empty": True
|
||||
}
|
||||
}, target_doc, set_missing_values)
|
||||
}, target_doc, postprocess)
|
||||
|
||||
return doc
|
||||
|
@ -1,5 +1,6 @@
|
||||
[
|
||||
{
|
||||
"advance_paid": 0.0,
|
||||
"buying_price_list": "_Test Price List",
|
||||
"company": "_Test Company",
|
||||
"conversion_rate": 1.0,
|
||||
@ -31,5 +32,39 @@
|
||||
"supplier": "_Test Supplier",
|
||||
"supplier_name": "_Test Supplier",
|
||||
"transaction_date": "2013-02-12"
|
||||
},
|
||||
{
|
||||
"advance_paid": 0.0,
|
||||
"buying_price_list": "_Test Price List",
|
||||
"company": "_Test Company",
|
||||
"conversion_rate": 1.0,
|
||||
"currency": "INR",
|
||||
"doctype": "Purchase Order",
|
||||
"fiscal_year": "_Test Fiscal Year 2013",
|
||||
"grand_total": 5000.0,
|
||||
"grand_total_import": 5000.0,
|
||||
"is_subcontracted": "No",
|
||||
"naming_series": "_T-Purchase Order-",
|
||||
"net_total": 5000.0,
|
||||
"po_details": [
|
||||
{
|
||||
"base_amount": 5000.0,
|
||||
"conversion_factor": 1.0,
|
||||
"description": "_Test Item",
|
||||
"doctype": "Purchase Order Item",
|
||||
"item_code": "_Test Item",
|
||||
"item_name": "_Test Item",
|
||||
"parentfield": "po_details",
|
||||
"qty": 10.0,
|
||||
"rate": 500.0,
|
||||
"schedule_date": "2013-03-01",
|
||||
"stock_uom": "_Test UOM",
|
||||
"uom": "_Test UOM",
|
||||
"warehouse": "_Test Warehouse - _TC"
|
||||
}
|
||||
],
|
||||
"supplier": "_Test Supplier",
|
||||
"supplier_name": "_Test Supplier",
|
||||
"transaction_date": "2013-02-12"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
@ -445,7 +445,7 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-09-08 08:06:30.684601",
|
||||
"modified": "2014-09-09 05:35:36.346557",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order Item",
|
||||
|
@ -186,12 +186,20 @@
|
||||
],
|
||||
"icon": "icon-user",
|
||||
"idx": 1,
|
||||
"modified": "2014-08-26 04:55:32.004458",
|
||||
"modified": "2014-09-10 17:53:09.286715",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Purchase User"
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"create": 0,
|
||||
@ -201,7 +209,7 @@
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Purchase User",
|
||||
"role": "Purchase Manager",
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
},
|
||||
@ -224,11 +232,27 @@
|
||||
"read": 1,
|
||||
"role": "Material User"
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Material Manager"
|
||||
},
|
||||
{
|
||||
"apply_user_permissions": 1,
|
||||
"permlevel": 0,
|
||||
"read": 1,
|
||||
"role": "Accounts User"
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager"
|
||||
}
|
||||
],
|
||||
"search_fields": "supplier_name,supplier_type",
|
||||
|
@ -4,5 +4,11 @@
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier",
|
||||
"supplier_type": "_Test Supplier Type"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"doctype": "Supplier",
|
||||
"supplier_name": "_Test Supplier 1",
|
||||
"supplier_type": "_Test Supplier Type"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"allow_import": 1,
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-05-21 16:16:45",
|
||||
"docstatus": 0,
|
||||
@ -575,7 +575,7 @@
|
||||
"icon": "icon-shopping-cart",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-08-14 02:17:26.401532",
|
||||
"modified": "2014-09-09 05:35:35.369734",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation",
|
||||
|
@ -331,7 +331,7 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-09-08 08:06:30.976906",
|
||||
"modified": "2014-09-09 05:35:36.623995",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation Item",
|
||||
|
@ -5,12 +5,12 @@
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2014-06-03 07:18:17.358554",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2014-09-11 08:53:17.358554",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Addresses and Contacts",
|
||||
"owner": "Administrator",
|
||||
"query": "SELECT\n `tabSupplier`.name as \"Supplier:Link/Supplier:120\",\n\t`tabSupplier`.supplier_name as \"Supplier Name::120\",\n\t`tabSupplier`.supplier_type as \"Supplier Type:Link/Supplier Type:120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2), \n\t\ttabAddress.state, tabAddress.pincode, tabAddress.country\n\t) as 'Address::180',\n concat_ws(', ', `tabContact`.first_name, `tabContact`.last_name) as 'Contact Name::180',\n\t`tabContact`.phone as \"Phone\",\n\t`tabContact`.mobile_no as \"Mobile No\",\n\t`tabContact`.email_id as \"Email Id::120\",\n\t`tabContact`.is_primary_contact as \"Is Primary Contact::120\"\nFROM\n\t`tabSupplier`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.supplier=`tabSupplier`.name\n\t)\n\tleft join `tabContact` on (\n\t\t`tabContact`.supplier=`tabSupplier`.name\n\t)\nWHERE\n\t`tabSupplier`.docstatus<2\nORDER BY\n\t`tabSupplier`.name asc",
|
||||
"query": "SELECT\n `tabSupplier`.name as \"Supplier:Link/Supplier:120\",\n\t`tabSupplier`.supplier_name as \"Supplier Name::120\",\n\t`tabSupplier`.supplier_type as \"Supplier Type:Link/Supplier Type:120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2), \n\t\ttabAddress.state, tabAddress.pincode, tabAddress.country\n\t) as 'Address::180',\n concat_ws(', ', `tabContact`.first_name, `tabContact`.last_name) as \"Contact Name::180\",\n\t`tabContact`.phone as \"Phone\",\n\t`tabContact`.mobile_no as \"Mobile No\",\n\t`tabContact`.email_id as \"Email Id::120\",\n\t`tabContact`.is_primary_contact as \"Is Primary Contact::120\"\nFROM\n\t`tabSupplier`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.supplier=`tabSupplier`.name\n\t)\n\tleft join `tabContact` on (\n\t\t`tabContact`.supplier=`tabSupplier`.name\n\t)\nWHERE\n\t`tabSupplier`.docstatus<2\nORDER BY\n\t`tabSupplier`.name asc",
|
||||
"ref_doctype": "Supplier",
|
||||
"report_name": "Supplier Addresses and Contacts",
|
||||
"report_type": "Query Report"
|
||||
|
@ -61,6 +61,11 @@ def get_data():
|
||||
"name": "Period Closing Voucher",
|
||||
"description": _("Close Balance Sheet and book Profit or Loss.")
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Payment Tool",
|
||||
"description": _("Create Payment Entries against Orders or Invoices.")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -135,12 +135,6 @@ def get_data():
|
||||
"name": "Item-wise Purchase History",
|
||||
"doctype": "Item"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Item-wise Last Purchase Rate",
|
||||
"doctype": "Item"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
|
@ -171,6 +171,12 @@ def get_data():
|
||||
"label": _("Stock Analytics"),
|
||||
"icon": "icon-bar-chart"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Warehouse-Wise Stock Balance",
|
||||
"doctype": "Warehouse"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -222,12 +228,6 @@ def get_data():
|
||||
"name": "Batch-Wise Balance History",
|
||||
"doctype": "Batch"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
"name": "Warehouse-Wise Stock Balance",
|
||||
"doctype": "Warehouse"
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"is_query_report": True,
|
||||
|
@ -363,9 +363,10 @@ class AccountsController(TransactionBase):
|
||||
and ifnull(allocated_amount, 0) = 0""" % (childtype, '%s', '%s'), (parentfield, self.name))
|
||||
|
||||
def get_advances(self, account_head, child_doctype, parentfield, dr_or_cr):
|
||||
against_order_list = []
|
||||
res = frappe.db.sql("""
|
||||
select
|
||||
t1.name as jv_no, t1.remark, t2.%s as amount, t2.name as jv_detail_no
|
||||
t1.name as jv_no, t1.remark, t2.%s as amount, t2.name as jv_detail_no, t2.%s as order_no
|
||||
from
|
||||
`tabJournal Voucher` t1, `tabJournal Voucher Detail` t2
|
||||
where
|
||||
@ -374,18 +375,25 @@ class AccountsController(TransactionBase):
|
||||
and ifnull(t2.against_invoice, '') = ''
|
||||
and ifnull(t2.against_jv, '') = ''
|
||||
order by t1.posting_date""" %
|
||||
(dr_or_cr, '%s'), account_head, as_dict=1)
|
||||
(dr_or_cr, "against_sales_order" if dr_or_cr == "credit" \
|
||||
else "against_purchase_order", '%s'),
|
||||
account_head, as_dict= True)
|
||||
|
||||
if self.get("entries"):
|
||||
for i in self.get("entries"):
|
||||
against_order_list.append(i.sales_order if dr_or_cr == "credit" else i.purchase_order)
|
||||
|
||||
self.set(parentfield, [])
|
||||
for d in res:
|
||||
self.append(parentfield, {
|
||||
"doctype": child_doctype,
|
||||
"journal_voucher": d.jv_no,
|
||||
"jv_detail_no": d.jv_detail_no,
|
||||
"remarks": d.remark,
|
||||
"advance_amount": flt(d.amount),
|
||||
"allocate_amount": 0
|
||||
})
|
||||
if not against_order_list or d.order_no in against_order_list:
|
||||
self.append(parentfield, {
|
||||
"doctype": child_doctype,
|
||||
"journal_voucher": d.jv_no,
|
||||
"jv_detail_no": d.jv_detail_no,
|
||||
"remarks": d.remark,
|
||||
"advance_amount": flt(d.amount),
|
||||
"allocate_amount": 0
|
||||
})
|
||||
|
||||
def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield):
|
||||
from erpnext.controllers.status_updater import get_tolerance_for
|
||||
@ -430,6 +438,32 @@ class AccountsController(TransactionBase):
|
||||
|
||||
return stock_items
|
||||
|
||||
def set_total_advance_paid(self):
|
||||
if self.doctype == "Sales Order":
|
||||
dr_or_cr = "credit"
|
||||
against_field = "against_sales_order"
|
||||
else:
|
||||
dr_or_cr = "debit"
|
||||
against_field = "against_purchase_order"
|
||||
|
||||
advance_paid = frappe.db.sql("""
|
||||
select
|
||||
sum(ifnull({dr_or_cr}, 0))
|
||||
from
|
||||
`tabJournal Voucher Detail`
|
||||
where
|
||||
{against_field} = %s and docstatus = 1 and is_advance = "Yes" """.format(dr_or_cr=dr_or_cr, \
|
||||
against_field=against_field), self.name)
|
||||
|
||||
if advance_paid:
|
||||
advance_paid = flt(advance_paid[0][0], self.precision("advance_paid"))
|
||||
if flt(self.grand_total) >= advance_paid:
|
||||
frappe.db.set_value(self.doctype, self.name, "advance_paid", advance_paid)
|
||||
else:
|
||||
frappe.throw(_("Total advance ({0}) against Order {1} cannot be greater \
|
||||
than the Grand Total ({2})")
|
||||
.format(advance_paid, self.name, self.grand_total))
|
||||
|
||||
@property
|
||||
def company_abbr(self):
|
||||
if not hasattr(self, "_abbr"):
|
||||
|
@ -36,6 +36,9 @@ def manage_recurring_documents(doctype, next_date=None, commit=True):
|
||||
% (doctype, date_field, '%s', '%s'), (next_date, recurring_id)):
|
||||
try:
|
||||
ref_wrapper = frappe.get_doc(doctype, ref_document)
|
||||
if hasattr(ref_wrapper, "before_recurring"):
|
||||
ref_wrapper.before_recurring()
|
||||
|
||||
new_document_wrapper = make_new_document(ref_wrapper, date_field, next_date)
|
||||
send_notification(new_document_wrapper)
|
||||
if commit:
|
||||
|
@ -16,10 +16,10 @@ def get_columns(filters, trans):
|
||||
# get conditions for grouping filter cond
|
||||
group_by_cols = group_wise_column(filters.get("group_by"))
|
||||
|
||||
columns = based_on_details["based_on_cols"] + period_cols + ["Total(Qty):Float:120", "Total(Amt):Currency:120"]
|
||||
columns = based_on_details["based_on_cols"] + period_cols + [_("Total(Qty)") + ":Float:120", _("Total(Amt)") + ":Currency:120"]
|
||||
if group_by_cols:
|
||||
columns = based_on_details["based_on_cols"] + group_by_cols + period_cols + \
|
||||
["Total(Qty):Float:120", "Total(Amt):Currency:120"]
|
||||
[_("Total(Qty)") + ":Float:120", _("Total(Amt)") + ":Currency:120"]
|
||||
|
||||
conditions = {"based_on_select": based_on_details["based_on_select"], "period_wise_select": period_select,
|
||||
"columns": columns, "group_by": based_on_details["based_on_group_by"], "grbc": group_by_cols, "trans": trans,
|
||||
@ -130,8 +130,8 @@ def period_wise_columns_query(filters, trans):
|
||||
get_period_wise_columns(dt, filters.get("period"), pwc)
|
||||
query_details = get_period_wise_query(dt, trans_date, query_details)
|
||||
else:
|
||||
pwc = [filters.get("fiscal_year") + " (Qty):Float:120",
|
||||
filters.get("fiscal_year") + " (Amt):Currency:120"]
|
||||
pwc = [_(filters.get("fiscal_year")) + " ("+_("Qty") + "):Float:120",
|
||||
_(filters.get("fiscal_year")) + " ("+ _("Amt") + "):Currency:120"]
|
||||
query_details = " SUM(t2.qty), SUM(t2.base_amount),"
|
||||
|
||||
query_details += 'SUM(t2.qty), SUM(t2.base_amount)'
|
||||
@ -139,11 +139,11 @@ def period_wise_columns_query(filters, trans):
|
||||
|
||||
def get_period_wise_columns(bet_dates, period, pwc):
|
||||
if period == 'Monthly':
|
||||
pwc += [get_mon(bet_dates[0]) + " (Qty):Float:120",
|
||||
get_mon(bet_dates[0]) + " (Amt):Currency:120"]
|
||||
pwc += [_(get_mon(bet_dates[0])) + " (" + _("Qty") + "):Float:120",
|
||||
_(get_mon(bet_dates[0])) + " (" + _("Amt") + "):Currency:120"]
|
||||
else:
|
||||
pwc += [get_mon(bet_dates[0]) + "-" + get_mon(bet_dates[1]) + " (Qty):Float:120",
|
||||
get_mon(bet_dates[0]) + "-" + get_mon(bet_dates[1]) + " (Amt):Currency:120"]
|
||||
pwc += [_(get_mon(bet_dates[0])) + "-" + _(get_mon(bet_dates[1])) + " (" + _("Qty") + "):Float:120",
|
||||
_(get_mon(bet_dates[0])) + "-" + _(get_mon(bet_dates[1])) + " (" + _("Amt") + "):Currency:120"]
|
||||
|
||||
def get_period_wise_query(bet_dates, trans_date, query_details):
|
||||
query_details += """SUM(IF(t1.%(trans_date)s BETWEEN '%(sd)s' AND '%(ed)s', t2.qty, NULL)),
|
||||
|
@ -20,7 +20,7 @@ frappe.pages['activity'].onload = function(wrapper) {
|
||||
});
|
||||
list.run();
|
||||
|
||||
wrapper.appframe.set_title_right("Refresh", function() { list.run(); });
|
||||
wrapper.appframe.set_title_right(__("Refresh"), function() { list.run(); });
|
||||
|
||||
// Build Report Button
|
||||
if(frappe.boot.user.can_get_report.indexOf("Feed")!=-1) {
|
||||
|
@ -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.3.0"
|
||||
app_version = "4.4.0"
|
||||
|
||||
error_report_email = "support@erpnext.com"
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -200,7 +200,7 @@ def validate_employee_role(doc, method):
|
||||
# called via User hook
|
||||
if "Employee" in [d.role for d in doc.get("user_roles")]:
|
||||
if not frappe.db.get_value("Employee", {"user_id": doc.name}):
|
||||
frappe.msgprint("Please set User ID field in an Employee record to set Employee Role")
|
||||
frappe.msgprint(_("Please set User ID field in an Employee record to set Employee Role"))
|
||||
doc.get("user_roles").remove(doc.get("user_roles", {"role": "Employee"})[0])
|
||||
|
||||
def update_user_permissions(doc, method):
|
||||
|
@ -158,6 +158,7 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"fieldname": "letter_head",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
@ -183,7 +184,7 @@
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"max_attachments": 3,
|
||||
"modified": "2014-08-28 03:32:38.865202",
|
||||
"modified": "2014-09-09 05:35:31.531651",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Leave Application",
|
||||
|
@ -72,6 +72,7 @@
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"fieldname": "letter_head",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
@ -336,7 +337,7 @@
|
||||
"icon": "icon-file-text",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-08-27 06:38:10.006224",
|
||||
"modified": "2014-09-09 05:35:33.807228",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Slip",
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
|
||||
def execute(filters=None):
|
||||
@ -15,9 +16,9 @@ def execute(filters=None):
|
||||
|
||||
def get_columns():
|
||||
return [
|
||||
"Employee:Link/Employee:120", "Name:Data:200", "Date of Birth:Date:100",
|
||||
"Branch:Link/Branch:120", "Department:Link/Department:120",
|
||||
"Designation:Link/Designation:120", "Gender::60", "Company:Link/Company:120"
|
||||
_("Employee") + ":Link/Employee:120", _("Name") + ":Data:200", _("Date of Birth")+ ":Date:100",
|
||||
_("Branch") + ":Link/Branch:120", _("Department") + ":Link/Department:120",
|
||||
_("Designation") + ":Link/Designation:120", _("Gender") + "::60", _("Company") + ":Link/Company:120"
|
||||
]
|
||||
|
||||
def get_employees(filters):
|
||||
|
@ -39,13 +39,13 @@ def execute(filters=None):
|
||||
','.join(['%s']*len(employee_names)), employee_names, as_dict=True)
|
||||
|
||||
columns = [
|
||||
"Fiscal Year", "Employee:Link/Employee:150", "Employee Name::200", "Department::150"
|
||||
_("Fiscal Year"), _("Employee") + ":Link/Employee:150", _("Employee Name") + "::200", _("Department") +"::150"
|
||||
]
|
||||
|
||||
for leave_type in leave_types:
|
||||
columns.append(leave_type + " Allocated:Float")
|
||||
columns.append(leave_type + " Taken:Float")
|
||||
columns.append(leave_type + " Balance:Float")
|
||||
columns.append(_(leave_type) + " " + _("Allocated") + ":Float")
|
||||
columns.append(_(leave_type) + " " + _("Taken") + ":Float")
|
||||
columns.append(_(leave_type) + " " + _("Balance") + ":Float")
|
||||
|
||||
data = {}
|
||||
for d in allocations:
|
||||
|
@ -45,15 +45,15 @@ def execute(filters=None):
|
||||
|
||||
def get_columns(filters):
|
||||
columns = [
|
||||
"Employee:Link/Employee:120", "Employee Name::140", "Branch:Link/Branch:120",
|
||||
"Department:Link/Department:120", "Designation:Link/Designation:120",
|
||||
"Company:Link/Company:120"
|
||||
_("Employee") + ":Link/Employee:120", _("Employee Name") + "::140", _("Branch")+ ":Link/Branch:120",
|
||||
_("Department") + ":Link/Department:120", _("Designation") + ":Link/Designation:120",
|
||||
_("Company") + ":Link/Company:120"
|
||||
]
|
||||
|
||||
for day in range(filters["total_days_in_month"]):
|
||||
columns.append(cstr(day+1) +"::20")
|
||||
|
||||
columns += ["Total Present:Float:80", "Total Absent:Float:80"]
|
||||
columns += [_("Total Present") + ":Float:80", _("Total Absent") + ":Float:80"]
|
||||
return columns
|
||||
|
||||
def get_attendance_list(conditions, filters):
|
||||
|
@ -36,10 +36,10 @@ def execute(filters=None):
|
||||
|
||||
def get_columns(salary_slips):
|
||||
columns = [
|
||||
"Employee:Link/Employee:120", "Employee Name::140", "Branch:Link/Branch:120",
|
||||
"Department:Link/Department:120", "Designation:Link/Designation:120",
|
||||
"Company:Link/Company:120", "Month::80", "Leave Without pay:Float:130",
|
||||
"Payment Days:Float:120"
|
||||
_("Employee") + ":Link/Employee:120", _("Employee Name") + "::140", _("Branch") + ":Link/Branch:120",
|
||||
_("Department") + ":Link/Department:120", _("Designation") + ":Link/Designation:120",
|
||||
_("Company") + ":Link/Company:120", _("Month") + "::80", _("Leave Without Pay") + ":Float:130",
|
||||
_("Payment Days") + ":Float:120"
|
||||
]
|
||||
|
||||
earning_types = frappe.db.sql_list("""select distinct e_type from `tabSalary Slip Earning`
|
||||
|
@ -66,7 +66,10 @@ cur_frm.cscript.workstation = function(doc,dt,dn) {
|
||||
frappe.model.with_doc("Workstation", d.workstation, function(name, r) {
|
||||
d.hour_rate = r.docs[0].hour_rate;
|
||||
refresh_field("hour_rate", dn, "bom_operations");
|
||||
d.fixed_cycle_cost = r.docs[0].fixed_cycle_cost;
|
||||
refresh_field("fixed_cycle_cost", dn, "bom_operations");
|
||||
erpnext.bom.calculate_op_cost(doc);
|
||||
erpnext.bom.calculate_fixed_cost(doc);
|
||||
erpnext.bom.calculate_total(doc);
|
||||
});
|
||||
}
|
||||
@ -74,6 +77,7 @@ cur_frm.cscript.workstation = function(doc,dt,dn) {
|
||||
|
||||
cur_frm.cscript.hour_rate = function(doc, dt, dn) {
|
||||
erpnext.bom.calculate_op_cost(doc);
|
||||
erpnext.bom.calculate_fixed_cost(doc);
|
||||
erpnext.bom.calculate_total(doc);
|
||||
}
|
||||
|
||||
@ -116,7 +120,6 @@ var get_bom_material_detail= function(doc, cdt, cdn) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cur_frm.cscript.qty = function(doc, cdt, cdn) {
|
||||
erpnext.bom.calculate_rm_cost(doc);
|
||||
erpnext.bom.calculate_total(doc);
|
||||
@ -145,6 +148,15 @@ erpnext.bom.calculate_op_cost = function(doc) {
|
||||
refresh_field('operating_cost');
|
||||
}
|
||||
|
||||
erpnext.bom.calculate_fixed_cost = function(doc) {
|
||||
var op = doc.bom_operations || [];
|
||||
var total_fixed_cost = 0;
|
||||
for(var i=0;i<op.length;i++) {
|
||||
total_fixed_cost += flt(op[i].fixed_cycle_cost);
|
||||
}
|
||||
cur_frm.set_value("total_fixed_cost", total_fixed_cost);
|
||||
}
|
||||
|
||||
erpnext.bom.calculate_rm_cost = function(doc) {
|
||||
var rm = doc.bom_materials || [];
|
||||
total_rm_cost = 0;
|
||||
@ -155,14 +167,15 @@ erpnext.bom.calculate_rm_cost = function(doc) {
|
||||
{'qty_consumed_per_unit': flt(rm[i].qty)/flt(doc.quantity)}, 'bom_materials');
|
||||
total_rm_cost += amt;
|
||||
}
|
||||
doc.raw_material_cost = total_rm_cost;
|
||||
refresh_field('raw_material_cost');
|
||||
cur_frm.set_value("raw_material_cost", total_rm_cost);
|
||||
}
|
||||
|
||||
|
||||
// Calculate Total Cost
|
||||
erpnext.bom.calculate_total = function(doc) {
|
||||
doc.total_cost = flt(doc.raw_material_cost) + flt(doc.operating_cost);
|
||||
doc.total_variable_cost = flt(doc.raw_material_cost) + flt(doc.operating_cost) ;
|
||||
refresh_field('total_variable_cost');
|
||||
doc.total_cost = flt(doc.total_fixed_cost) + flt(doc.total_variable_cost);
|
||||
refresh_field('total_cost');
|
||||
}
|
||||
|
||||
@ -204,5 +217,7 @@ cur_frm.fields_dict['bom_materials'].grid.get_field('bom_no').get_query = functi
|
||||
cur_frm.cscript.validate = function(doc, dt, dn) {
|
||||
erpnext.bom.calculate_op_cost(doc);
|
||||
erpnext.bom.calculate_rm_cost(doc);
|
||||
erpnext.bom.calculate_fixed_cost(doc);
|
||||
erpnext.bom.calculate_total(doc);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_attach": 0,
|
||||
"allow_copy": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"creation": "2013-01-22 15:11:38",
|
||||
@ -86,6 +87,7 @@
|
||||
{
|
||||
"fieldname": "bom_operations",
|
||||
"fieldtype": "Table",
|
||||
"in_list_view": 0,
|
||||
"label": "BOM Operations",
|
||||
"oldfieldname": "bom_operations",
|
||||
"oldfieldtype": "Table",
|
||||
@ -115,19 +117,6 @@
|
||||
"oldfieldtype": "Section Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "total_cost",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Total Cost",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "cb1",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "raw_material_cost",
|
||||
"fieldtype": "Float",
|
||||
@ -142,6 +131,33 @@
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "cb1",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "total_variable_cost",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Total Variable Cost",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "total_fixed_cost",
|
||||
"fieldtype": "Float",
|
||||
"label": "Total Fixed Cost",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "total_cost",
|
||||
"fieldtype": "Float",
|
||||
"label": "Total Cost",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "more_info_section",
|
||||
"fieldtype": "Section Break",
|
||||
@ -232,7 +248,7 @@
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2014-05-27 03:49:08.024523",
|
||||
"modified": "2014-09-08 16:30:46.265762",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM",
|
||||
|
@ -127,7 +127,7 @@ class BOM(Document):
|
||||
self.save()
|
||||
|
||||
def get_bom_unitcost(self, bom_no):
|
||||
bom = frappe.db.sql("""select name, total_cost/quantity as unit_cost from `tabBOM`
|
||||
bom = frappe.db.sql("""select name, total_variable_cost/quantity as unit_cost from `tabBOM`
|
||||
where is_active = 1 and name = %s""", bom_no, as_dict=1)
|
||||
return bom and bom[0]['unit_cost'] or 0
|
||||
|
||||
@ -269,7 +269,8 @@ class BOM(Document):
|
||||
"""Calculate bom totals"""
|
||||
self.calculate_op_cost()
|
||||
self.calculate_rm_cost()
|
||||
self.total_cost = self.raw_material_cost + self.operating_cost
|
||||
self.calculate_fixed_cost()
|
||||
self.total_variable_cost = self.raw_material_cost + self.operating_cost
|
||||
|
||||
def calculate_op_cost(self):
|
||||
"""Update workstation rate and calculates totals"""
|
||||
@ -282,6 +283,15 @@ class BOM(Document):
|
||||
total_op_cost += flt(d.operating_cost)
|
||||
self.operating_cost = total_op_cost
|
||||
|
||||
def calculate_fixed_cost(self):
|
||||
"""Update workstation rate and calculates totals"""
|
||||
fixed_cost = 0
|
||||
for d in self.get('bom_operations'):
|
||||
if d.workstation:
|
||||
fixed_cost += flt(frappe.db.get_value("Workstation", d.workstation, "fixed_cycle_cost"))
|
||||
self.total_fixed_cost = fixed_cost
|
||||
|
||||
|
||||
def calculate_rm_cost(self):
|
||||
"""Fetch RM rate as per today's valuation rate and calculate totals"""
|
||||
total_rm_cost = 0
|
||||
|
@ -15,6 +15,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-2 text-right">
|
||||
{%= doc.get_formatted("total_cost") %}
|
||||
{%= doc.get_formatted("total_variable_cost") %}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,3 +1,3 @@
|
||||
frappe.listview_settings['BOM'] = {
|
||||
add_fields: ["is_active", "is_default", "total_cost"]
|
||||
add_fields: ["is_active", "is_default", "total_variable_cost"]
|
||||
};
|
||||
|
@ -54,10 +54,20 @@
|
||||
"is_default": 1,
|
||||
"item": "_Test FG Item",
|
||||
"quantity": 1.0
|
||||
},
|
||||
},
|
||||
{
|
||||
"bom_operations": [
|
||||
{
|
||||
"operation_no": "1",
|
||||
"opn_description": "_Test",
|
||||
"workstation": "_Test Workstation 1",
|
||||
"time_in_min": 60,
|
||||
"operating_cost": 100
|
||||
}
|
||||
],
|
||||
"bom_materials": [
|
||||
{
|
||||
"operation_no": 1,
|
||||
"amount": 5000.0,
|
||||
"doctype": "BOM Item",
|
||||
"item_code": "_Test Item",
|
||||
@ -67,6 +77,7 @@
|
||||
"stock_uom": "_Test UOM"
|
||||
},
|
||||
{
|
||||
"operation_no": 1,
|
||||
"amount": 2000.0,
|
||||
"bom_no": "BOM/_Test Item Home Desktop Manufactured/001",
|
||||
"doctype": "BOM Item",
|
||||
@ -82,6 +93,7 @@
|
||||
"is_active": 1,
|
||||
"is_default": 1,
|
||||
"item": "_Test FG Item 2",
|
||||
"quantity": 1.0
|
||||
"quantity": 1.0,
|
||||
"with_operations": 1
|
||||
}
|
||||
]
|
@ -1,81 +1,89 @@
|
||||
{
|
||||
"creation": "2013-02-22 01:27:49.000000",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"creation": "2013-02-22 01:27:49",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "operation_no",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Operation No",
|
||||
"oldfieldname": "operation_no",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"fieldname": "operation_no",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Operation No",
|
||||
"oldfieldname": "operation_no",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "opn_description",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Operation Description",
|
||||
"oldfieldname": "opn_description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"fieldname": "opn_description",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Operation Description",
|
||||
"oldfieldname": "opn_description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "workstation",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Workstation",
|
||||
"oldfieldname": "workstation",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Workstation",
|
||||
"permlevel": 0,
|
||||
"fieldname": "workstation",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Workstation",
|
||||
"oldfieldname": "workstation",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Workstation",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 0,
|
||||
"label": "Hour Rate",
|
||||
"oldfieldname": "hour_rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 0,
|
||||
"label": "Hour Rate",
|
||||
"oldfieldname": "hour_rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "time_in_mins",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 0,
|
||||
"label": "Operation Time (mins)",
|
||||
"oldfieldname": "time_in_mins",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"fieldname": "time_in_mins",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 0,
|
||||
"label": "Operation Time (mins)",
|
||||
"oldfieldname": "time_in_mins",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "operating_cost",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Operating Cost",
|
||||
"oldfieldname": "operating_cost",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"allow_on_submit": 0,
|
||||
"fieldname": "operating_cost",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Operating Cost",
|
||||
"oldfieldname": "operating_cost",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "fixed_cycle_cost",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 0,
|
||||
"label": "Fixed Cycle Cost",
|
||||
"permlevel": 0
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-02-03 12:53:03.000000",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Operation",
|
||||
"owner": "Administrator"
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-09-15 12:03:47.456370",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Operation",
|
||||
"owner": "Administrator",
|
||||
"permissions": []
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class BOMReplaceTool(Document):
|
||||
frappe.throw(_("Current BOM and New BOM can not be same"))
|
||||
|
||||
def update_new_bom(self):
|
||||
current_bom_unitcost = frappe.db.sql("""select total_cost/quantity
|
||||
current_bom_unitcost = frappe.db.sql("""select total_variable_cost/quantity
|
||||
from `tabBOM` where name = %s""", self.current_bom)
|
||||
current_bom_unitcost = current_bom_unitcost and flt(current_bom_unitcost[0][0]) or 0
|
||||
frappe.db.sql("""update `tabBOM Item` set bom_no=%s,
|
||||
|
@ -123,3 +123,5 @@ cur_frm.set_query("bom_no", function(doc) {
|
||||
}
|
||||
} else msgprint(__("Please enter Production Item first"));
|
||||
});
|
||||
|
||||
cur_frm.add_fetch('bom_no', 'total_fixed_cost', 'total_fixed_cost');
|
@ -1,257 +1,264 @@
|
||||
{
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-01-10 16:34:16",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-01-10 16:34:16",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "item",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Item",
|
||||
"options": "icon-gift",
|
||||
"fieldname": "item",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Item",
|
||||
"options": "icon-gift",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"default": "PRO-",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Series",
|
||||
"options": "PRO-",
|
||||
"permlevel": 0,
|
||||
"default": "PRO-",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Series",
|
||||
"options": "PRO-",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nDraft\nSubmitted\nStopped\nIn Process\nCompleted\nCancelled",
|
||||
"permlevel": 0,
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nDraft\nSubmitted\nStopped\nIn Process\nCompleted\nCancelled",
|
||||
"permlevel": 0,
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "production_item",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Item To Manufacture",
|
||||
"oldfieldname": "production_item",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Item",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"fieldname": "production_item",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Item To Manufacture",
|
||||
"oldfieldname": "production_item",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Item",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"depends_on": "production_item",
|
||||
"description": "Bill of Material to be considered for manufacturing",
|
||||
"fieldname": "bom_no",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "BOM No",
|
||||
"oldfieldname": "bom_no",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "BOM",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"depends_on": "production_item",
|
||||
"description": "Bill of Material to be considered for manufacturing",
|
||||
"fieldname": "bom_no",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "BOM No",
|
||||
"oldfieldname": "bom_no",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "BOM",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"description": "If checked, BOM for sub-assembly items will be considered for getting raw materials. Otherwise, all sub-assembly items will be treated as a raw material.",
|
||||
"fieldname": "use_multi_level_bom",
|
||||
"fieldtype": "Check",
|
||||
"label": "Use Multi-Level BOM",
|
||||
"default": "1",
|
||||
"description": "If checked, BOM for sub-assembly items will be considered for getting raw materials. Otherwise, all sub-assembly items will be treated as a raw material.",
|
||||
"fieldname": "use_multi_level_bom",
|
||||
"fieldtype": "Check",
|
||||
"label": "Use Multi-Level BOM",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"oldfieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"oldfieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "Manufacture against Sales Order",
|
||||
"fieldname": "sales_order",
|
||||
"fieldtype": "Link",
|
||||
"label": "Sales Order",
|
||||
"options": "Sales Order",
|
||||
"permlevel": 0,
|
||||
"description": "Manufacture against Sales Order",
|
||||
"fieldname": "sales_order",
|
||||
"fieldtype": "Link",
|
||||
"label": "Sales Order",
|
||||
"options": "Sales Order",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"depends_on": "production_item",
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Qty To Manufacture",
|
||||
"oldfieldname": "qty",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"depends_on": "production_item",
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Qty To Manufacture",
|
||||
"oldfieldname": "qty",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.docstatus==1",
|
||||
"description": "Automatically updated via Stock Entry of type Manufacture/Repack",
|
||||
"fieldname": "produced_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Manufactured Qty",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "produced_qty",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "sales_order",
|
||||
"fieldname": "expected_delivery_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Expected Delivery Date",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "warehouses",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Warehouses",
|
||||
"options": "icon-building",
|
||||
"depends_on": "production_item",
|
||||
"fieldname": "total_fixed_cost",
|
||||
"fieldtype": "Float",
|
||||
"label": "Total Fixed Cost",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"depends_on": "production_item",
|
||||
"description": "Manufactured quantity will be updated in this warehouse",
|
||||
"fieldname": "fg_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 0,
|
||||
"label": "For Warehouse",
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_12",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "wip_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"label": "Work-in-Progress Warehouse",
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "more_info",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "More Info",
|
||||
"options": "icon-file-text",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Item Description",
|
||||
"permlevel": 0,
|
||||
"depends_on": "eval:doc.docstatus==1",
|
||||
"description": "Automatically updated via Stock Entry of type Manufacture/Repack",
|
||||
"fieldname": "produced_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Manufactured Qty",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "produced_qty",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "project_name",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"label": "Project Name",
|
||||
"oldfieldname": "project_name",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Project",
|
||||
"permlevel": 0,
|
||||
"depends_on": "sales_order",
|
||||
"fieldname": "expected_delivery_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Expected Delivery Date",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "warehouses",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Warehouses",
|
||||
"options": "icon-building",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "production_item",
|
||||
"description": "Manufactured quantity will be updated in this warehouse",
|
||||
"fieldname": "fg_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 0,
|
||||
"label": "For Warehouse",
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_12",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "wip_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"label": "Work-in-Progress Warehouse",
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "more_info",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "More Info",
|
||||
"options": "icon-file-text",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break2",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Item Description",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "project_name",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"label": "Project Name",
|
||||
"oldfieldname": "project_name",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Project",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break2",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
},
|
||||
{
|
||||
"depends_on": "production_item",
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "Stock UOM",
|
||||
"oldfieldname": "stock_uom",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"depends_on": "production_item",
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "Stock UOM",
|
||||
"oldfieldname": "stock_uom",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"oldfieldname": "company",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"oldfieldname": "company",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Amended From",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "amended_from",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Production Order",
|
||||
"permlevel": 0,
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"label": "Amended From",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "amended_from",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Production Order",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"icon": "icon-cogs",
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-06-23 07:55:50.092300",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Order",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"icon": "icon-cogs",
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-09-15 11:45:48.591196",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Production Order",
|
||||
"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": "Manufacturing 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": "Manufacturing User",
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"apply_user_permissions": 1,
|
||||
"permlevel": 0,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"permlevel": 0,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Material User"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ class ProductionOrder(Document):
|
||||
self.validate_bom_no()
|
||||
self.validate_sales_order()
|
||||
self.validate_warehouse()
|
||||
self.set_fixed_cost()
|
||||
|
||||
from erpnext.utilities.transaction_base import validate_uom_is_integer
|
||||
validate_uom_is_integer(self, "stock_uom", ["qty", "produced_qty"])
|
||||
@ -55,6 +56,10 @@ class ProductionOrder(Document):
|
||||
for w in [self.fg_warehouse, self.wip_warehouse]:
|
||||
validate_warehouse_company(w, self.company)
|
||||
|
||||
def set_fixed_cost(self):
|
||||
if self.total_fixed_cost==None:
|
||||
self.total_fixed_cost = frappe.db.get_value("BOM", self.bom_no, "total_fixed_cost")
|
||||
|
||||
def validate_production_order_against_so(self):
|
||||
# already ordered qty
|
||||
ordered_qty_against_so = frappe.db.sql("""select sum(qty) from `tabProduction Order`
|
||||
@ -156,11 +161,10 @@ def get_item_details(item):
|
||||
return {}
|
||||
|
||||
res = res[0]
|
||||
bom = frappe.db.sql("""select name from `tabBOM` where item=%s
|
||||
and ifnull(is_default, 0)=1""", item)
|
||||
bom = frappe.db.sql("""select name as bom_no,total_fixed_cost from `tabBOM` where item=%s
|
||||
and ifnull(is_default, 0)=1""", item, as_dict=1)
|
||||
if bom:
|
||||
res.bom_no = bom[0][0]
|
||||
|
||||
res.update(bom[0])
|
||||
return res
|
||||
|
||||
@frappe.whitelist()
|
||||
|
@ -54,5 +54,4 @@ class TestProductionOrder(unittest.TestCase):
|
||||
|
||||
self.assertRaises(StockOverProductionError, s.submit)
|
||||
|
||||
|
||||
test_records = frappe.get_test_records('Production Order')
|
||||
test_records = frappe.get_test_records('Production Order')
|
@ -153,7 +153,6 @@ class ProductionPlanningTool(Document):
|
||||
pi.so_pending_qty = flt(p['pending_qty'])
|
||||
pi.planned_qty = flt(p['pending_qty'])
|
||||
|
||||
|
||||
def validate_data(self):
|
||||
self.validate_company()
|
||||
for d in self.get('pp_details'):
|
||||
|
10
erpnext/manufacturing/doctype/workstation/test_records.json
Normal file
10
erpnext/manufacturing/doctype/workstation/test_records.json
Normal file
@ -0,0 +1,10 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Workstation",
|
||||
"name": "_Test Workstation 1",
|
||||
"workstation_name": "_Test Workstation 1",
|
||||
"warehouse": "_Test warehouse - _TC",
|
||||
"fixed_cycle_cost": 1000,
|
||||
"hour_rate":100
|
||||
}
|
||||
]
|
@ -0,0 +1,12 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and Contributors
|
||||
# See license.txt
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
test_dependencies = ["Warehouse"]
|
||||
test_records = frappe.get_test_records('Workstation')
|
||||
|
||||
|
||||
class TestWorkstation(unittest.TestCase):
|
||||
pass
|
@ -1,155 +1,161 @@
|
||||
{
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:workstation_name",
|
||||
"creation": "2013-01-10 16:34:17",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:workstation_name",
|
||||
"creation": "2013-01-10 16:34:17",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "workstation_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Workstation Name",
|
||||
"oldfieldname": "workstation_name",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"fieldname": "workstation_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Workstation Name",
|
||||
"oldfieldname": "workstation_name",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Warehouse",
|
||||
"oldfieldname": "warehouse",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Warehouse",
|
||||
"oldfieldname": "warehouse",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Description",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text",
|
||||
"permlevel": 0,
|
||||
"width": "300px"
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "capacity",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Capacity",
|
||||
"oldfieldname": "capacity",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"fieldname": "capacity",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Capacity",
|
||||
"oldfieldname": "capacity",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "capacity_units",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Capacity Units",
|
||||
"oldfieldname": "capacity_units",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nUnits/Shifts\nUnits/Hour",
|
||||
"permlevel": 0,
|
||||
"fieldname": "capacity_units",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Capacity Units",
|
||||
"oldfieldname": "capacity_units",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nUnits/Shifts\nUnits/Hour",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "hour_rate_labour",
|
||||
"fieldtype": "Float",
|
||||
"label": "Hour Rate Labour",
|
||||
"oldfieldname": "hour_rate_labour",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"fieldname": "fixed_cycle_cost",
|
||||
"fieldtype": "Float",
|
||||
"label": "Fixed Cycle Cost",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "hour_rate_labour",
|
||||
"fieldtype": "Float",
|
||||
"label": "Hour Rate Labour",
|
||||
"oldfieldname": "hour_rate_labour",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"reqd": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "over_heads",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Overheads",
|
||||
"oldfieldtype": "Section Break",
|
||||
"fieldname": "over_heads",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Overheads",
|
||||
"oldfieldtype": "Section Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "Electricity cost per hour",
|
||||
"fieldname": "hour_rate_electricity",
|
||||
"fieldtype": "Float",
|
||||
"label": "Electricity Cost",
|
||||
"oldfieldname": "hour_rate_electricity",
|
||||
"oldfieldtype": "Currency",
|
||||
"description": "Electricity cost per hour",
|
||||
"fieldname": "hour_rate_electricity",
|
||||
"fieldtype": "Float",
|
||||
"label": "Electricity Cost",
|
||||
"oldfieldname": "hour_rate_electricity",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "Consumable cost per hour",
|
||||
"fieldname": "hour_rate_consumable",
|
||||
"fieldtype": "Float",
|
||||
"label": "Consumable Cost",
|
||||
"oldfieldname": "hour_rate_consumable",
|
||||
"oldfieldtype": "Currency",
|
||||
"description": "Consumable cost per hour",
|
||||
"fieldname": "hour_rate_consumable",
|
||||
"fieldtype": "Float",
|
||||
"label": "Consumable Cost",
|
||||
"oldfieldname": "hour_rate_consumable",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "Rent per hour",
|
||||
"fieldname": "hour_rate_rent",
|
||||
"fieldtype": "Float",
|
||||
"label": "Rent Cost",
|
||||
"oldfieldname": "hour_rate_rent",
|
||||
"oldfieldtype": "Currency",
|
||||
"description": "Rent per hour",
|
||||
"fieldname": "hour_rate_rent",
|
||||
"fieldtype": "Float",
|
||||
"label": "Rent Cost",
|
||||
"oldfieldname": "hour_rate_rent",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "overhead",
|
||||
"fieldtype": "Float",
|
||||
"label": "Overhead",
|
||||
"oldfieldname": "overhead",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"fieldname": "overhead",
|
||||
"fieldtype": "Float",
|
||||
"label": "Overhead",
|
||||
"oldfieldname": "overhead",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "hour_rate_section_break",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Hour Rate",
|
||||
"oldfieldtype": "Section Break",
|
||||
"fieldname": "hour_rate_section_break",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Hour Rate",
|
||||
"oldfieldtype": "Section Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": "Hour Rate",
|
||||
"oldfieldname": "hour_rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"fieldname": "hour_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": "Hour Rate",
|
||||
"oldfieldname": "hour_rate",
|
||||
"oldfieldtype": "Currency",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"icon": "icon-wrench",
|
||||
"idx": 1,
|
||||
"modified": "2014-05-27 03:49:22.635046",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Workstation",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"icon": "icon-wrench",
|
||||
"idx": 1,
|
||||
"modified": "2014-09-15 10:59:07.960814",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Workstation",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"apply_user_permissions": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Manufacturing User",
|
||||
"submit": 0,
|
||||
"apply_user_permissions": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Manufacturing User",
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -80,3 +80,4 @@ execute:frappe.delete_doc("DocType", "Landed Cost Wizard")
|
||||
erpnext.patches.v4_2.default_website_style
|
||||
erpnext.patches.v4_2.set_company_country
|
||||
erpnext.patches.v4_2.update_sales_order_invoice_field_name
|
||||
erpnext.patches.v4_2.cost_of_production_cycle
|
9
erpnext/patches/v4_2/cost_of_production_cycle.py
Normal file
9
erpnext/patches/v4_2/cost_of_production_cycle.py
Normal file
@ -0,0 +1,9 @@
|
||||
# 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")
|
||||
frappe.db.sql("""update tabBOM set total_variable_cost = total_cost""")
|
@ -3,6 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
|
||||
def execute(filters=None):
|
||||
@ -12,9 +13,9 @@ def execute(filters=None):
|
||||
filters["from_time"] = "00:00:00"
|
||||
filters["to_time"] = "24:00:00"
|
||||
|
||||
columns = ["Time Log:Link/Time Log:120", "Employee::150", "From Datetime::140",
|
||||
"To Datetime::140", "Hours::70", "Activity Type::120", "Task:Link/Task:150",
|
||||
"Task Subject::180", "Project:Link/Project:120", "Status::70"]
|
||||
columns = [_("Time Log") + ":Link/Time Log:120", _("Employee") + "::150", _("From Datetime") + "::140",
|
||||
_("To Datetime") + "::140", _("Hours") + "::70", _("Activity Type") + "::120", _("Task") + ":Link/Task:150",
|
||||
_("Task Subject") + "::180", _("Project") + ":Link/Project:120", _("Status") + "::70"]
|
||||
|
||||
user_map = get_user_map()
|
||||
task_map = get_task_map()
|
||||
|
@ -1,7 +1,8 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import frappe
|
||||
import frappe
|
||||
from frappe import _
|
||||
|
||||
def execute(filters=None):
|
||||
columns = get_columns()
|
||||
@ -21,11 +22,11 @@ def execute(filters=None):
|
||||
return columns, data
|
||||
|
||||
def get_columns():
|
||||
return ["Project Id:Link/Project:140", "Cost of Purchased Items:Currency:160",
|
||||
"Cost of Issued Items:Currency:160", "Cost of Delivered Items:Currency:160",
|
||||
"Project Name::120", "Project Status::120", "Company:Link/Company:100",
|
||||
"Customer:Link/Customer:140", "Project Value:Currency:120",
|
||||
"Project Start Date:Date:120", "Completion Date:Date:120"]
|
||||
return [_("Project Id") + ":Link/Project:140", _("Cost of Purchased Items") + ":Currency:160",
|
||||
_("Cost of Issued Items") + ":Currency:160", _("Cost of Delivered Items") + ":Currency:160",
|
||||
_("Project Name") + "::120", _("Project Status") + "::120", _("Company") + ":Link/Company:100",
|
||||
_("Customer") + ":Link/Customer:140", _("Project Value") + ":Currency:120",
|
||||
_("Project Start Date") + ":Date:120", _("Completion Date") + ":Date:120"]
|
||||
|
||||
def get_project_details():
|
||||
return frappe.db.sql(""" select name, project_name, status, company, customer, project_value,
|
||||
|
@ -7,21 +7,36 @@ var get_filters = function(){
|
||||
"fieldname":"period",
|
||||
"label": __("Period"),
|
||||
"fieldtype": "Select",
|
||||
"options": ["Monthly", "Quarterly", "Half-Yearly", "Yearly"].join("\n"),
|
||||
"options": [
|
||||
{ "value": "Monthly", "label": __("Monthly") },
|
||||
{ "value": "Quarterly", "label": __("Quarterly") },
|
||||
{ "value": "Half-Yearly", "label": __("Half-Yearly") },
|
||||
{ "value": "Yearly", "label": __("Yearly") }
|
||||
],
|
||||
"default": "Monthly"
|
||||
},
|
||||
{
|
||||
"fieldname":"based_on",
|
||||
"label": __("Based On"),
|
||||
"fieldtype": "Select",
|
||||
"options": ["Item", "Item Group", "Supplier", "Supplier Type", "Project"].join("\n"),
|
||||
"options": [
|
||||
{ "value": "Item", "label": __("Item") },
|
||||
{ "value": "Item Group", "label": __("Item Group") },
|
||||
{ "value": "Supplier", "label": __("Supplier") },
|
||||
{ "value": "Supplier Type", "label": __("Supplier Type") },
|
||||
{ "value": "Supplier Type", "label": __("Project") }
|
||||
],
|
||||
"default": "Item"
|
||||
},
|
||||
{
|
||||
"fieldname":"group_by",
|
||||
"label": __("Group By"),
|
||||
"fieldtype": "Select",
|
||||
"options": ["", "Item", "Supplier"].join("\n"),
|
||||
"options": [
|
||||
"",
|
||||
{ "value": "Item", "label": __("Item") },
|
||||
{ "value": "Supplier", "label": __("Supplier") }
|
||||
],
|
||||
"default": ""
|
||||
},
|
||||
{
|
||||
|
@ -7,21 +7,37 @@ var get_filters = function(){
|
||||
"fieldname":"period",
|
||||
"label": __("Period"),
|
||||
"fieldtype": "Select",
|
||||
"options": ["Monthly", "Quarterly", "Half-Yearly", "Yearly"].join("\n"),
|
||||
"options": [
|
||||
{ "value": "Monthly", "label": __("Monthly") },
|
||||
{ "value": "Quarterly", "label": __("Quarterly") },
|
||||
{ "value": "Half-Yearly", "label": __("Half-Yearly") },
|
||||
{ "value": "Yearly", "label": __("Yearly") }
|
||||
],
|
||||
"default": "Monthly"
|
||||
},
|
||||
{
|
||||
"fieldname":"based_on",
|
||||
"label": __("Based On"),
|
||||
"fieldtype": "Select",
|
||||
"options": ["Item", "Item Group", "Customer", "Customer Group", "Territory", "Project"].join("\n"),
|
||||
"options": [
|
||||
{ "value": "Item", "label": __("Item") },
|
||||
{ "value": "Item Group", "label": __("Item Group") },
|
||||
{ "value": "Customer", "label": __("Customer") },
|
||||
{ "value": "Customer Group", "label": __("Customer Group") },
|
||||
{ "value": "Territory", "label": __("Territory") },
|
||||
{ "value": "Supplier Type", "label": __("Project") }
|
||||
],
|
||||
"default": "Item"
|
||||
},
|
||||
{
|
||||
"fieldname":"group_by",
|
||||
"label": __("Group By"),
|
||||
"fieldtype": "Select",
|
||||
"options": ["", "Item", "Customer"].join("\n"),
|
||||
"options": [
|
||||
"",
|
||||
{ "value": "Item", "label": __("Item") },
|
||||
{ "value": "Customer", "label": __("Customer") }
|
||||
],
|
||||
"default": ""
|
||||
},
|
||||
{
|
||||
|
@ -282,7 +282,7 @@
|
||||
],
|
||||
"icon": "icon-user",
|
||||
"idx": 1,
|
||||
"modified": "2014-08-07 06:57:25.248707",
|
||||
"modified": "2014-09-10 16:41:07.553182",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Customer",
|
||||
@ -309,6 +309,14 @@
|
||||
"read": 1,
|
||||
"role": "Sales User"
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Sales Manager"
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"create": 1,
|
||||
@ -330,6 +338,38 @@
|
||||
"read": 1,
|
||||
"role": "Sales Master Manager",
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Material User"
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Material Manager"
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User"
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager"
|
||||
}
|
||||
],
|
||||
"search_fields": "customer_name,customer_group,territory",
|
||||
|
@ -22,5 +22,13 @@
|
||||
"customer_type": "Individual",
|
||||
"doctype": "Customer",
|
||||
"territory": "_Test Territory"
|
||||
},
|
||||
{
|
||||
"company": "_Test Company",
|
||||
"customer_group": "_Test Customer Group",
|
||||
"customer_name": "_Test Customer 3",
|
||||
"customer_type": "Individual",
|
||||
"doctype": "Customer",
|
||||
"territory": "_Test Territory"
|
||||
}
|
||||
]
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"allow_import": 1,
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"creation": "2013-05-24 19:29:08",
|
||||
"docstatus": 0,
|
||||
@ -832,7 +832,7 @@
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"max_attachments": 1,
|
||||
"modified": "2014-08-12 05:04:36.157045",
|
||||
"modified": "2014-09-09 05:35:33.413559",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Quotation",
|
||||
|
@ -332,7 +332,7 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-09-08 08:06:31.198440",
|
||||
"modified": "2014-09-09 05:35:36.871532",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Quotation Item",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -326,6 +326,11 @@ def make_delivery_note(source_name, target_doc=None):
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_sales_invoice(source_name, target_doc=None):
|
||||
def postprocess(source, target):
|
||||
set_missing_values(source, target)
|
||||
#Get the advance paid Journal Vouchers in Sales Invoice Advance
|
||||
target.get_advances()
|
||||
|
||||
def set_missing_values(source, target):
|
||||
target.is_pos = 0
|
||||
target.ignore_pricing_rule = 1
|
||||
@ -361,7 +366,18 @@ def make_sales_invoice(source_name, target_doc=None):
|
||||
"doctype": "Sales Team",
|
||||
"add_if_empty": True
|
||||
}
|
||||
}, target_doc, set_missing_values)
|
||||
}, 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
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
[
|
||||
{
|
||||
"advance_paid": 0.0,
|
||||
"company": "_Test Company",
|
||||
"conversion_rate": 1.0,
|
||||
"currency": "INR",
|
||||
|
@ -415,7 +415,7 @@
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2014-09-08 08:06:31.435020",
|
||||
"modified": "2014-09-09 05:35:37.173841",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order Item",
|
||||
|
@ -8,7 +8,7 @@ pscript['onload_Sales Browser'] = function(wrapper){
|
||||
|
||||
wrapper.appframe.add_module_icon("Selling")
|
||||
|
||||
wrapper.appframe.set_title_right('Refresh', function() {
|
||||
wrapper.appframe.set_title_right(__('Refresh'), function() {
|
||||
wrapper.make_tree();
|
||||
});
|
||||
|
||||
@ -44,7 +44,7 @@ pscript['onshow_Sales Browser'] = function(wrapper){
|
||||
// set route
|
||||
var ctype = frappe.get_route()[1] || 'Territory';
|
||||
|
||||
wrapper.appframe.set_title(ctype+' Tree')
|
||||
wrapper.appframe.set_title(__('{0} Tree',[__(ctype)]));
|
||||
|
||||
if(erpnext.sales_chart && erpnext.sales_chart.ctype != ctype) {
|
||||
wrapper.make_tree();
|
||||
@ -64,7 +64,7 @@ erpnext.SalesChart = Class.extend({
|
||||
|
||||
this.tree = new frappe.ui.Tree({
|
||||
parent: $(parent),
|
||||
label: root,
|
||||
label: __(root),
|
||||
args: {ctype: ctype},
|
||||
method: 'erpnext.selling.page.sales_browser.sales_browser.get_children',
|
||||
toolbar: [
|
||||
@ -112,20 +112,20 @@ erpnext.SalesChart = Class.extend({
|
||||
|
||||
var fields = [
|
||||
{fieldtype:'Data', fieldname: 'name_field',
|
||||
label:'New ' + me.ctype + ' Name', reqd:true},
|
||||
{fieldtype:'Select', fieldname:'is_group', label:'Group Node', options:'No\nYes',
|
||||
label:__('New {0} Name',[__(me.ctype)]), reqd:true},
|
||||
{fieldtype:'Select', fieldname:'is_group', label:__('Group Node'), options:'No\nYes',
|
||||
description: __("Further nodes can be only created under 'Group' type nodes")},
|
||||
{fieldtype:'Button', fieldname:'create_new', label:'Create New' }
|
||||
{fieldtype:'Button', fieldname:'create_new', label:__('Create New') }
|
||||
]
|
||||
|
||||
if(me.ctype == "Sales Person") {
|
||||
fields.splice(-1, 0, {fieldtype:'Link', fieldname:'employee', label:'Employee',
|
||||
fields.splice(-1, 0, {fieldtype:'Link', fieldname:'employee', label:__('Employee'),
|
||||
options:'Employee', description: __("Please enter Employee Id of this sales parson")});
|
||||
}
|
||||
|
||||
// the dialog
|
||||
var d = new frappe.ui.Dialog({
|
||||
title: __('New ') + __(me.ctype),
|
||||
title: __('New {0}',[__(me.ctype)]),
|
||||
fields: fields
|
||||
})
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user