Compare commits

...

65 Commits

Author SHA1 Message Date
Nabin Hait
6a8d7a1b91 Merge branch 'develop' 2015-06-16 16:50:49 +05:30
Nabin Hait
5d71a28e97 bumped to version 5.0.25 2015-06-16 17:20:49 +06:00
Nabin Hait
7d100a1ee7 Merge pull request #3480 from nabinhait/develop
Indexes
2015-06-16 16:49:26 +05:30
Nabin Hait
81dca110eb Change log added 2015-06-16 16:48:47 +05:30
Nabin Hait
9c852108d0 Added index in sales/purchase invoice and fix in index patch 2015-06-16 16:48:47 +05:30
Nabin Hait
e3ac032696 Merge pull request #3472 from neilLasrado/po
Multiple Fixes
2015-06-16 15:52:48 +05:30
Neil Trini Lasrado
64cacfb077 Fixes in Activity Cost 2015-06-16 15:42:40 +05:30
Neil Trini Lasrado
ae4cc078ea Activity Cost - Mandatory removed for Employee. 2015-06-16 15:30:08 +05:30
Nabin Hait
0ee543e932 Merge pull request #3479 from nabinhait/develop
[fix][report] Payment period based on invoice date
2015-06-16 15:29:14 +05:30
Nabin Hait
a123638d37 [fix][report] Payment period based on invoice date 2015-06-16 15:21:00 +05:30
Nabin Hait
58996985ed Merge pull request #3476 from nabinhait/develop
Expense Approver Query and discount label
2015-06-16 15:01:08 +05:30
Nabin Hait
5d0ce7939f Show only users with Expense Approver role in Expense Claim Approver field 2015-06-15 17:59:37 +05:30
Neil Trini Lasrado
4abf552d7b Over Production Allowance Percentage Setting added to Manufacturing Settings 2015-06-15 15:58:45 +05:30
Nabin Hait
7c5ba957ac Label changed for discount amount in base currency 2015-06-15 15:47:07 +05:30
Nabin Hait
77f04e293a Merge branch 'develop' 2015-06-15 10:35:39 +05:30
Nabin Hait
d1d3237784 bumped to version 5.0.24 2015-06-15 11:05:39 +06:00
Nabin Hait
76f0d26f1e Merge pull request #3471 from nabinhait/develop
Hotfix
2015-06-15 10:32:23 +05:30
Nabin Hait
65922d3079 [fix] supplier invoice date can not be after posting date 2015-06-15 10:23:53 +05:30
Nabin Hait
810041cbe3 [fix] Fixed error due to performance upgrade cleanup 2015-06-15 10:20:11 +05:30
Nabin Hait
b9626659ea Merge pull request #3465 from neilLasrado/po
Po
2015-06-15 10:04:36 +05:30
Nabin Hait
e3d13bee36 Merge pull request #3467 from anandpdoshi/anand-june-12
Fixes
2015-06-15 10:03:20 +05:30
Nabin Hait
13bd538aca Merge branch 'develop' 2015-06-14 22:04:51 +05:30
Nabin Hait
d72a24965b bumped to version 5.0.23 2015-06-14 22:34:51 +06:00
Nabin Hait
dc633fe360 Merge pull request #3470 from nabinhait/develop
Performance upgrade in reports and indexing
2015-06-14 22:01:30 +05:30
Nabin Hait
39046d663d [patch] Add index on Account and GL Entry table 2015-06-14 20:59:28 +05:30
Nabin Hait
6b01abe9ad [report][performance] Speed increased by approx 10 times in Trial Balance, General Ledger, AR/AP, Balance Sheet and P&L Statement 2015-06-14 20:59:28 +05:30
Anand Doshi
63e4d31aa6 [fix] Task should be mandatory in Time Log only when Project is mentioned but Production Order is not 2015-06-12 18:59:18 -04:00
Anand Doshi
f2a0161709 [fix] Don't create Time Logs against Production Order if Workstation is not specified in Operations 2015-06-12 18:58:36 -04:00
Neil Trini Lasrado
3c1a4a0b9b percent_complete made no-copy in Project 2015-06-12 18:34:08 +05:30
Neil Trini Lasrado
82cc2921d1 Validation added to prevent user from creating salary structure with 'From Date' before employee 'Date of joining' 2015-06-12 18:34:08 +05:30
Nabin Hait
87edd86854 Merge branch 'develop' 2015-06-12 18:06:21 +05:30
Nabin Hait
e37dd77923 bumped to version 5.0.22 2015-06-12 18:36:21 +06:00
Nabin Hait
e4f689184f Merge pull request #3459 from neilLasrado/po
Multiple Fixes.
2015-06-12 17:55:23 +05:30
Nabin Hait
85f825e98c Merge pull request #3463 from nabinhait/develop
multiple issues
2015-06-12 17:48:54 +05:30
Nabin Hait
89592c5180 Load tasks in project for printing purpose 2015-06-12 17:37:28 +05:30
Neil Trini Lasrado
587bd144d5 Added Customers Not Buying Since Long Time against Sales Invoice 2015-06-11 18:36:52 +05:30
Neil Trini Lasrado
1f048b2426 Fixes in Activity Cost 2015-06-11 18:36:52 +05:30
Neil Trini Lasrado
1792ff3be7 Validation added in Purchase Invoice to check if Supplier Invoice Date is greater than Posting Date
Check Supplier Invoice Number Uniqueness setting added to Accounts Settings
Validation added in Purchase Invoice to check Supplier Invoice Number Uniqueness if Check Supplier Invoice Number Uniqueness is enabled in Accounts Settings
2015-06-11 18:36:52 +05:30
Neil Trini Lasrado
fc595064e0 validation added to prevent Delivery Date in Porduction Order to be lesser than Planned Start Date 2015-06-11 18:36:52 +05:30
Nabin Hait
804b4acb9b [fix] Issue fixed in C-Form related to field renaming 2015-06-11 16:56:36 +05:30
Nabin Hait
5c7557914b Removed BOM No from mandatory from Stock Entry against Production Order 2015-06-11 16:50:35 +05:30
Nabin Hait
381a9377d9 Merge branch 'develop' 2015-06-11 16:14:48 +05:30
Nabin Hait
9bdd1aa1ed bumped to version 5.0.21 2015-06-11 16:44:48 +06:00
Nabin Hait
d0df28bfa0 Merge pull request #3458 from nabinhait/develop
[fix] load tasks in project via __setup__ instead of onload function, to return tasks via get_doc
2015-06-11 16:12:05 +05:30
Nabin Hait
1966225450 [fix] load tasks in project via __setup__ instead of onload function, to return tasks via get_doc 2015-06-11 15:31:47 +05:30
Nabin Hait
4cee27eec0 Merge pull request #3446 from anandpdoshi/anand-june-9
POS - search by Item Group
2015-06-10 18:42:14 +05:30
Nabin Hait
c7d4eaee79 Merge pull request #3442 from nabinhait/develop
fixes in stock entry and report
2015-06-10 18:40:42 +05:30
Nabin Hait
43c1a9b502 [fix] Quote url for item image in product listing page 2015-06-10 18:23:17 +05:30
Nabin Hait
b937fac3ce [report] Warehouse column added in 'Ordered Items to be Delivered' report 2015-06-10 18:21:57 +05:30
Nabin Hait
53d94996ad [fix] Query for Against Journal Entry 2015-06-10 18:20:18 +05:30
Anand Doshi
26f6752c1e POS - search by Item Group 2015-06-09 16:33:46 -04:00
Nabin Hait
bb429745c0 [fix] Blank option in naming series 2015-06-09 18:59:51 +05:30
Nabin Hait
909f0c38f1 [report][enhancement] Payment period based on invoice date: show party columns and filter based on party 2015-06-09 18:42:52 +05:30
Nabin Hait
a790ba05f4 [fix] Item name, description should not be overwritten on saving of stock entry 2015-06-09 18:42:52 +05:30
Nabin Hait
11fc4f85d0 Merge branch 'develop' 2015-06-09 15:56:20 +05:30
Nabin Hait
17452a1695 bumped to version 5.0.20 2015-06-09 16:26:20 +06:00
Nabin Hait
7c3d48e353 Merge pull request #3434 from neilLasrado/material-request
Status Indicators fixed in Material Request List
2015-06-09 15:47:46 +05:30
Neil Trini Lasrado
5d288e407c item variants patch removed 2015-06-09 15:46:57 +05:30
Neil Trini Lasrado
f64fae752f fixes 2015-06-09 15:46:57 +05:30
Neil Trini Lasrado
82763f052f Status Indicators fixed in Material Request List 2015-06-09 15:46:57 +05:30
Nabin Hait
bafc73568a Merge pull request #3435 from neilLasrado/barcode
Barcode added to Purchase Receipt
2015-06-09 15:44:09 +05:30
Neil Trini Lasrado
d015195617 fixes in barcode 2015-06-09 15:21:50 +05:30
Neil Trini Lasrado
b2f550ccb3 Barcode added to Purchase Receipt 2015-06-09 15:18:58 +05:30
Nabin Hait
41413af42d Merge pull request #3437 from anandpdoshi/task-close-assignment
[fix] Close assignment (ToDo) when Task status is changed to Closed
2015-06-09 15:00:06 +05:30
Anand Doshi
ec60ebde6f [fix] Close assignment (ToDo) when Task status is changed to Closed 2015-06-08 12:48:11 -04:00
54 changed files with 1370 additions and 1151 deletions

View File

@@ -1,2 +1,2 @@
from __future__ import unicode_literals
__version__ = '5.0.19'
__version__ = '5.0.25'

View File

@@ -35,7 +35,7 @@
"permlevel": 0,
"read_only": 1,
"reqd": 1,
"search_index": 1
"search_index": 0
},
{
"default": "0",
@@ -44,7 +44,7 @@
"label": "Is Group",
"permlevel": 0,
"precision": "",
"search_index": 1
"search_index": 0
},
{
"fieldname": "company",
@@ -57,7 +57,7 @@
"permlevel": 0,
"read_only": 1,
"reqd": 1,
"search_index": 1
"search_index": 0
},
{
"fieldname": "root_type",
@@ -147,7 +147,8 @@
"label": "Lft",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "rgt",
@@ -156,7 +157,8 @@
"label": "Rgt",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "old_parent",
@@ -171,7 +173,7 @@
"icon": "icon-money",
"idx": 1,
"in_create": 0,
"modified": "2015-05-28 14:10:40.606010",
"modified": "2015-06-14 20:57:55.471334",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",

View File

@@ -4,6 +4,13 @@
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"fieldname": "check_supplier_invoice_uniqueness",
"fieldtype": "Check",
"label": "Check Supplier Invoice Number Uniqueness",
"permlevel": 0,
"precision": ""
},
{
"default": "1",
"description": "If enabled, the system will post accounting entries for inventory automatically.",
@@ -43,7 +50,7 @@
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"modified": "2015-02-05 05:11:34.163902",
"modified": "2015-06-11 06:06:34.047890",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

View File

@@ -54,7 +54,7 @@ class CForm(Document):
frappe.throw(_("Please enter atleast 1 invoice in the table"))
def set_total_invoiced_amount(self):
total = sum([flt(d.base_grand_total) for d in self.get('invoices')])
total = sum([flt(d.grand_total) for d in self.get('invoices')])
frappe.db.set(self, 'total_invoiced_amount', total)
def get_invoice_details(self, invoice_no):

View File

@@ -48,7 +48,8 @@
"fieldtype": "Dynamic Link",
"label": "Party",
"options": "party_type",
"permlevel": 0
"permlevel": 0,
"search_index": 1
},
{
"fieldname": "cost_center",
@@ -192,7 +193,7 @@
"icon": "icon-list",
"idx": 1,
"in_create": 1,
"modified": "2015-04-27 20:32:48.246818",
"modified": "2015-06-14 20:57:19.800276",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",

View File

@@ -458,11 +458,11 @@ def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None):
if voucher_type=="Bank Entry":
account = frappe.db.get_value("Company", company, "default_bank_account")
if not account:
account = frappe.db.get_value("Account", {"company": company, "account_type": "Bank"})
account = frappe.db.get_value("Account", {"company": company, "account_type": "Bank", "is_group": 0})
elif voucher_type=="Cash Entry":
account = frappe.db.get_value("Company", company, "default_cash_account")
if not account:
account = frappe.db.get_value("Account", {"company": company, "account_type": "Cash"})
account = frappe.db.get_value("Account", {"company": company, "account_type": "Cash", "is_group": 0})
if account:
return {
@@ -538,15 +538,13 @@ def get_opening_accounts(company):
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
if not filters.get("party"):
return []
return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
where jv_detail.parent = jv.name and jv_detail.account = %s and jv_detail.party = %s
where jv_detail.parent = jv.name and jv_detail.account = %s and ifnull(jv_detail.party, '') = %s
and (ifnull(jv_detail.against_invoice, '') = '' and ifnull(jv_detail.against_voucher, '') = ''
and ifnull(jv_detail.against_jv, '') = '' )
and jv.docstatus = 1 and jv.{0} like %s order by jv.name desc limit %s, %s""".format(searchfield),
(filters["account"], filters["party"], "%{0}%".format(txt), start, page_len))
(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
@frappe.whitelist()
def get_outstanding(args):

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cint, formatdate, flt
from frappe.utils import cint, formatdate, flt, getdate
from frappe import msgprint, _, throw
from erpnext.setup.utils import get_company_currency
import frappe.defaults
@@ -39,6 +39,7 @@ class PurchaseInvoice(BuyingController):
self.po_required()
self.pr_required()
self.validate_supplier_invoice()
self.check_active_purchase_items()
self.check_conversion_rate()
self.validate_credit_to_acc()
@@ -385,6 +386,16 @@ class PurchaseInvoice(BuyingController):
project.update_purchase_costing()
project.save()
project_list.append(d.project_name)
def validate_supplier_invoice(self):
if self.bill_date:
if getdate(self.bill_date) > getdate(self.posting_date):
frappe.throw("Supplier Invoice Date cannot be greater than Posting Date")
if self.bill_no:
if cint(frappe.db.get_single_value("Accounts Settings", "check_supplier_invoice_uniqueness")):
pi = frappe.db.exists("Purchase Invoice", {"bill_no": self.bill_no, "fiscal_year": self.fiscal_year})
if pi:
frappe.throw("Supplier Invoice No exists in Purchase Invoice {0}".format(pi))
@frappe.whitelist()
def get_expense_account(doctype, txt, searchfield, start, page_len, filters):

View File

@@ -7,6 +7,7 @@ import frappe
@frappe.whitelist()
def get_items(price_list, sales_or_purchase, item=None):
condition = ""
order_by = ""
args = {"price_list": price_list}
if sales_or_purchase == "Sales":
@@ -30,16 +31,25 @@ def get_items(price_list, sales_or_purchase, item=None):
item_code[0]["barcode"] = item
return item_code
condition += " and (CONCAT(i.name, i.item_name) like %(name)s or (i.variant_of like %(name)s))"
condition += " and ((CONCAT(i.name, i.item_name) like %(name)s) or (i.variant_of like %(name)s) or (i.item_group like %(name)s))"
order_by = """if(locate(%(_name)s, i.name), locate(%(_name)s, i.name), 99999),
if(locate(%(_name)s, i.item_name), locate(%(_name)s, i.item_name), 99999),
if(locate(%(_name)s, i.variant_of), locate(%(_name)s, i.variant_of), 99999),
if(locate(%(_name)s, i.item_group), locate(%(_name)s, i.item_group), 99999),"""
args["name"] = "%%%s%%" % item
args["_name"] = item.replace("%", "")
# locate function is used to sort by closest match from the beginning of the value
return frappe.db.sql("""select i.name, i.item_name, i.image,
item_det.price_list_rate, item_det.currency
from `tabItem` i LEFT JOIN
(select item_code, price_list_rate, currency from
`tabItem Price` where price_list=%s) item_det
`tabItem Price` where price_list=%(price_list)s) item_det
ON
(item_det.item_code=i.name or item_det.item_code=i.variant_of)
where
ifnull(i.has_variants, 0) = 0 and
%s""" % ('%(price_list)s', condition), args, as_dict=1)
{condition}
order by
{order_by}
i.name""".format(condition=condition, order_by=order_by), args, as_dict=1)

View File

@@ -38,7 +38,8 @@
"options": "Customer",
"permlevel": 0,
"print_hide": 1,
"read_only": 0
"read_only": 0,
"search_index": 1
},
{
"depends_on": "customer",
@@ -502,7 +503,7 @@
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
@@ -880,7 +881,7 @@
"options": "Project",
"permlevel": 0,
"read_only": 0,
"search_index": 1
"search_index": 0
},
{
"depends_on": "eval:doc.source == 'Campaign'",
@@ -1243,7 +1244,7 @@
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2015-05-27 02:48:02.897865",
"modified": "2015-06-16 16:45:06.618286",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -65,8 +65,7 @@ class SalesInvoice(SellingController):
self.set_against_income_account()
self.validate_c_form()
self.validate_time_logs_are_submitted()
self.validate_multiple_billing("Delivery Note", "dn_detail", "amount",
"items")
self.validate_multiple_billing("Delivery Note", "dn_detail", "amount", "items")
def on_submit(self):
super(SalesInvoice, self).on_submit()

View File

@@ -51,7 +51,7 @@ class ReceivablePayableReport(object):
currency_precision = get_currency_precision() or 2
dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"
voucher_details = self.get_voucher_details()
voucher_details = self.get_voucher_details(args.get("party_type"))
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
@@ -153,23 +153,26 @@ class ReceivablePayableReport(object):
return self.party_map
def get_voucher_details(self):
def get_voucher_details(self, party_type):
voucher_details = frappe._dict()
if party_type == "Customer":
for si in frappe.db.sql("""select name, due_date
from `tabSales Invoice` where docstatus=1""", as_dict=1):
voucher_details.setdefault(si.name, si)
for si in frappe.db.sql("""select name, due_date
from `tabSales Invoice` where docstatus=1""", as_dict=1):
voucher_details.setdefault(si.name, si)
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
from `tabPurchase Invoice` where docstatus=1""", as_dict=1):
voucher_details.setdefault(pi.name, pi)
if party_type == "Supplier":
for pi in frappe.db.sql("""select name, due_date, bill_no, bill_date
from `tabPurchase Invoice` where docstatus=1""", as_dict=1):
voucher_details.setdefault(pi.name, pi)
return voucher_details
def get_gl_entries(self, party_type):
if not hasattr(self, "gl_entries"):
conditions, values = self.prepare_conditions(party_type)
self.gl_entries = frappe.db.sql("""select * from `tabGL Entry`
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party, debit, credit,
voucher_type, voucher_no, against_voucher_type, against_voucher from `tabGL Entry`
where docstatus < 2 and party_type=%s {0} order by posting_date, party"""
.format(conditions), values, as_dict=True)
@@ -187,7 +190,7 @@ class ReceivablePayableReport(object):
if self.filters.get(party_type_field):
conditions.append("party=%s")
values.append(self.filters.get(party_type_field))
values.append(self.filters.get(party_type_field))
return " and ".join(conditions), values

View File

@@ -83,7 +83,7 @@ def get_data(company, root_type, balance_must_be, period_list, ignore_closing_en
gl_entries_by_account = get_gl_entries(company, period_list[0]["from_date"], period_list[-1]["to_date"],
accounts[0].lft, accounts[0].rgt, ignore_closing_entries=ignore_closing_entries)
calculate_values(accounts, gl_entries_by_account, period_list)
calculate_values(accounts_by_name, gl_entries_by_account, period_list)
accumulate_values_into_parents(accounts, accounts_by_name, period_list)
out = prepare_data(accounts, balance_must_be, period_list)
@@ -92,16 +92,14 @@ def get_data(company, root_type, balance_must_be, period_list, ignore_closing_en
return out
def calculate_values(accounts, gl_entries_by_account, period_list):
for d in accounts:
for name in ([d.name] + (d.collapsed_children or [])):
for entry in gl_entries_by_account.get(name, []):
for period in period_list:
entry.posting_date = getdate(entry.posting_date)
# check if posting date is within the period
if entry.posting_date <= period.to_date:
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
def calculate_values(accounts_by_name, gl_entries_by_account, period_list):
for entries in gl_entries_by_account.values():
for entry in entries:
d = accounts_by_name.get(entry.account)
for period in period_list:
# check if posting date is within the period
if entry.posting_date <= period.to_date:
d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
def accumulate_values_into_parents(accounts, accounts_by_name, period_list):
@@ -159,22 +157,8 @@ def add_total_row(out, balance_must_be, period_list):
out.append({})
def get_accounts(company, root_type):
# root lft, rgt
root_account = frappe.db.sql("""select lft, rgt from `tabAccount`
where company=%s and root_type=%s and ifnull(parent_account, '') = ''
order by lft limit 1""",
(company, root_type), as_dict=True)
if not root_account:
return None
lft, rgt = root_account[0].lft, root_account[0].rgt
accounts = frappe.db.sql("""select * from `tabAccount`
where company=%(company)s and lft >= %(lft)s and rgt <= %(rgt)s order by lft""",
{ "company": company, "lft": lft, "rgt": rgt }, as_dict=True)
return accounts
return frappe.db.sql("""select name, parent_account, lft, rgt, root_type, report_type, account_name from `tabAccount`
where company=%s and root_type=%s order by lft""", (company, root_type), as_dict=True)
def filter_accounts(accounts, depth=10):
parent_children_map = {}
@@ -196,14 +180,6 @@ def filter_accounts(accounts, depth=10):
filtered_accounts.append(child)
add_to_list(child.name, level + 1)
else:
# include all children at level lower than the depth
parent_account = accounts_by_name[parent]
parent_account["collapsed_children"] = []
for d in accounts:
if d.lft > parent_account.lft and d.rgt < parent_account.rgt:
parent_account["collapsed_children"].append(d.name)
add_to_list(None, 0)
return filtered_accounts, accounts_by_name
@@ -234,7 +210,7 @@ def get_gl_entries(company, from_date, to_date, root_lft, root_rgt, ignore_closi
if from_date:
additional_conditions.append("and posting_date >= %(from_date)s")
gl_entries = frappe.db.sql("""select * from `tabGL Entry`
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit from `tabGL Entry`
where company=%(company)s
{additional_conditions}
and posting_date <= %(to_date)s

View File

@@ -66,7 +66,7 @@ def get_gl_entries(filters):
gl_entries = frappe.db.sql("""select posting_date, account, party_type, party,
sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit,
voucher_type, voucher_no, cost_center, remarks, is_opening, against
voucher_type, voucher_no, cost_center, remarks, against
from `tabGL Entry`
where company=%(company)s {conditions}
{group_by_condition}
@@ -91,6 +91,9 @@ def get_conditions(filters):
if filters.get("party"):
conditions.append("party=%(party)s")
if not (filters.get("account") or filters.get("party") or filters.get("group_by_account")):
conditions.append("posting_date >=%(from_date)s")
from frappe.desk.reportview import build_match_conditions
match_conditions = build_match_conditions("GL Entry")
@@ -148,14 +151,15 @@ def initialize_gle_map(gl_entries):
def get_accountwise_gle(filters, gl_entries, gle_map):
opening, total_debit, total_credit = 0, 0, 0
from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
for gle in gl_entries:
amount = flt(gle.debit, 3) - flt(gle.credit, 3)
if gle.posting_date < getdate(filters.from_date):
if (filters.get("account") or filters.get("party") or filters.get("group_by_account")) \
and gle.posting_date < from_date:
gle_map[gle.account].opening += amount
if filters.get("account") or filters.get("party"):
opening += amount
elif gle.posting_date <= getdate(filters.to_date):
elif gle.posting_date <= to_date:
gle_map[gle.account].entries.append(gle)
gle_map[gle.account].total_debit += flt(gle.debit, 3)
gle_map[gle.account].total_credit += flt(gle.credit, 3)

View File

@@ -3,6 +3,14 @@
frappe.query_reports["Payment Period Based On Invoice Date"] = {
"filters": [
{
fieldname:"company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_user_default("company")
},
{
fieldname: "from_date",
label: __("From Date"),
@@ -23,27 +31,28 @@ frappe.query_reports["Payment Period Based On Invoice Date"] = {
default: "Incoming"
},
{
fieldname:"account",
label: __("Account"),
fieldtype: "Link",
options: "Account",
get_query: function() {
"fieldname":"party_type",
"label": __("Party Type"),
"fieldtype": "Link",
"options": "DocType",
"get_query": function() {
return {
query: "erpnext.controllers.queries.get_account_list",
filters: {
"report_type": "Balance Sheet",
company: frappe.query_report.filters_by_name.company.get_value()
}
filters: {"name": ["in", ["Customer", "Supplier"]]}
}
}
},
{
fieldname:"company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_user_default("company")
"fieldname":"party",
"label": __("Party"),
"fieldtype": "Dynamic Link",
"get_options": function() {
var party_type = frappe.query_report.filters_by_name.party_type.get_value();
var party = frappe.query_report.filters_by_name.party.get_value();
if(party && !party_type) {
frappe.throw(__("Please select Party Type first"));
}
return party_type;
}
},
]
}

View File

@@ -9,8 +9,9 @@ from frappe.utils import flt
def execute(filters=None):
if not filters: filters = {}
columns = get_columns()
validate_filters(filters)
columns = get_columns(filters)
entries = get_entries(filters)
invoice_posting_date_map = get_invoice_posting_date_map(filters)
against_date = ""
@@ -20,67 +21,72 @@ def execute(filters=None):
for d in entries:
if d.against_voucher:
against_date = d.against_voucher and invoice_posting_date_map[d.against_voucher] or ""
outstanding_amount = flt(d.debit) or -1 * flt(d.credit)
payment_amount = flt(d.debit) or -1 * flt(d.credit)
else:
against_date = d.against_invoice and invoice_posting_date_map[d.against_invoice] or ""
outstanding_amount = flt(d.credit) or -1 * flt(d.debit)
payment_amount = flt(d.credit) or -1 * flt(d.debit)
row = [d.name, d.account, d.posting_date, d.against_voucher or d.against_invoice,
row = [d.name, d.party_type, d.party, d.posting_date, d.against_voucher or d.against_invoice,
against_date, d.debit, d.credit, d.cheque_no, d.cheque_date, d.remark]
if d.against_voucher or d.against_invoice:
row += get_ageing_data(30, 60, 90, d.posting_date, against_date, outstanding_amount)
row += get_ageing_data(30, 60, 90, d.posting_date, against_date, payment_amount)
else:
row += ["", "", "", "", ""]
data.append(row)
return columns, data
def validate_filters(filters):
if (filters.get("payment_type") == "Incoming" and filters.get("party_type") == "Supplier") or \
(filters.get("payment_type") == "Outgoing" and filters.get("party_type") == "Customer"):
frappe.throw(_("{0} payment entries can not be filtered by {1}")\
.format(filters.payment_type, filters.party_type))
def get_columns():
return [_("Journal Entry") + ":Link/Journal Entry:140", _("Account") + ":Link/Account:140",
_("Posting Date") + ":Date:100", _("Against Invoice") + ":Link/Purchase Invoice:130",
def get_columns(filters):
return [_("Journal Entry") + ":Link/Journal Entry:140",
_("Party Type") + ":Link/DocType:100", _("Party") + ":Dynamic Link/Party Type:140",
_("Posting Date") + ":Date:100",
_("Against Invoice") + (":Link/Purchase Invoice:130" if filters.get("payment_type") == "Outgoing" else ":Link/Sales 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):
conditions = ""
party = None
conditions = []
if filters.get("account"):
party = filters["account"]
else:
conditions += " and company = '%s'" % frappe.db.escape(filters["company"])
if not filters.get("party_type"):
if filters.get("payment_type") == "Outgoing":
filters["party_type"] = "Supplier"
else:
filters["party_type"] = "Customer"
if filters.get("party_type"):
conditions.append("jvd.party_type=%(party_type)s")
account_type = "Receivable" if filters.get("payment_type") == "Incoming" else "Payable"
if filters.get("party"):
conditions.append("jvd.party=%(party)s")
conditions += """ and account in
(select name from tabAccount
where account_type = '{0}'
and company='{1}')""".format(account_type, frappe.db.escape(filters["company"]))
if party:
conditions += " and jvd.party = '%s'" % frappe.db.escape(party)
else:
conditions += " and ifnull(jvd.party, '') != ''"
if filters.get("company"):
conditions.append("jv.company=%(company)s")
if filters.get("from_date"):
conditions += " and jv.posting_date >= '%s'" % filters["from_date"]
conditions.append("jv.posting_date >= %(from_date)s")
if filters.get("to_date"):
conditions += " and jv.posting_date <= '%s'" % filters["to_date"]
conditions.append("jv.posting_date <= %(to_date)s")
return conditions
return "and {}".format(" and ".join(conditions)) if conditions else ""
def get_entries(filters):
conditions = get_conditions(filters)
entries = frappe.db.sql("""select jv.name, jvd.account, jv.posting_date,
entries = frappe.db.sql("""select jv.name, jvd.party_type, jvd.party, jv.posting_date,
jvd.against_voucher, jvd.against_invoice, jvd.debit, jvd.credit,
jv.cheque_no, jv.cheque_date, jv.remark
from `tabJournal Entry Account` jvd, `tabJournal Entry` jv
where jvd.parent = jv.name and jv.docstatus=1 %s order by jv.name DESC""" %
conditions, as_dict=1, debug=1)
conditions, filters, as_dict=1)
return entries

View File

@@ -9,7 +9,7 @@ from erpnext.accounts.report.financial_statements import filter_accounts, get_gl
value_fields = ("opening_debit", "opening_credit", "debit", "credit", "closing_debit", "closing_credit")
def execute(filters):
def execute(filters=None):
validate_filters(filters)
data = get_data(filters)
columns = get_columns()
@@ -45,8 +45,8 @@ def validate_filters(filters):
filters.to_date = filters.year_end_date
def get_data(filters):
accounts = frappe.db.sql("""select * from `tabAccount` where company=%s order by lft""",
filters.company, as_dict=True)
accounts = frappe.db.sql("""select name, parent_account, account_name, root_type, report_type, lft, rgt
from `tabAccount` where company=%s order by lft""", filters.company, as_dict=True)
if not accounts:
return None
@@ -56,17 +56,58 @@ def get_data(filters):
min_lft, max_rgt = frappe.db.sql("""select min(lft), max(rgt) from `tabAccount`
where company=%s""", (filters.company,))[0]
gl_entries_by_account = get_gl_entries(filters.company, None, filters.to_date, min_lft, max_rgt,
gl_entries_by_account = get_gl_entries(filters.company, filters.from_date, filters.to_date, min_lft, max_rgt,
ignore_closing_entries=not flt(filters.with_period_closing_entry))
total_row = calculate_values(accounts, gl_entries_by_account, filters)
opening_balances = get_opening_balances(filters)
total_row = calculate_values(accounts, gl_entries_by_account, opening_balances, filters)
accumulate_values_into_parents(accounts, accounts_by_name)
data = prepare_data(accounts, filters, total_row)
return data
def get_opening_balances(filters):
balance_sheet_opening = get_rootwise_opening_balances(filters, "Balance Sheet")
pl_opening = get_rootwise_opening_balances(filters, "Profit and Loss")
balance_sheet_opening.update(pl_opening)
return balance_sheet_opening
def get_rootwise_opening_balances(filters, report_type):
additional_conditions = " and posting_date >= %(year_start_date)s" \
if report_type == "Profit and Loss" else ""
if not flt(filters.with_period_closing_entry):
additional_conditions += " and ifnull(voucher_type, '')!='Period Closing Voucher'"
gle = frappe.db.sql("""
select
account, sum(ifnull(debit, 0)) as opening_debit, sum(ifnull(credit, 0)) as opening_credit
from `tabGL Entry`
where
company=%(company)s
{additional_conditions}
and posting_date < %(from_date)s
and account in (select name from `tabAccount` where report_type=%(report_type)s)
group by account""".format(additional_conditions=additional_conditions),
{
"company": filters.company,
"from_date": filters.from_date,
"report_type": report_type,
"year_start_date": filters.year_start_date
},
as_dict=True)
opening = frappe._dict()
for d in gle:
opening.setdefault(d.account, d)
return opening
def calculate_values(accounts, gl_entries_by_account, filters):
def calculate_values(accounts, gl_entries_by_account, opening_balances, filters):
init = {
"opening_debit": 0.0,
"opening_credit": 0.0,
@@ -88,29 +129,15 @@ def calculate_values(accounts, gl_entries_by_account, filters):
d.update(init.copy())
for entry in gl_entries_by_account.get(d.name, []):
posting_date = getdate(entry.posting_date)
# opening
if posting_date < filters.from_date:
is_valid_opening = (d.root_type in ("Asset", "Liability", "Equity") or
(filters.year_start_date <= posting_date < filters.from_date))
if is_valid_opening:
d["opening_debit"] += flt(entry.debit)
d["opening_credit"] += flt(entry.credit)
elif posting_date <= filters.to_date:
if entry.is_opening == "Yes" and d.root_type in ("Asset", "Liability", "Equity"):
d["opening_debit"] += flt(entry.debit)
d["opening_credit"] += flt(entry.credit)
else:
d["debit"] += flt(entry.debit)
d["credit"] += flt(entry.credit)
d["debit"] += flt(entry.debit)
d["credit"] += flt(entry.credit)
total_row["debit"] += d["debit"]
total_row["credit"] += d["credit"]
# add opening
d["opening_debit"] = opening_balances.get(d.name, {}).get("opening_debit", 0)
d["opening_credit"] = opening_balances.get(d.name, {}).get("opening_credit", 0)
return total_row

View File

@@ -91,7 +91,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None):
# different filter for group and ledger - improved performance
if acc.is_group:
cond.append("""exists (
select * from `tabAccount` ac where ac.name = gle.account
select name from `tabAccount` ac where ac.name = gle.account
and ac.lft >= %s and ac.rgt <= %s
)""" % (acc.lft, acc.rgt))
else:
@@ -397,7 +397,7 @@ def get_outstanding_invoices(amount_query, account, party_type, party):
for d in outstanding_voucher_list:
payment_amount = frappe.db.sql("""
select ifnull(sum(ifnull({amount_query}, 0)), 0)
select ifnull(sum({amount_query}), 0)
from
`tabGL Entry`
where

View File

@@ -457,7 +457,7 @@
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
@@ -873,7 +873,7 @@
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2015-06-02 17:15:44.711032",
"modified": "2015-06-15 15:38:56.794601",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",

View File

@@ -439,7 +439,7 @@
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
@@ -660,7 +660,7 @@
"icon": "icon-shopping-cart",
"idx": 1,
"is_submittable": 1,
"modified": "2015-06-02 17:15:57.283516",
"modified": "2015-06-15 15:39:08.954248",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",

View File

@@ -0,0 +1,17 @@
- Performance upgrade in Trial Balance, General Ledger, AR/AP, Balance Sheet and P&L Statement reports
- Add index on Account and GL Entry, Sales Invoice and Purchase Invoice table
- Don't create Time Logs against Production Order if Workstation is not specified in Operations
- Task should be mandatory in Time Log only when Project is mentioned but Production Order is not
- Supplier invoice no unique validation and supplier invoice date can not be after posting date
- Removed BOM No from mandatory from Stock Entry against Production Order
- Load tasks in project for printing purpose
- Added Customers Not Buying Since Long Time against Sales Invoice
- POS - search by Item Group
- Payment period based on invoice date: show party columns and filter based on party
- Barcode added to Purchase Receipt
- Fetch item name and desc on change of item code in Quality Inspection
- Show item name in item grid view based 'In List View' property
- Validate and update manufactured qty in Stock Entry
- Show only users with Expense Approver role in Expense Claim Approver field
- Over Production Allowance Percentage Setting added to Manufacturing Settings
- Activity Cost - Mandatory removed for Employee

View File

@@ -5,7 +5,7 @@ app_publisher = "Frappe 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 = "5.0.19"
app_version = "5.0.25"
error_report_email = "support@erpnext.com"

View File

@@ -63,7 +63,7 @@ cur_frm.cscript.onload = function(doc,cdt,cdn) {
cur_frm.set_query("exp_approver", function() {
return {
filters: [["UserRole", "role", "=", "Expense Approver"]]
query: "erpnext.hr.doctype.expense_claim.expense_claim.get_expense_approver"
};
});
}

View File

@@ -58,4 +58,13 @@ class ExpenseClaim(Document):
def validate_sanctioned_amount(self):
for d in self.get('expenses'):
if flt(d.sanctioned_amount) > flt(d.claim_amount):
frappe.throw(_("Sanctioned Amount cannot be greater than Claim Amount in Row {0}.").format(d.idx))
frappe.throw(_("Sanctioned Amount cannot be greater than Claim Amount in Row {0}.").format(d.idx))
@frappe.whitelist()
def get_expense_approver(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""
select u.name, concat(u.first_name, ' ', u.last_name)
from tabUser u, tabUserRole r
where u.name = r.parent and r.role = 'Expense Approver' and u.name like %s
""", ("%" + txt + "%"))

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, flt
from frappe.utils import cstr, flt, getdate
from frappe.model.naming import make_autoname
from frappe import _
from frappe.model.mapper import get_mapped_doc
@@ -14,6 +14,13 @@ from erpnext.hr.utils import set_employee_name
class SalaryStructure(Document):
def autoname(self):
self.name = make_autoname(self.employee + '/.SST' + '/.#####')
def validate(self):
self.check_existing()
self.validate_amount()
self.validate_employee()
self.validate_joining_date()
set_employee_name(self)
def get_employee_details(self):
ret = {}
@@ -77,14 +84,11 @@ class SalaryStructure(Document):
old_employee = frappe.db.get_value("Salary Structure", self.name, "employee")
if old_employee and self.employee != old_employee:
frappe.throw(_("Employee can not be changed"))
def validate(self):
self.check_existing()
self.validate_amount()
self.validate_employee()
set_employee_name(self)
def validate_joining_date(self):
joining_date = getdate(frappe.db.get_value("Employee", self.employee, "date_of_joining"))
if getdate(self.from_date) < joining_date:
frappe.throw(_("From Date in Salary Structure cannot be lesser than Employee Joining Date."))
@frappe.whitelist()
def make_salary_slip(source_name, target_doc=None):

View File

@@ -55,6 +55,13 @@
"label": "Time Between Operations (in mins)",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "over_production_allowance_percentage",
"fieldtype": "Percent",
"label": "Over Production Allowance Percentage",
"permlevel": 0,
"precision": ""
}
],
"hide_heading": 0,
@@ -65,7 +72,7 @@
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"modified": "2015-04-21 07:57:40.260862",
"modified": "2015-06-15 05:52:22.986958",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Manufacturing Settings",

View File

@@ -90,8 +90,9 @@ class ProductionOrder(Document):
(self.sales_order, self.production_item))[0][0]
# total qty in SO
so_qty = flt(so_item_qty) + flt(dnpi_qty)
if total_qty > so_qty:
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings", "over_production_allowance_percentage"))
if total_qty > so_qty + (allowance_percentage/100 * so_qty):
frappe.throw(_("Cannot produce more Item {0} than Sales Order quantity {1}").format(self.production_item,
so_qty), OverProductionError)
@@ -217,12 +218,14 @@ class ProductionOrder(Document):
for i, d in enumerate(self.operations):
self.set_operation_start_end_time(i, d)
if not d.workstation:
continue
time_log = make_time_log(self.name, d.operation, d.planned_start_time, d.planned_end_time,
flt(self.qty) - flt(d.completed_qty), self.project_name, d.workstation, operation_id=d.name)
if d.workstation:
# validate operating hours if workstation [not mandatory] is specified
self.check_operation_fits_in_working_hours(d)
# validate operating hours if workstation [not mandatory] is specified
self.check_operation_fits_in_working_hours(d)
original_start_time = time_log.from_time
while True:
@@ -309,10 +312,9 @@ class ProductionOrder(Document):
self.actual_end_date = None
def validate_delivery_date(self):
if self.docstatus==1:
if self.planned_end_date and self.expected_delivery_date \
and getdate(self.expected_delivery_date) < getdate(self.planned_end_date):
frappe.msgprint(_("Production might not be able to finish by the Expected Delivery Date."))
if self.planned_start_date and self.expected_delivery_date \
and getdate(self.expected_delivery_date) < getdate(self.planned_start_date):
frappe.throw(_("Expected Delivery Date must be greater than Planned Start Date."))
def delete_time_logs(self):
for time_log in frappe.get_all("Time Log", ["name"], {"production_order": self.name}):

View File

@@ -165,4 +165,5 @@ erpnext.patches.v5_0.repost_gle_for_jv_with_multiple_party
erpnext.patches.v5_0.portal_fixes
erpnext.patches.v5_0.reset_values_in_tools
execute:frappe.delete_doc("Page", "users")
erpnext.patches.v5_0.update_material_transferred_for_manufacturing_again
erpnext.patches.v5_0.update_material_transferred_for_manufacturing_again
erpnext.patches.v5_0.index_on_account_and_gl_entry

View File

@@ -0,0 +1,30 @@
from __future__ import unicode_literals
import frappe
def execute():
index_map = {
"Account": ["parent_account", "lft", "rgt"],
"GL Entry": ["posting_date", "account", 'party', "voucher_no"],
"Sales Invoice": ["posting_date", "debit_to", "customer"],
"Purchase Invoice": ["posting_date", "credit_to", "supplier"]
}
for dt, indexes in index_map.items():
existing_indexes = [(d.Key_name, d.Column_name) for d in frappe.db.sql("""show index from `tab{0}`
where Column_name != 'name'""".format(dt), as_dict=1)]
for old, column in existing_indexes:
if column in ("parent", "group_or_ledger", "is_group", "is_pl_account", "debit_or_credit",
"account_name", "company", "project_name", "voucher_date", "due_date", "bill_no",
"bill_date", "is_opening", "fiscal_year", "outstanding_amount"):
frappe.db.sql("alter table `tab{0}` drop index {1}".format(dt, old))
existing_indexes = [(d.Key_name, d.Column_name) for d in frappe.db.sql("""show index from `tab{0}`
where Column_name != 'name'""".format(dt), as_dict=1)]
existing_indexed_columns = list(set([x[1] for x in existing_indexes]))
for new in indexes:
if new not in existing_indexed_columns:
frappe.db.sql("alter table `tab{0}` add index ({1})".format(dt, new))

View File

@@ -0,0 +1 @@
cur_frm.add_fetch('employee', 'employee_name', 'employee_name');

View File

@@ -2,47 +2,13 @@
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "Activity Cost - .#",
"autoname": "AC-.#####",
"creation": "2015-03-23 02:00:21.861546",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "employee",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Employee",
"no_copy": 0,
"options": "Employee",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0
},
{
"fieldname": "employee_name",
"fieldtype": "Read Only",
"label": "Employee Name",
"options": "employee.employee_name",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"permlevel": 0,
"precision": ""
},
{
"allow_on_submit": 0,
"fieldname": "activity_type",
@@ -63,6 +29,41 @@
"search_index": 0,
"set_only_once": 0
},
{
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"permlevel": 0,
"precision": ""
},
{
"allow_on_submit": 0,
"fieldname": "employee",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Employee",
"no_copy": 0,
"options": "Employee",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0
},
{
"fieldname": "employee_name",
"fieldtype": "Data",
"label": "Employee Name",
"options": "",
"permlevel": 0,
"precision": "",
"read_only": 1
},
{
"fieldname": "section_break_4",
"fieldtype": "Section Break",
@@ -135,7 +136,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-04-14 02:08:33.690406",
"modified": "2015-06-16 03:12:25.644839",
"modified_by": "Administrator",
"module": "Projects",
"name": "Activity Cost",

View File

@@ -15,10 +15,21 @@ class ActivityCost(Document):
self.check_unique()
def set_title(self):
self.title = _("{0} for {1}").format(self.employee_name, self.activity_type)
if self.employee:
if not self.employee_name:
self.employee_name = frappe.db.get_value("Employee", self.employee, "employee_name")
self.title = _("{0} for {1}").format(self.employee_name, self.activity_type)
else:
self.title = self.activity_type
def check_unique(self):
if frappe.db.sql("""select name from `tabActivity Cost` where employee_name= %s and activity_type= %s and name != %s""",
(self.employee_name, self.activity_type, self.name)):
frappe.throw(_("Activity Cost exists for Employee {0} against Activity Type - {1}")
.format(self.employee, self.activity_type), DuplicationError)
if self.employee:
if frappe.db.sql("""select name from `tabActivity Cost` where employee_name= %s and activity_type= %s and name != %s""",
(self.employee_name, self.activity_type, self.name)):
frappe.throw(_("Activity Cost exists for Employee {0} against Activity Type - {1}")
.format(self.employee, self.activity_type), DuplicationError)
else:
if frappe.db.sql("""select name from `tabActivity Cost` where ifnull(employee, '')='' and activity_type= %s and name != %s""",
(self.activity_type, self.name)):
frappe.throw(_("Default Activity Cost exists for Activity Type - {0}")
.format(self.activity_type), DuplicationError)

View File

@@ -163,6 +163,7 @@
"fieldtype": "Percent",
"in_list_view": 0,
"label": "% Tasks Completed",
"no_copy": 1,
"permlevel": 0,
"read_only": 1
},
@@ -356,7 +357,7 @@
"icon": "icon-puzzle-piece",
"idx": 1,
"max_attachments": 4,
"modified": "2015-04-27 07:37:44.239930",
"modified": "2015-06-12 09:00:54.080220",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project",

View File

@@ -15,16 +15,23 @@ class Project(Document):
def onload(self):
"""Load project tasks for quick view"""
for task in frappe.get_all("Task", "*", {"project": self.name}, order_by="exp_start_date asc"):
self.append("tasks", {
"title": task.subject,
"status": task.status,
"start_date": task.exp_start_date,
"end_date": task.exp_end_date,
"description": task.description,
"task_id": task.name
})
if not self.get("tasks"):
for task in self.get_tasks():
self.append("tasks", {
"title": task.subject,
"status": task.status,
"start_date": task.exp_start_date,
"end_date": task.exp_end_date,
"description": task.description,
"task_id": task.name
})
def __setup__(self):
self.onload()
def get_tasks(self):
return frappe.get_all("Task", "*", {"project": self.name}, order_by="exp_start_date asc")
def validate(self):
self.validate_dates()
self.sync_tasks()

View File

@@ -28,7 +28,11 @@ class Task(Document):
def validate(self):
self.validate_dates()
if self.status!=self.get_db_value("status") and self.status == "Closed":
from frappe.desk.form.assign_to import clear
clear(self.doctype, self.name)
def validate_dates(self):
if self.exp_start_date and self.exp_end_date and getdate(self.exp_start_date) > getdate(self.exp_end_date):
frappe.throw(_("'Expected Start Date' can not be greater than 'Expected End Date'"))
@@ -41,17 +45,17 @@ class Task(Document):
self.reschedule_dependent_tasks()
self.update_percentage()
self.update_project()
def update_percentage(self):
"""update percent complete in project"""
if self.project and not self.flags.from_project:
project = frappe.get_doc("Project", self.project)
project.run_method("update_percent_complete")
def update_total_expense_claim(self):
self.total_expense_claim = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim`
self.total_expense_claim = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim`
where project = %s and task = %s and approval_status = "Approved" and docstatus=1""",(self.project, self.name))
def update_time_and_costing(self):
tl = frappe.db.sql("""select min(from_time) as start_date, max(to_time) as end_date,
sum(billing_amount) as total_billing_amount, sum(costing_amount) as total_costing_amount,
@@ -64,14 +68,14 @@ class Task(Document):
self.actual_time= tl.time
self.act_start_date= tl.start_date
self.act_end_date= tl.end_date
def update_project(self):
if self.project and frappe.db.exists("Project", self.project):
project = frappe.get_doc("Project", self.project)
project.flags.dont_sync_tasks = True
project.update_costing()
project.save()
def check_recursion(self):
if self.flags.ignore_recursion_check: return
check_list = [['task', 'parent'], ['parent', 'task']]
@@ -88,7 +92,7 @@ class Task(Document):
task_list.append(b[0])
if count == 15:
break
def reschedule_dependent_tasks(self):
end_date = self.exp_end_date or self.act_end_date
if end_date:

View File

@@ -11,19 +11,19 @@ from erpnext.projects.doctype.task.task import CircularReferenceError
class TestTask(unittest.TestCase):
def test_circular_reference(self):
task1 = frappe.new_doc('Task')
task1.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 1",
"exp_start_date": "2015-1-1",
"exp_end_date": "2015-1-10"
})
task1.save()
task2 = frappe.new_doc('Task')
task2.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 2",
"exp_start_date": "2015-1-11",
"exp_end_date": "2015-1-15",
@@ -34,10 +34,10 @@ class TestTask(unittest.TestCase):
]
})
task2.save()
task3 = frappe.new_doc('Task')
task3.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 2",
"exp_start_date": "2015-1-11",
"exp_end_date": "2015-1-15",
@@ -53,13 +53,13 @@ class TestTask(unittest.TestCase):
"task": task3.name
})
self.assertRaises(CircularReferenceError, task1.save)
task1.set("depends_on", [])
task1.save()
task4 = frappe.new_doc('Task')
task4.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 1",
"exp_start_date": "2015-1-1",
"exp_end_date": "2015-1-15",
@@ -74,20 +74,20 @@ class TestTask(unittest.TestCase):
task3.append("depends_on", {
"task": task4.name
})
def test_reschedule_dependent_task(self):
task1 = frappe.new_doc('Task')
task1.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 1",
"exp_start_date": "2015-1-1",
"exp_end_date": "2015-1-10"
})
task1.save()
task2 = frappe.new_doc('Task')
task2.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 2",
"exp_start_date": "2015-1-11",
"exp_end_date": "2015-1-15",
@@ -98,10 +98,10 @@ class TestTask(unittest.TestCase):
]
})
task2.save()
task3 = frappe.new_doc('Task')
task3.update({
"status": "Open",
"status": "Open",
"subject": "_Test Task 3",
"exp_start_date": "2015-1-16",
"exp_end_date": "2015-1-18",
@@ -112,18 +112,18 @@ class TestTask(unittest.TestCase):
]
})
task3.save()
task1.update({
"exp_end_date": "2015-1-20"
})
task1.save()
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21'))
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28'))
time_log = frappe.new_doc('Time Log')
time_log.update({
"from_time": "2015-1-1",
@@ -131,18 +131,49 @@ class TestTask(unittest.TestCase):
"task": task1.name
})
time_log.submit()
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21'))
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28'))
time_log.cancel()
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21'))
self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26'))
self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28'))
def test_close_assignment(self):
task = frappe.new_doc("Task")
task.subject = "Test Close Assignment"
task.insert()
def assign():
from frappe.desk.form import assign_to
assign_to.add({
"assign_to": "test@example.com",
"doctype": task.doctype,
"name": task.name,
"description": "Close this task"
})
def get_owner_and_status():
return frappe.db.get_value("ToDo", filters={"reference_type": task.doctype, "reference_name": task.name,
"description": "Close this task"}, fieldname=("owner", "status"), as_dict=True)
assign()
todo = get_owner_and_status()
self.assertEquals(todo.owner, "test@example.com")
self.assertEquals(todo.status, "Open")
# assignment should be
task.load_from_db()
task.status = "Closed"
task.save()
todo = get_owner_and_status()
self.assertEquals(todo.owner, "test@example.com")
self.assertEquals(todo.status, "Closed")

View File

@@ -128,7 +128,7 @@ class TimeLog(Document):
def update_production_order(self):
"""Updates `start_date`, `end_date`, `status` for operation in Production Order."""
if self.production_order and self.for_manufacturing:
if not self.operation_id:
frappe.throw(_("Operation ID not set"))
@@ -208,22 +208,23 @@ class TimeLog(Document):
self.production_order = None
self.operation = None
self.quantity = None
def update_cost(self):
rate = get_activity_cost(self.employee, self.activity_type)
if rate:
self.costing_rate = rate.get('costing_rate')
self.billing_rate = rate.get('billing_rate')
self.billing_rate = rate.get('billing_rate')
self.costing_amount = self.costing_rate * self.hours
if self.billable:
self.billing_amount = self.billing_rate * self.hours
else:
self.billing_amount = 0
def validate_task(self):
if self.project and not self.task:
# if a time log is being created against a project without production order
if (self.project and not self.production_order) and not self.task:
frappe.throw(_("Task is Mandatory if Time Log is against a project"))
def update_task(self):
if self.task and frappe.db.exists("Task", self.task):
task = frappe.get_doc("Task", self.task)
@@ -266,9 +267,12 @@ def get_events(start, end, filters=None):
d.title += " for Project: " + d.project
return data
@frappe.whitelist()
def get_activity_cost(employee=None, activity_type=None):
rate = frappe.db.sql("""select costing_rate, billing_rate from `tabActivity Cost` where employee= %s
and activity_type= %s""", (employee, activity_type), as_dict=1)
if not rate:
rate = frappe.db.sql("""select costing_rate, billing_rate from `tabActivity Cost` where ifnull(employee, '')=''
and activity_type= %s""", (activity_type), as_dict=1)
return rate[0] if rate else {}

View File

@@ -105,6 +105,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
},
barcode: function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
if(d.barcode=="" || d.barcode==null) {
// barcode cleared, remove item
d.item_code = "";
}
this.item_code(doc, cdt, cdn);
},
item_code: function(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);

View File

@@ -81,7 +81,8 @@ erpnext.feature_setup.feature_dict = {
'Item': {'fields': ['barcode']},
'Delivery Note': {'items': ['barcode']},
'Sales Invoice': {'items': ['barcode']},
'Stock Entry': {'items': ['barcode']}
'Stock Entry': {'items': ['barcode']},
'Purchase Receipt': {'items': ['barcode']}
},
'fs_item_group_in_details': {
'Delivery Note': {'items':['item_group']},

View File

@@ -488,7 +488,7 @@
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
@@ -858,7 +858,7 @@
"idx": 1,
"is_submittable": 1,
"max_attachments": 1,
"modified": "2015-05-27 02:48:00.388847",
"modified": "2015-06-15 15:37:39.199814",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation",

View File

@@ -493,7 +493,7 @@
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
@@ -1080,7 +1080,7 @@
"idx": 1,
"is_submittable": 1,
"issingle": 0,
"modified": "2015-05-27 02:48:01.160307",
"modified": "2015-06-15 15:36:38.898462",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",

View File

@@ -8,6 +8,13 @@ frappe.query_reports["Customers Not Buying Since Long Time"] = {
"label": __("Days Since Last Order"),
"fieldtype": "Int",
"default": 60
},
{
"fieldname":"doctype",
"label": __("Doctype"),
"fieldtype": "Select",
"default": "Sales Order",
"options": "Sales Order\nSales Invoice"
}
]
}

View File

@@ -10,41 +10,51 @@ def execute(filters=None):
if not filters: filters ={}
days_since_last_order = filters.get("days_since_last_order")
doctype = filters.get("doctype")
if cint(days_since_last_order) <= 0:
frappe.throw(_("'Days Since Last Order' must be greater than or equal to zero"))
columns = get_columns()
customers = get_so_details()
customers = get_sales_details(doctype)
data = []
for cust in customers:
if cint(cust[8]) >= cint(days_since_last_order):
cust.insert(7,get_last_so_amt(cust[0]))
cust.insert(7,get_last_sales_amt(cust[0], doctype))
data.append(cust)
return columns, data
def get_so_details():
def get_sales_details(doctype):
cond = """sum(so.base_net_total) as 'total_order_considered',
max(so.posting_date) as 'last_order_date',
DATEDIFF(CURDATE(), max(so.posting_date)) as 'days_since_last_order' """
if doctype == "Sales Order":
cond = """sum(if(so.status = "Stopped",
so.base_net_total * so.per_delivered/100,
so.base_net_total)) as 'total_order_considered',
max(so.transaction_date) as 'last_order_date',
DATEDIFF(CURDATE(), max(so.transaction_date)) as 'days_since_last_order'"""
return frappe.db.sql("""select
cust.name,
cust.customer_name,
cust.territory,
cust.customer_group,
count(distinct(so.name)) as 'num_of_order',
sum(base_net_total) as 'total_order_value',
sum(if(so.status = "Stopped",
so.base_net_total * so.per_delivered/100,
so.base_net_total)) as 'total_order_considered',
max(so.transaction_date) as 'last_sales_order_date',
DATEDIFF(CURDATE(), max(so.transaction_date)) as 'days_since_last_order'
from `tabCustomer` cust, `tabSales Order` so
sum(base_net_total) as 'total_order_value', {0}
from `tabCustomer` cust, `tab{1}` so
where cust.name = so.customer and so.docstatus = 1
group by cust.name
order by 'days_since_last_order' desc """,as_list=1)
order by 'days_since_last_order' desc """.format(cond, doctype), as_list=1)
def get_last_so_amt(customer):
res = frappe.db.sql("""select base_net_total from `tabSales Order`
where customer = %s and docstatus = 1 order by transaction_date desc
limit 1""", customer)
def get_last_sales_amt(customer, doctype):
cond = "posting_date"
if doctype =="Sales Order":
cond = "transaction_date"
res = frappe.db.sql("""select base_net_total from `tab{0}`
where customer = %s and docstatus = 1 order by {1} desc
limit 1""".format(doctype, cond), customer)
return res and res[0][0] or 0
@@ -58,6 +68,6 @@ def get_columns():
_("Total Order Value") + ":Currency:120",
_("Total Order Considered") + ":Currency:160",
_("Last Order Amount") + ":Currency:160",
_("Last Sales Order Date") + ":Date:160",
_("Last Order Date") + ":Date:160",
_("Days Since Last Order") + "::160"
]

View File

@@ -124,15 +124,6 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
this.apply_pricing_rule();
},
barcode: function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
if(d.barcode=="" || d.barcode==null) {
// barcode cleared, remove item
d.item_code = "";
}
this.item_code(doc, cdt, cdn);
},
selling_price_list: function() {
this.apply_price_list();
},

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
import urllib
from frappe.utils.nestedset import NestedSet
from frappe.website.website_generator import WebsiteGenerator
from frappe.website.render import clear_cache
@@ -91,7 +91,7 @@ def get_item_for_list_in_html(context):
# add missing absolute link in files
# user may forget it during upload
if (context.get("website_image") or "").startswith("files/"):
context["website_image"] = "/" + context["website_image"]
context["website_image"] = "/" + urllib.quote(context["website_image"])
return frappe.get_template("templates/includes/product_in_grid.html").render(context)
def get_group_item_count(item_group):

View File

@@ -49,7 +49,7 @@ class NamingSeries(Document):
self.set_series_for(self.select_doc_for_series, series_list)
# create series
map(self.insert_series, [d.split('.')[0] for d in series_list])
map(self.insert_series, [d.split('.')[0] for d in series_list if d.strip()])
msgprint(_("Series Updated"))

View File

@@ -517,7 +517,7 @@
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
@@ -1070,7 +1070,7 @@
"idx": 1,
"in_create": 0,
"is_submittable": 1,
"modified": "2015-05-27 02:47:59.778147",
"modified": "2015-06-15 15:37:54.699371",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note",

View File

@@ -221,7 +221,7 @@
"icon": "icon-ticket",
"idx": 1,
"is_submittable": 1,
"modified": "2015-05-27 15:36:06.818491",
"modified": "2015-06-09 05:47:05.934432",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request",

View File

@@ -6,7 +6,13 @@ frappe.listview_settings['Material Request'] = {
} else if(doc.docstatus==1 && flt(doc.per_ordered) < 100) {
return [__("Pending"), "orange", "per_ordered,<,100"];
} else if(doc.docstatus==1 && flt(doc.per_ordered) == 100) {
return [__("Ordered"), "green", "per_ordered,=,100"];
if (doc.material_request_type == "Purchase") {
return [__("Ordered"), "green", "per_ordered,=,100"];
} else if (doc.material_request_type == "Material Transfer") {
return [__("Transfered"), "green", "per_ordered,=,100"];
} else if (doc.material_request_type == "Material Issue") {
return [__("Issued"), "green", "per_ordered,=,100"];
}
}
}
};

View File

@@ -443,7 +443,7 @@
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
@@ -854,7 +854,7 @@
"icon": "icon-truck",
"idx": 1,
"is_submittable": 1,
"modified": "2015-05-27 02:48:00.763945",
"modified": "2015-06-15 15:38:43.754869",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt",

View File

@@ -4,6 +4,19 @@
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"fieldname": "barcode",
"fieldtype": "Data",
"label": "Barcode",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "section_break_2",
"fieldtype": "Section Break",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "item_code",
"fieldtype": "Link",
@@ -642,7 +655,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-06-02 14:19:13.528248",
"modified": "2015-06-08 08:21:18.024324",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",

View File

@@ -112,7 +112,7 @@ class StockEntry(StockController):
for f in ("uom", "stock_uom", "description", "item_name", "expense_account",
"cost_center", "conversion_factor"):
if f not in ["expense_account", "cost_center"] or not item.get(f):
if f in ["stock_uom", "conversion_factor"] or not item.get(f):
item.set(f, item_details.get(f))
if self.difference_account:
@@ -185,9 +185,6 @@ class StockEntry(StockController):
def validate_production_order(self):
if self.purpose in ("Manufacture", "Material Transfer for Manufacture"):
if not self.bom_no:
frappe.throw(_("BOM No is mandatory"))
# check if production order is entered
if not self.production_order:
frappe.throw(_("Production order number is mandatory for stock entry purpose manufacture"))

View File

@@ -5,12 +5,12 @@
"doctype": "Report",
"idx": 1,
"is_standard": "Yes",
"modified": "2015-04-07 08:18:14.440193",
"modified": "2015-06-10 15:52:49.492144",
"modified_by": "Administrator",
"module": "Stock",
"name": "Ordered Items To Be Delivered",
"owner": "Administrator",
"query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project_name` as \"Project\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.qty as \"Qty:Float:140\",\n `tabSales Order Item`.delivered_qty as \"Delivered Qty:Float:140\",\n (`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0)) as \"Qty to Deliver:Float:140\",\n `tabSales Order Item`.base_rate as \"Rate:Float:140\",\n `tabSales Order Item`.base_amount as \"Amount:Float:140\",\n ((`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0))*`tabSales Order Item`.base_rate) as \"Amount to Deliver:Float:140\",\n `tabBin`.actual_qty as \"Available Qty:Float:120\",\n `tabBin`.projected_qty as \"Projected Qty:Float:120\",\n `tabSales Order`.`delivery_date` as \"Expected Delivery Date:Date:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order Item`.item_group as \"Item Group:Link/Item Group:120\"\nfrom\n `tabSales Order`, `tabSales Order Item`, `tabBin`\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status != \"Stopped\"\n and ifnull(`tabSales Order Item`.delivered_qty,0) < ifnull(`tabSales Order Item`.qty,0)\n and `tabBin`.item_code = `tabSales Order Item`.item_code\n and `tabBin`.warehouse = `tabSales Order Item`.warehouse\norder by `tabSales Order`.transaction_date asc",
"query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project_name` as \"Project\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.qty as \"Qty:Float:140\",\n `tabSales Order Item`.delivered_qty as \"Delivered Qty:Float:140\",\n (`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0)) as \"Qty to Deliver:Float:140\",\n `tabSales Order Item`.base_rate as \"Rate:Float:140\",\n `tabSales Order Item`.base_amount as \"Amount:Float:140\",\n ((`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0))*`tabSales Order Item`.base_rate) as \"Amount to Deliver:Float:140\",\n `tabBin`.actual_qty as \"Available Qty:Float:120\",\n `tabBin`.projected_qty as \"Projected Qty:Float:120\",\n `tabSales Order`.`delivery_date` as \"Expected Delivery Date:Date:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order Item`.item_group as \"Item Group:Link/Item Group:120\",\n `tabSales Order Item`.warehouse as \"Warehouse:Link/Warehouse:200\"\nfrom\n `tabSales Order`, `tabSales Order Item`, `tabBin`\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status != \"Stopped\"\n and ifnull(`tabSales Order Item`.delivered_qty,0) < ifnull(`tabSales Order Item`.qty,0)\n and `tabBin`.item_code = `tabSales Order Item`.item_code\n and `tabBin`.warehouse = `tabSales Order Item`.warehouse\norder by `tabSales Order`.transaction_date asc",
"ref_doctype": "Delivery Note",
"report_name": "Ordered Items To Be Delivered",
"report_type": "Query Report"

View File

@@ -1,6 +1,6 @@
from setuptools import setup, find_packages
version = "5.0.19"
version = "5.0.25"
with open("requirements.txt", "r") as f:
install_requires = f.readlines()