[cleanup] form dashboards

This commit is contained in:
Rushabh Mehta 2016-07-07 14:02:26 +05:30
parent 964ad0fcae
commit ea0ff23891
9 changed files with 98 additions and 84 deletions

View File

@ -3,9 +3,6 @@ from frappe import _
data = { data = {
'docstatus': 1, 'docstatus': 1,
'fieldname': 'request_for_quotation', 'fieldname': 'request_for_quotation',
# 'non_standard_fieldnames': {
# 'Purchase Order': 'prevdoc_detail_docname',
# },
'transactions': [ 'transactions': [
{ {
'label': _('Related Documents'), 'label': _('Related Documents'),

View File

@ -173,6 +173,7 @@ class AccountsController(TransactionBase):
ret = get_item_details(args) ret = get_item_details(args)
for fieldname, value in ret.items(): for fieldname, value in ret.items():
if item.meta.get_field(fieldname) and value is not None: if item.meta.get_field(fieldname) and value is not None:
if (item.get(fieldname) is None or fieldname in force_item_fields): if (item.get(fieldname) is None or fieldname in force_item_fields):
@ -279,7 +280,7 @@ class AccountsController(TransactionBase):
def set_advances(self): def set_advances(self):
"""Returns list of advances against Account, Party, Reference""" """Returns list of advances against Account, Party, Reference"""
res = self.get_advance_entries() res = self.get_advance_entries()
self.set("advances", []) self.set("advances", [])
@ -293,7 +294,7 @@ class AccountsController(TransactionBase):
"advance_amount": flt(d.amount), "advance_amount": flt(d.amount),
"allocated_amount": flt(d.amount) if d.against_order else 0 "allocated_amount": flt(d.amount) if d.against_order else 0
}) })
def get_advance_entries(self, include_unallocated=True): def get_advance_entries(self, include_unallocated=True):
if self.doctype == "Sales Invoice": if self.doctype == "Sales Invoice":
party_account = self.debit_to party_account = self.debit_to
@ -309,36 +310,36 @@ class AccountsController(TransactionBase):
amount_field = "debit_in_account_currency" amount_field = "debit_in_account_currency"
order_field = "purchase_order" order_field = "purchase_order"
order_doctype = "Purchase Order" order_doctype = "Purchase Order"
order_list = list(set([d.get(order_field) order_list = list(set([d.get(order_field)
for d in self.get("items") if d.get(order_field)])) for d in self.get("items") if d.get(order_field)]))
journal_entries = get_advance_journal_entries(party_type, party, party_account, journal_entries = get_advance_journal_entries(party_type, party, party_account,
amount_field, order_doctype, order_list, include_unallocated) amount_field, order_doctype, order_list, include_unallocated)
payment_entries = get_advance_payment_entries(party_type, party, party_account, payment_entries = get_advance_payment_entries(party_type, party, party_account,
order_doctype, order_list, include_unallocated) order_doctype, order_list, include_unallocated)
res = journal_entries + payment_entries res = journal_entries + payment_entries
return res return res
def validate_advance_entries(self): def validate_advance_entries(self):
order_field = "sales_order" if self.doctype == "Sales Invoice" else "purchase_order" order_field = "sales_order" if self.doctype == "Sales Invoice" else "purchase_order"
order_list = list(set([d.get(order_field) order_list = list(set([d.get(order_field)
for d in self.get("items") if d.get(order_field)])) for d in self.get("items") if d.get(order_field)]))
if not order_list: return if not order_list: return
advance_entries = self.get_advance_entries(include_unallocated=False) advance_entries = self.get_advance_entries(include_unallocated=False)
if advance_entries: if advance_entries:
advance_entries_against_si = [d.reference_name for d in self.get("advances")] advance_entries_against_si = [d.reference_name for d in self.get("advances")]
for d in advance_entries: for d in advance_entries:
if not advance_entries_against_si or d.reference_name not in advance_entries_against_si: if not advance_entries_against_si or d.reference_name not in advance_entries_against_si:
frappe.msgprint(_("Payment Entry {0} is linked against Order {1}, check if it should be pulled as advance in this invoice.") frappe.msgprint(_("Payment Entry {0} is linked against Order {1}, check if it should be pulled as advance in this invoice.")
.format(d.reference_name, d.against_order)) .format(d.reference_name, d.against_order))
def update_against_document_in_jv(self): def update_against_document_in_jv(self):
""" """
Links invoice and advance voucher: Links invoice and advance voucher:
@ -346,7 +347,7 @@ class AccountsController(TransactionBase):
2. split into multiple rows if partially adjusted, assign against voucher 2. split into multiple rows if partially adjusted, assign against voucher
3. submit advance voucher 3. submit advance voucher
""" """
if self.doctype == "Sales Invoice": if self.doctype == "Sales Invoice":
party_type = "Customer" party_type = "Customer"
party = self.customer party = self.customer
@ -374,14 +375,14 @@ class AccountsController(TransactionBase):
'dr_or_cr' : dr_or_cr, 'dr_or_cr' : dr_or_cr,
'unadjusted_amount' : flt(d.advance_amount), 'unadjusted_amount' : flt(d.advance_amount),
'allocated_amount' : flt(d.allocated_amount), 'allocated_amount' : flt(d.allocated_amount),
'exchange_rate': (self.conversion_rate 'exchange_rate': (self.conversion_rate
if self.party_account_currency != self.company_currency else 1), if self.party_account_currency != self.company_currency else 1),
'grand_total': (self.base_grand_total 'grand_total': (self.base_grand_total
if self.party_account_currency==self.company_currency else self.grand_total), if self.party_account_currency==self.company_currency else self.grand_total),
'outstanding_amount': self.outstanding_amount 'outstanding_amount': self.outstanding_amount
}) })
lst.append(args) lst.append(args)
if lst: if lst:
from erpnext.accounts.utils import reconcile_against_document from erpnext.accounts.utils import reconcile_against_document
reconcile_against_document(lst) reconcile_against_document(lst)
@ -467,7 +468,7 @@ class AccountsController(TransactionBase):
if self.currency == self.company_currency and advance_paid > order_total: if self.currency == self.company_currency and advance_paid > order_total:
frappe.throw(_("Total advance ({0}) against Order {1} cannot be greater than the Grand Total ({2})") frappe.throw(_("Total advance ({0}) against Order {1} cannot be greater than the Grand Total ({2})")
.format(formatted_advance_paid, self.name, formatted_order_total)) .format(formatted_advance_paid, self.name, formatted_order_total))
frappe.db.set_value(self.doctype, self.name, "advance_paid", advance_paid) frappe.db.set_value(self.doctype, self.name, "advance_paid", advance_paid)
@property @property
@ -646,11 +647,11 @@ def set_balance_in_account_currency(gl_dict, account_currency=None, conversion_r
else flt(gl_dict.credit / conversion_rate, 2) else flt(gl_dict.credit / conversion_rate, 2)
def get_advance_journal_entries(party_type, party, party_account, amount_field, def get_advance_journal_entries(party_type, party, party_account, amount_field,
order_doctype, order_list, include_unallocated=True): order_doctype, order_list, include_unallocated=True):
dr_or_cr = "credit_in_account_currency" if party_type=="Customer" else "debit_in_account_currency" dr_or_cr = "credit_in_account_currency" if party_type=="Customer" else "debit_in_account_currency"
conditions = [] conditions = []
if include_unallocated: if include_unallocated:
conditions.append("ifnull(t2.reference_name, '')=''") conditions.append("ifnull(t2.reference_name, '')=''")
@ -659,12 +660,12 @@ def get_advance_journal_entries(party_type, party, party_account, amount_field,
order_condition = ', '.join(['%s'] * len(order_list)) order_condition = ', '.join(['%s'] * len(order_list))
conditions.append(" (t2.reference_type = '{0}' and ifnull(t2.reference_name, '') in ({1}))"\ conditions.append(" (t2.reference_type = '{0}' and ifnull(t2.reference_name, '') in ({1}))"\
.format(order_doctype, order_condition)) .format(order_doctype, order_condition))
reference_condition = " and (" + " or ".join(conditions) + ")" if conditions else "" reference_condition = " and (" + " or ".join(conditions) + ")" if conditions else ""
journal_entries = frappe.db.sql(""" journal_entries = frappe.db.sql("""
select select
"Journal Entry" as reference_type, t1.name as reference_name, "Journal Entry" as reference_type, t1.name as reference_name,
t1.remark as remarks, t2.{0} as amount, t2.name as reference_row, t1.remark as remarks, t2.{0} as amount, t2.name as reference_row,
t2.reference_name as against_order t2.reference_name as against_order
from from
@ -677,10 +678,10 @@ def get_advance_journal_entries(party_type, party, party_account, amount_field,
and (ifnull(t2.reference_name, '')='' {2}) and (ifnull(t2.reference_name, '')='' {2})
order by t1.posting_date""".format(amount_field, dr_or_cr, reference_condition), order by t1.posting_date""".format(amount_field, dr_or_cr, reference_condition),
[party_account, party_type, party] + order_list, as_dict=1) [party_account, party_type, party] + order_list, as_dict=1)
return list(journal_entries) return list(journal_entries)
def get_advance_payment_entries(party_type, party, party_account, def get_advance_payment_entries(party_type, party, party_account,
order_doctype, order_list=None, include_unallocated=True, against_all_orders=False): order_doctype, order_list=None, include_unallocated=True, against_all_orders=False):
party_account_field = "paid_from" if party_type == "Customer" else "paid_to" party_account_field = "paid_from" if party_type == "Customer" else "paid_to"
payment_type = "Receive" if party_type == "Customer" else "Pay" payment_type = "Receive" if party_type == "Customer" else "Pay"
@ -693,28 +694,28 @@ def get_advance_payment_entries(party_type, party, party_account,
else: else:
reference_condition = "" reference_condition = ""
order_list = [] order_list = []
payment_entries_against_order = frappe.db.sql(""" payment_entries_against_order = frappe.db.sql("""
select select
"Payment Entry" as reference_type, t1.name as reference_name, "Payment Entry" as reference_type, t1.name as reference_name,
t1.remarks, t2.allocated_amount as amount, t2.name as reference_row, t1.remarks, t2.allocated_amount as amount, t2.name as reference_row,
t2.reference_name as against_order, t1.posting_date t2.reference_name as against_order, t1.posting_date
from `tabPayment Entry` t1, `tabPayment Entry Reference` t2 from `tabPayment Entry` t1, `tabPayment Entry Reference` t2
where where
t1.name = t2.parent and t1.{0} = %s and t1.payment_type = %s t1.name = t2.parent and t1.{0} = %s and t1.payment_type = %s
and t1.party_type = %s and t1.party = %s and t1.docstatus = 1 and t1.party_type = %s and t1.party = %s and t1.docstatus = 1
and t2.reference_doctype = %s {1} and t2.reference_doctype = %s {1}
""".format(party_account_field, reference_condition), """.format(party_account_field, reference_condition),
[party_account, payment_type, party_type, party, order_doctype] + order_list, as_dict=1) [party_account, payment_type, party_type, party, order_doctype] + order_list, as_dict=1)
if include_unallocated: if include_unallocated:
unallocated_payment_entries = frappe.db.sql(""" unallocated_payment_entries = frappe.db.sql("""
select "Payment Entry" as reference_type, name as reference_name, select "Payment Entry" as reference_type, name as reference_name,
remarks, unallocated_amount as amount remarks, unallocated_amount as amount
from `tabPayment Entry` from `tabPayment Entry`
where where
{0} = %s and party_type = %s and party = %s and payment_type = %s {0} = %s and party_type = %s and party = %s and payment_type = %s
and docstatus = 1 and unallocated_amount > 0 and docstatus = 1 and unallocated_amount > 0
""".format(party_account_field), (party_account, party_type, party, payment_type), as_dict=1) """.format(party_account_field), (party_account, party_type, party, payment_type), as_dict=1)
return list(payment_entries_against_order) + list(unallocated_payment_entries) return list(payment_entries_against_order) + list(unallocated_payment_entries)

View File

@ -28,7 +28,7 @@ class BuyingController(StockController):
super(BuyingController, self).validate() super(BuyingController, self).validate()
if getattr(self, "supplier", None) and not self.supplier_name: if getattr(self, "supplier", None) and not self.supplier_name:
self.supplier_name = frappe.db.get_value("Supplier", self.supplier, "supplier_name") self.supplier_name = frappe.db.get_value("Supplier", self.supplier, "supplier_name")
self.is_item_table_empty()
self.set_qty_as_per_stock_uom() self.set_qty_as_per_stock_uom()
self.validate_stock_or_nonstock_items() self.validate_stock_or_nonstock_items()
self.validate_warehouse() self.validate_warehouse()
@ -129,7 +129,7 @@ class BuyingController(StockController):
valuation_amount_adjustment -= item.item_tax_amount valuation_amount_adjustment -= item.item_tax_amount
self.round_floats_in(item) self.round_floats_in(item)
if flt(item.conversion_factor)==0: if flt(item.conversion_factor)==0.0:
item.conversion_factor = get_conversion_factor(item.item_code, item.uom).get("conversion_factor") or 1.0 item.conversion_factor = get_conversion_factor(item.item_code, item.uom).get("conversion_factor") or 1.0
qty_in_stock_uom = flt(item.qty * item.conversion_factor) qty_in_stock_uom = flt(item.qty * item.conversion_factor)
@ -276,10 +276,6 @@ class BuyingController(StockController):
return self._sub_contracted_items return self._sub_contracted_items
def is_item_table_empty(self):
if not len(self.get("items")):
frappe.throw(_("Item table can not be blank"))
def set_qty_as_per_stock_uom(self): def set_qty_as_per_stock_uom(self):
for d in self.get("items"): for d in self.get("items"):
if d.meta.get_field("stock_qty"): if d.meta.get_field("stock_qty"):

View File

@ -4,7 +4,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe.utils import flt, comma_or from frappe.utils import flt, comma_or
from frappe import msgprint, _, throw from frappe import _
from frappe.model.document import Document from frappe.model.document import Document
def validate_status(status, options): def validate_status(status, options):
@ -135,15 +135,12 @@ class StatusUpdater(Document):
item['idx'] = d.idx item['idx'] = d.idx
item['target_ref_field'] = args['target_ref_field'].replace('_', ' ') item['target_ref_field'] = args['target_ref_field'].replace('_', ' ')
if not item[args['target_ref_field']]: # if not item[args['target_ref_field']]:
msgprint(_("Note: System will not check over-delivery and over-booking for Item {0} as quantity or amount is 0").format(item.item_code)) # msgprint(_("Note: System will not check over-delivery and over-booking for Item {0} as quantity or amount is 0").format(item.item_code))
elif args.get('no_tolerance'): if args.get('no_tolerance'):
item['reduce_by'] = item[args['target_field']] - item[args['target_ref_field']] item['reduce_by'] = item[args['target_field']] - item[args['target_ref_field']]
if item['reduce_by'] > .01: if item['reduce_by'] > .01:
msgprint(_("Allowance for over-{0} crossed for Item {1}") self.limits_crossed_error(args, item)
.format(args["overflow_type"], item.item_code))
throw(_("{0} must be reduced by {1} or you should increase overflow tolerance")
.format(_(item.target_ref_field.title()), item["reduce_by"]))
else: else:
self.check_overflow_with_tolerance(item, args) self.check_overflow_with_tolerance(item, args)
@ -162,10 +159,20 @@ class StatusUpdater(Document):
item['max_allowed'] = flt(item[args['target_ref_field']] * (100+tolerance)/100) item['max_allowed'] = flt(item[args['target_ref_field']] * (100+tolerance)/100)
item['reduce_by'] = item[args['target_field']] - item['max_allowed'] item['reduce_by'] = item[args['target_field']] - item['max_allowed']
msgprint(_("Allowance for over-{0} crossed for Item {1}.") self.limits_crossed_error(args, item)
.format(args["overflow_type"], item["item_code"]))
throw(_("{0} must be reduced by {1} or you should increase overflow tolerance") def limits_crossed_error(self, args, item):
.format(_(item["target_ref_field"].title()), item["reduce_by"])) '''Raise exception for limits crossed'''
frappe.throw(_('This document is over limit by {0} {1} for item {4}. Are you making another {3} against the same {2}?')
.format(
frappe.bold(_(item["target_ref_field"].title())),
frappe.bold(item["reduce_by"]),
frappe.bold(_(args.get('target_dt'))),
frappe.bold(_(self.doctype)),
frappe.bold(item.get('item_code'))
) + '<br><br>' +
_('To allow over-billing or over-ordering, update "Allowance" in Stock Settings or the Item.'),
title = _('Limit Crossed'))
def update_qty(self, update_modified=True): def update_qty(self, update_modified=True):
"""Updates qty or amount at row level """Updates qty or amount at row level

View File

@ -92,7 +92,8 @@
"image": null, "image": null,
"item_code": "Base Plate", "item_code": "Base Plate",
"item_group": "Raw Material", "item_group": "Raw Material",
"item_name": "Base Plate" "item_name": "Base Plate",
"is_sub_contracted_item": 1
}, },
{ {
"default_supplier": "Scott Ties", "default_supplier": "Scott Ties",

View File

@ -4,7 +4,7 @@ import frappe, sys
import erpnext import erpnext
import frappe.utils import frappe.utils
from erpnext.demo.setup_data import setup_data from erpnext.demo.setup_data import setup_data
from erpnext.demo.user import hr, sales from erpnext.demo.user import hr, sales, purchase
def make(domain='Manufacturing'): def make(domain='Manufacturing'):
frappe.flags.domain = domain frappe.flags.domain = domain
@ -42,7 +42,7 @@ def simulate():
hr.work() hr.work()
sales.work() sales.work()
# run_purchase() purchase.work()
# run_manufacturing() # run_manufacturing()
# run_stock() # run_stock()
# run_accounts() # run_accounts()

View File

@ -300,3 +300,8 @@ def setup_user_roles():
user = frappe.get_doc('User', 'GabrielleLoftus@example.com') user = frappe.get_doc('User', 'GabrielleLoftus@example.com')
user.add_roles('Sales User', 'Sales Manager', 'Accounts User') user.add_roles('Sales User', 'Sales Manager', 'Accounts User')
frappe.db.set_global('demo_sales_user_2', user.name) frappe.db.set_global('demo_sales_user_2', user.name)
if not frappe.db.get_global('demo_purchase_user'):
user = frappe.get_doc('User', 'MichalSobczak@example.com')
user.add_roles('Purchase User', 'Purchase Manager', 'Accounts User')
frappe.db.set_global('demo_purchase_user', user.name)

View File

@ -4,7 +4,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe, random import frappe, random
from frappe.utils.make_random import how_many, can_make, get_random from frappe.utils.make_random import how_many, get_random
from frappe.desk import query_report from frappe.desk import query_report
from erpnext.setup.utils import get_exchange_rate from erpnext.setup.utils import get_exchange_rate
from erpnext.accounts.party import get_party_account_currency from erpnext.accounts.party import get_party_account_currency
@ -13,30 +13,40 @@ from erpnext.stock.doctype.material_request.material_request import make_request
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import \ from erpnext.buying.doctype.request_for_quotation.request_for_quotation import \
make_supplier_quotation as make_quotation_from_rfq make_supplier_quotation as make_quotation_from_rfq
def run_purchase(current_date): def work():
frappe.set_user(frappe.db.get_global('demo_purchase_user'))
if random.random() < 0.3: if random.random() < 0.3:
report = "Items To Be Requested" report = "Items To Be Requested"
for row in query_report.run(report)["result"][:how_many("Material Request")]: for row in query_report.run(report)["result"][:random.randint(1, 5)]:
item_code, qty = row[0], abs(row[-1]) item_code, qty = row[0], abs(row[-1])
mr = make_material_request(item_code, qty) mr = make_material_request(item_code, qty)
if random.random() < 0.3: if random.random() < 0.3:
for mr in frappe.get_all('Material Request', filters={'material_request_type': 'Purchase', 'status': 'Open'}): for mr in frappe.get_all('Material Request',
rfq = make_request_for_quotation(mr.name) filters={'material_request_type': 'Purchase', 'status': 'Open'},
rfq.transaction_date = frappe.flags.current_date limit=random.randint(1,6)):
add_suppliers(rfq) if not frappe.get_all('Request for Quotation',
rfq.save() filters={'material_request': mr.name}, limit=1):
rfq.submit() rfq = make_request_for_quotation(mr.name)
rfq.transaction_date = frappe.flags.current_date
add_suppliers(rfq)
rfq.save()
rfq.submit()
# Make suppier quotation from RFQ against each supplier. # Make suppier quotation from RFQ against each supplier.
if random.random() < 0.3: if random.random() < 0.3:
for supplier_quotation in frappe.get_all('Request for Quotation', {'status': 'Open'}): for rfq in frappe.get_all('Request for Quotation',
rfq = frappe.get_doc('Request for Quotation', rfq.name) filters={'status': 'Open'}, limit=random.randint(1, 6)):
for supplier in rfq.suppliers: if not frappe.get_all('Supplier Quotation',
supplier_quotation = make_quotation_from_rfq(rfq.name, supplier.supplier) filters={'request_for_quotation': rfq.name}, limit=1):
supplier_quotation.save() rfq = frappe.get_doc('Request for Quotation', rfq.name)
supplier_quotation.submit()
for supplier in rfq.suppliers:
supplier_quotation = make_quotation_from_rfq(rfq.name, supplier.supplier)
supplier_quotation.save()
supplier_quotation.submit()
# get supplier details # get supplier details
supplier = get_random("Supplier") supplier = get_random("Supplier")
@ -49,14 +59,14 @@ def run_purchase(current_date):
exchange_rate = get_exchange_rate(party_account_currency, company_currency) exchange_rate = get_exchange_rate(party_account_currency, company_currency)
# make supplier quotations # make supplier quotations
if can_make("Supplier Quotation"): if random.random() < 0.3:
from erpnext.stock.doctype.material_request.material_request import make_supplier_quotation from erpnext.stock.doctype.material_request.material_request import make_supplier_quotation
report = "Material Requests for which Supplier Quotations are not created" report = "Material Requests for which Supplier Quotations are not created"
for row in query_report.run(report)["result"][:how_many("Supplier Quotation")]: for row in query_report.run(report)["result"][:how_many("Supplier Quotation")]:
if row[0] != "'Total'": if row[0] != "'Total'":
sq = frappe.get_doc(make_supplier_quotation(row[0])) sq = frappe.get_doc(make_supplier_quotation(row[0]))
sq.transaction_date = current_date sq.transaction_date = frappe.flags.current_date
sq.supplier = supplier sq.supplier = supplier
sq.currency = party_account_currency or company_currency sq.currency = party_account_currency or company_currency
sq.conversion_rate = exchange_rate sq.conversion_rate = exchange_rate
@ -65,7 +75,7 @@ def run_purchase(current_date):
frappe.db.commit() frappe.db.commit()
# make purchase orders # make purchase orders
if can_make("Purchase Order"): if random.random() < 0.3:
from erpnext.stock.doctype.material_request.material_request import make_purchase_order from erpnext.stock.doctype.material_request.material_request import make_purchase_order
report = "Requested Items To Be Ordered" report = "Requested Items To Be Ordered"
for row in query_report.run(report)["result"][:how_many("Purchase Order")]: for row in query_report.run(report)["result"][:how_many("Purchase Order")]:
@ -74,13 +84,13 @@ def run_purchase(current_date):
po.supplier = supplier po.supplier = supplier
po.currency = party_account_currency or company_currency po.currency = party_account_currency or company_currency
po.conversion_rate = exchange_rate po.conversion_rate = exchange_rate
po.transaction_date = current_date po.transaction_date = frappe.flags.current_date
po.insert() po.insert()
po.submit() po.submit()
frappe.db.commit() frappe.db.commit()
if can_make("Subcontract"): if random.random() < 0.3:
make_subcontract(current_date) make_subcontract()
def make_material_request(item_code, qty): def make_material_request(item_code, qty):
mr = frappe.new_doc("Material Request") mr = frappe.new_doc("Material Request")

View File

@ -3,9 +3,6 @@ from frappe import _
data = { data = {
'docstatus': 1, 'docstatus': 1,
'fieldname': 'material_request', 'fieldname': 'material_request',
'non_standard_fieldnames': {
'Purchase Order': 'prevdoc_detail_docname',
},
'transactions': [ 'transactions': [
{ {
'label': _('Related Documents'), 'label': _('Related Documents'),