Merge branch 'responsive' of github.com:webnotes/erpnext into responsive
This commit is contained in:
commit
a93ca595e1
@ -42,9 +42,9 @@ class DocType:
|
|||||||
self.check_negative_balance(adv_adj)
|
self.check_negative_balance(adv_adj)
|
||||||
|
|
||||||
# Update outstanding amt on against voucher
|
# Update outstanding amt on against voucher
|
||||||
if self.doc.against_voucher and self.doc.against_voucher_type not in \
|
if self.doc.against_voucher and self.doc.against_voucher_type != "POS" \
|
||||||
('Journal Voucher','POS') and update_outstanding == 'Yes':
|
and update_outstanding == 'Yes':
|
||||||
self.update_outstanding_amt()
|
self.update_outstanding_amt()
|
||||||
|
|
||||||
def check_mandatory(self):
|
def check_mandatory(self):
|
||||||
mandatory = ['account','remarks','voucher_type','voucher_no','fiscal_year','company']
|
mandatory = ['account','remarks','voucher_type','voucher_no','fiscal_year','company']
|
||||||
@ -164,16 +164,25 @@ class DocType:
|
|||||||
and ifnull(is_cancelled,'No') = 'No'""",
|
and ifnull(is_cancelled,'No') = 'No'""",
|
||||||
(self.doc.against_voucher, self.doc.against_voucher_type))[0][0] or 0.0)
|
(self.doc.against_voucher, self.doc.against_voucher_type))[0][0] or 0.0)
|
||||||
|
|
||||||
if self.doc.against_voucher_type=='Purchase Invoice':
|
if self.doc.against_voucher_type == 'Purchase Invoice':
|
||||||
# amount to debit
|
|
||||||
bal = -bal
|
bal = -bal
|
||||||
|
|
||||||
|
elif self.doc.against_voucher_type == "Journal Voucher":
|
||||||
|
against_voucher_amount = flt(webnotes.conn.sql("""select sum(debit) - sum(credit)
|
||||||
|
from `tabGL Entry` where voucher_type = 'Journal Voucher' and voucher_no = %s
|
||||||
|
and account = %s""", (self.doc.against_voucher, self.doc.account))[0][0])
|
||||||
|
|
||||||
|
bal = against_voucher_amount + bal
|
||||||
|
if against_voucher_amount < 0:
|
||||||
|
bal = -bal
|
||||||
|
|
||||||
# Validation : Outstanding can not be negative
|
# Validation : Outstanding can not be negative
|
||||||
if bal < 0 and self.doc.is_cancelled == 'No':
|
if bal < 0 and self.doc.is_cancelled == 'No':
|
||||||
msgprint(_("Outstanding for Voucher ") + self.doc.against_voucher +
|
msgprint(_("Outstanding for Voucher ") + self.doc.against_voucher +
|
||||||
_(" will become ") + fmt_money(bal) + _("Outstanding cannot be less than zero. \
|
_(" will become ") + fmt_money(bal) + _(". Outstanding cannot be less than zero. \
|
||||||
Please match exact outstanding."), raise_exception=1)
|
Please match exact outstanding."), raise_exception=1)
|
||||||
|
|
||||||
# Update outstanding amt on against voucher
|
# Update outstanding amt on against voucher
|
||||||
sql("update `tab%s` set outstanding_amount=%s where name='%s'"%
|
if self.doc.against_voucher_type in ["Sales Invoice", "Purchase Invoice"]:
|
||||||
(self.doc.against_voucher_type, bal, self.doc.against_voucher))
|
sql("update `tab%s` set outstanding_amount=%s where name='%s'"%
|
||||||
|
(self.doc.against_voucher_type, bal, self.doc.against_voucher))
|
@ -158,7 +158,7 @@ class DocType(AccountsController):
|
|||||||
if r:
|
if r:
|
||||||
self.doc.remark = ("\n").join(r)
|
self.doc.remark = ("\n").join(r)
|
||||||
else:
|
else:
|
||||||
webnotes.msgprint("Remarks is mandatory", raise_exception=1)
|
webnotes.msgprint("User Remarks is mandatory", raise_exception=1)
|
||||||
|
|
||||||
def set_aging_date(self):
|
def set_aging_date(self):
|
||||||
if self.doc.is_opening != 'Yes':
|
if self.doc.is_opening != 'Yes':
|
||||||
|
@ -33,6 +33,28 @@ class DocType(BuyingController):
|
|||||||
self.doc, self.doclist = d, dl
|
self.doc, self.doclist = d, dl
|
||||||
self.tname = 'Purchase Invoice Item'
|
self.tname = 'Purchase Invoice Item'
|
||||||
self.fname = 'entries'
|
self.fname = 'entries'
|
||||||
|
self.status_updater = [{
|
||||||
|
'source_dt': 'Purchase Invoice Item',
|
||||||
|
'target_dt': 'Purchase Order Item',
|
||||||
|
'join_field': 'po_detail',
|
||||||
|
'target_field': 'billed_amt',
|
||||||
|
'target_parent_dt': 'Purchase Order',
|
||||||
|
'target_parent_field': 'per_billed',
|
||||||
|
'target_ref_field': 'import_amount',
|
||||||
|
'source_field': 'import_amount',
|
||||||
|
'percent_join_field': 'purchase_order',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'source_dt': 'Purchase Invoice Item',
|
||||||
|
'target_dt': 'Purchase Receipt Item',
|
||||||
|
'join_field': 'pr_detail',
|
||||||
|
'target_field': 'billed_amt',
|
||||||
|
'target_parent_dt': 'Purchase Receipt',
|
||||||
|
'target_parent_field': 'per_billed',
|
||||||
|
'target_ref_field': 'import_amount',
|
||||||
|
'source_field': 'import_amount',
|
||||||
|
'percent_join_field': 'purchase_receipt',
|
||||||
|
}]
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
super(DocType, self).validate()
|
super(DocType, self).validate()
|
||||||
@ -391,8 +413,8 @@ class DocType(BuyingController):
|
|||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
|
|
||||||
self.update_against_document_in_jv()
|
self.update_against_document_in_jv()
|
||||||
purchase_controller.update_prevdoc_detail(self, is_submit = 1)
|
|
||||||
|
self.update_prevdoc_status()
|
||||||
|
|
||||||
def make_gl_entries(self):
|
def make_gl_entries(self):
|
||||||
from accounts.general_ledger import make_gl_entries
|
from accounts.general_ledger import make_gl_entries
|
||||||
@ -503,7 +525,8 @@ class DocType(BuyingController):
|
|||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
from accounts.utils import remove_against_link_from_jv
|
from accounts.utils import remove_against_link_from_jv
|
||||||
remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_voucher")
|
remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_voucher")
|
||||||
get_obj(dt = 'Purchase Common').update_prevdoc_detail(self, is_submit = 0)
|
|
||||||
|
self.update_prevdoc_status()
|
||||||
|
|
||||||
self.make_cancel_gl_entries()
|
self.make_cancel_gl_entries()
|
||||||
|
|
||||||
|
@ -38,6 +38,35 @@ class DocType(SellingController):
|
|||||||
self.log = []
|
self.log = []
|
||||||
self.tname = 'Sales Invoice Item'
|
self.tname = 'Sales Invoice Item'
|
||||||
self.fname = 'entries'
|
self.fname = 'entries'
|
||||||
|
self.status_updater = [{
|
||||||
|
'source_dt': 'Sales Invoice Item',
|
||||||
|
'target_field': 'billed_amt',
|
||||||
|
'target_ref_field': 'export_amount',
|
||||||
|
'target_dt': 'Sales Order Item',
|
||||||
|
'join_field': 'so_detail',
|
||||||
|
'target_parent_dt': 'Sales Order',
|
||||||
|
'target_parent_field': 'per_billed',
|
||||||
|
'source_field': 'export_amount',
|
||||||
|
'join_field': 'so_detail',
|
||||||
|
'percent_join_field': 'sales_order',
|
||||||
|
'status_field': 'billing_status',
|
||||||
|
'keyword': 'Billed'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'source_dt': 'Sales Invoice Item',
|
||||||
|
'target_dt': 'Delivery Note Item',
|
||||||
|
'join_field': 'dn_detail',
|
||||||
|
'target_field': 'billed_amt',
|
||||||
|
'target_parent_dt': 'Delivery Note',
|
||||||
|
'target_parent_field': 'per_billed',
|
||||||
|
'target_ref_field': 'export_amount',
|
||||||
|
'source_field': 'export_amount',
|
||||||
|
'percent_join_field': 'delivery_note',
|
||||||
|
'status_field': 'billing_status',
|
||||||
|
'keyword': 'Billed',
|
||||||
|
'no_tolerance': True,
|
||||||
|
}]
|
||||||
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
super(DocType, self).validate()
|
super(DocType, self).validate()
|
||||||
@ -99,7 +128,9 @@ class DocType(SellingController):
|
|||||||
|
|
||||||
self.set_buying_amount()
|
self.set_buying_amount()
|
||||||
self.check_prev_docstatus()
|
self.check_prev_docstatus()
|
||||||
get_obj("Sales Common").update_prevdoc_detail(1,self)
|
|
||||||
|
self.update_status_updater_args()
|
||||||
|
self.update_prevdoc_status()
|
||||||
|
|
||||||
# this sequence because outstanding may get -ve
|
# this sequence because outstanding may get -ve
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
@ -128,10 +159,30 @@ class DocType(SellingController):
|
|||||||
from accounts.utils import remove_against_link_from_jv
|
from accounts.utils import remove_against_link_from_jv
|
||||||
remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_invoice")
|
remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_invoice")
|
||||||
|
|
||||||
sales_com_obj.update_prevdoc_detail(0, self)
|
self.update_status_updater_args()
|
||||||
|
self.update_prevdoc_status()
|
||||||
|
|
||||||
self.make_cancel_gl_entries()
|
self.make_cancel_gl_entries()
|
||||||
|
|
||||||
|
def update_status_updater_args(self):
|
||||||
|
if cint(self.doc.is_pos) and cint(self.doc.update_stock):
|
||||||
|
self.status_updater.append({
|
||||||
|
'source_dt':'Sales Invoice Item',
|
||||||
|
'target_dt':'Sales Order Item',
|
||||||
|
'target_parent_dt':'Sales Order',
|
||||||
|
'target_parent_field':'per_delivered',
|
||||||
|
'target_field':'delivered_qty',
|
||||||
|
'target_ref_field':'qty',
|
||||||
|
'source_field':'qty',
|
||||||
|
'join_field':'so_detail',
|
||||||
|
'percent_join_field':'sales_order',
|
||||||
|
'status_field':'delivery_status',
|
||||||
|
'keyword':'Delivered',
|
||||||
|
'second_source_dt': 'Delivery Note Item',
|
||||||
|
'second_source_field': 'qty',
|
||||||
|
'second_join_field': 'prevdoc_detail_docname'
|
||||||
|
})
|
||||||
|
|
||||||
def on_update_after_submit(self):
|
def on_update_after_submit(self):
|
||||||
self.validate_recurring_invoice()
|
self.validate_recurring_invoice()
|
||||||
self.convert_to_recurring()
|
self.convert_to_recurring()
|
||||||
@ -269,7 +320,7 @@ class DocType(SellingController):
|
|||||||
|
|
||||||
ret = self.get_debit_to()
|
ret = self.get_debit_to()
|
||||||
self.doc.debit_to = ret.get('debit_to')
|
self.doc.debit_to = ret.get('debit_to')
|
||||||
|
|
||||||
def get_barcode_details(self, barcode):
|
def get_barcode_details(self, barcode):
|
||||||
return get_obj('Sales Common').get_barcode_details(barcode)
|
return get_obj('Sales Common').get_barcode_details(barcode)
|
||||||
|
|
||||||
@ -340,17 +391,6 @@ class DocType(SellingController):
|
|||||||
from accounts.utils import reconcile_against_document
|
from accounts.utils import reconcile_against_document
|
||||||
reconcile_against_document(lst)
|
reconcile_against_document(lst)
|
||||||
|
|
||||||
def validate_customer(self):
|
|
||||||
""" Validate customer name with SO and DN"""
|
|
||||||
for d in getlist(self.doclist,'entries'):
|
|
||||||
dt = d.delivery_note and 'Delivery Note' or d.sales_order and 'Sales Order' or ''
|
|
||||||
if dt:
|
|
||||||
dt_no = d.delivery_note or d.sales_order
|
|
||||||
cust = webnotes.conn.sql("select customer from `tab%s` where name = %s" % (dt, '%s'), dt_no)
|
|
||||||
if cust and cstr(cust[0][0]) != cstr(self.doc.customer):
|
|
||||||
msgprint("Customer %s does not match with customer of %s: %s." %(self.doc.customer, dt, dt_no), raise_exception=1)
|
|
||||||
|
|
||||||
|
|
||||||
def validate_customer_account(self):
|
def validate_customer_account(self):
|
||||||
"""Validates Debit To Account and Customer Matches"""
|
"""Validates Debit To Account and Customer Matches"""
|
||||||
if self.doc.customer and self.doc.debit_to and not cint(self.doc.is_pos):
|
if self.doc.customer and self.doc.debit_to and not cint(self.doc.is_pos):
|
||||||
@ -360,6 +400,19 @@ class DocType(SellingController):
|
|||||||
(not acc_head and (self.doc.debit_to != cstr(self.doc.customer) + " - " + self.get_company_abbr())):
|
(not acc_head and (self.doc.debit_to != cstr(self.doc.customer) + " - " + self.get_company_abbr())):
|
||||||
msgprint("Debit To: %s do not match with Customer: %s for Company: %s.\n If both correctly entered, please select Master Type \
|
msgprint("Debit To: %s do not match with Customer: %s for Company: %s.\n If both correctly entered, please select Master Type \
|
||||||
and Master Name in account master." %(self.doc.debit_to, self.doc.customer,self.doc.company), raise_exception=1)
|
and Master Name in account master." %(self.doc.debit_to, self.doc.customer,self.doc.company), raise_exception=1)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_customer(self):
|
||||||
|
""" Validate customer name with SO and DN"""
|
||||||
|
if self.doc.customer:
|
||||||
|
for d in getlist(self.doclist,'entries'):
|
||||||
|
dt = d.delivery_note and 'Delivery Note' or d.sales_order and 'Sales Order' or ''
|
||||||
|
if dt:
|
||||||
|
dt_no = d.delivery_note or d.sales_order
|
||||||
|
cust = webnotes.conn.get_value(dt, dt_no, "customer")
|
||||||
|
if cust and cstr(cust) != cstr(self.doc.customer):
|
||||||
|
msgprint("Customer %s does not match with customer of %s: %s."
|
||||||
|
%(self.doc.customer, dt, dt_no), raise_exception=1)
|
||||||
|
|
||||||
|
|
||||||
def validate_debit_acc(self):
|
def validate_debit_acc(self):
|
||||||
|
@ -127,6 +127,16 @@ wn.module_page["Accounts"] = [
|
|||||||
right: true,
|
right: true,
|
||||||
icon: "icon-table",
|
icon: "icon-table",
|
||||||
items: [
|
items: [
|
||||||
|
{
|
||||||
|
"label":wn._("Customer Account Head"),
|
||||||
|
route: "query-report/Customer Account Head",
|
||||||
|
doctype: "Account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label":wn._("Supplier Account Head"),
|
||||||
|
route: "query-report/Supplier Account Head",
|
||||||
|
doctype: "Account"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label":wn._("General Ledger"),
|
"label":wn._("General Ledger"),
|
||||||
page: "general-ledger"
|
page: "general-ledger"
|
||||||
@ -232,6 +242,16 @@ wn.module_page["Accounts"] = [
|
|||||||
route: "query-report/Sales Partners Commission",
|
route: "query-report/Sales Partners Commission",
|
||||||
doctype: "Sales Invoice"
|
doctype: "Sales Invoice"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label":wn._("Customer Account Head"),
|
||||||
|
route: "query-report/Customer Account Head",
|
||||||
|
doctype: "Account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label":wn._("Item-wise Sales Register"),
|
||||||
|
route: "query-report/Item-wise Sales Register",
|
||||||
|
doctype: "Sales Invoice"
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
0
accounts/report/customer_account_head/__init__.py
Normal file
0
accounts/report/customer_account_head/__init__.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# ERPNext - web based ERP (http://erpnext.com)
|
||||||
|
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import webnotes
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
account_map = get_account_map()
|
||||||
|
columns = get_columns(account_map)
|
||||||
|
data = []
|
||||||
|
customers = webnotes.conn.sql("select name from tabCustomer where docstatus < 2")
|
||||||
|
for cust in customers:
|
||||||
|
row = [cust[0]]
|
||||||
|
for company in sorted(account_map):
|
||||||
|
row.append(account_map[company].get(cust[0], ''))
|
||||||
|
data.append(row)
|
||||||
|
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
def get_account_map():
|
||||||
|
accounts = webnotes.conn.sql("""select name, company, master_name
|
||||||
|
from `tabAccount` where master_type = 'Customer'
|
||||||
|
and ifnull(master_name, '') != '' and docstatus < 2""", as_dict=1)
|
||||||
|
|
||||||
|
account_map = {}
|
||||||
|
for acc in accounts:
|
||||||
|
account_map.setdefault(acc.company, {}).setdefault(acc.master_name, {})
|
||||||
|
account_map[acc.company][acc.master_name] = acc.name
|
||||||
|
|
||||||
|
return account_map
|
||||||
|
|
||||||
|
def get_columns(account_map):
|
||||||
|
columns = ["Customer:Link/Customer:120"] + \
|
||||||
|
[(company + ":Link/Account:120") for company in sorted(account_map)]
|
||||||
|
|
||||||
|
return columns
|
@ -0,0 +1,21 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"creation": "2013-06-03 16:17:34",
|
||||||
|
"docstatus": 0,
|
||||||
|
"modified": "2013-06-03 16:17:34",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"owner": "Administrator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Report",
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"name": "__common__",
|
||||||
|
"ref_doctype": "Account",
|
||||||
|
"report_name": "Customer Account Head",
|
||||||
|
"report_type": "Script Report"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Report",
|
||||||
|
"name": "Customer Account Head"
|
||||||
|
}
|
||||||
|
]
|
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-28 15:54:16",
|
"creation": "2013-05-28 15:54:16",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-05-28 16:02:57",
|
"modified": "2013-06-05 13:01:05",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -11,7 +11,7 @@
|
|||||||
"doctype": "Report",
|
"doctype": "Report",
|
||||||
"is_standard": "Yes",
|
"is_standard": "Yes",
|
||||||
"name": "__common__",
|
"name": "__common__",
|
||||||
"query": "select \n `tabPurchase Order`.`name` as \"Purchase Order:Link/Purchase Order:120\",\n `tabPurchase Order`.`transaction_date` as \"Date:Date:100\",\n\t`tabPurchase Order`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Order Item`.`project_name` as \"Project\",\n\t`tabPurchase Order Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Order Item`.qty as \"Qty:Float:100\",\n\t`tabPurchase Order Item`.billed_qty as \"Billed Qty:Float:100\", \n\t(`tabPurchase Order Item`.qty - ifnull(`tabPurchase Order Item`.billed_qty, 0)) as \"Qty to Bill:Float:100\",\n\t`tabPurchase Order Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Order Item`.description as \"Description::200\"\nfrom\n\t`tabPurchase Order`, `tabPurchase Order Item`\nwhere\n\t`tabPurchase Order Item`.`parent` = `tabPurchase Order`.`name`\n\tand `tabPurchase Order`.docstatus = 1\n\tand `tabPurchase Order`.status != \"Stopped\"\n\tand ifnull(`tabPurchase Order Item`.billed_qty, 0) < ifnull(`tabPurchase Order Item`.qty, 0)\norder by `tabPurchase Order`.transaction_date asc",
|
"query": "select \n `tabPurchase Order`.`name` as \"Purchase Order:Link/Purchase Order:120\",\n `tabPurchase Order`.`transaction_date` as \"Date:Date:100\",\n\t`tabPurchase Order`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Order Item`.`project_name` as \"Project\",\n\t`tabPurchase Order Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Order Item`.amount as \"Amount:Currency:100\",\n\t`tabPurchase Order Item`.billed_amt as \"Billed Amount:Currency:100\", \n\t(`tabPurchase Order Item`.amount - ifnull(`tabPurchase Order Item`.billed_amt, 0)) as \"Amount to Bill:Currency:100\",\n\t`tabPurchase Order Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Order Item`.description as \"Description::200\"\nfrom\n\t`tabPurchase Order`, `tabPurchase Order Item`\nwhere\n\t`tabPurchase Order Item`.`parent` = `tabPurchase Order`.`name`\n\tand `tabPurchase Order`.docstatus = 1\n\tand `tabPurchase Order`.status != \"Stopped\"\n\tand ifnull(`tabPurchase Order Item`.billed_amt, 0) < ifnull(`tabPurchase Order Item`.amount, 0)\norder by `tabPurchase Order`.transaction_date asc",
|
||||||
"ref_doctype": "Purchase Invoice",
|
"ref_doctype": "Purchase Invoice",
|
||||||
"report_name": "Purchase Order Items To Be Billed",
|
"report_name": "Purchase Order Items To Be Billed",
|
||||||
"report_type": "Query Report"
|
"report_type": "Query Report"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-28 15:57:59",
|
"creation": "2013-05-28 15:57:59",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-05-28 17:34:05",
|
"modified": "2013-06-05 12:59:17",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -11,7 +11,7 @@
|
|||||||
"doctype": "Report",
|
"doctype": "Report",
|
||||||
"is_standard": "Yes",
|
"is_standard": "Yes",
|
||||||
"name": "__common__",
|
"name": "__common__",
|
||||||
"query": "select \n `tabPurchase Receipt`.`name` as \"Purchase Receipt:Link/Purchase Receipt:120\",\n `tabPurchase Receipt`.`posting_date` as \"Date:Date:100\",\n `tabPurchase Receipt`.`supplier` as \"Supplier:Link/Supplier:120\",\n `tabPurchase Receipt Item`.`project_name` as \"Project\",\n\t`tabPurchase Receipt Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Receipt Item`.qty as \"Qty:Float:100\",\n\t`tabPurchase Receipt Item`.billed_qty as \"Billed Qty:Float:100\", \n\t(`tabPurchase Receipt Item`.qty - ifnull(`tabPurchase Receipt Item`.billed_qty, 0)) as \"Qty to Bill:Float:100\",\n\t`tabPurchase Receipt Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Receipt Item`.description as \"Description::200\"\nfrom\n\t`tabPurchase Receipt`, `tabPurchase Receipt Item`\nwhere\n\t`tabPurchase Receipt Item`.`parent` = `tabPurchase Receipt`.`name`\n\tand `tabPurchase Receipt`.docstatus = 1\n\tand `tabPurchase Receipt`.status != \"Stopped\"\n\tand ifnull(`tabPurchase Receipt Item`.billed_qty, 0) < ifnull(`tabPurchase Receipt Item`.qty, 0)\norder by `tabPurchase Receipt`.posting_date asc",
|
"query": "select \n `tabPurchase Receipt`.`name` as \"Purchase Receipt:Link/Purchase Receipt:120\",\n `tabPurchase Receipt`.`posting_date` as \"Date:Date:100\",\n `tabPurchase Receipt`.`supplier` as \"Supplier:Link/Supplier:120\",\n `tabPurchase Receipt Item`.`project_name` as \"Project\",\n\t`tabPurchase Receipt Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Receipt Item`.amount as \"Amount:Currency:100\",\n\t`tabPurchase Receipt Item`.billed_amt as \"Billed Amount:Currency:100\", \n\t(`tabPurchase Receipt Item`.amount - ifnull(`tabPurchase Receipt Item`.billed_amt, 0)) as \"Amount to Bill:Currency:100\",\n\t`tabPurchase Receipt Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Receipt Item`.description as \"Description::200\"\nfrom\n\t`tabPurchase Receipt`, `tabPurchase Receipt Item`\nwhere\n\t`tabPurchase Receipt Item`.`parent` = `tabPurchase Receipt`.`name`\n\tand `tabPurchase Receipt`.docstatus = 1\n\tand `tabPurchase Receipt`.status != \"Stopped\"\n\tand ifnull(`tabPurchase Receipt Item`.billed_amt, 0) < ifnull(`tabPurchase Receipt Item`.amount, 0)\norder by `tabPurchase Receipt`.posting_date asc",
|
||||||
"ref_doctype": "Purchase Invoice",
|
"ref_doctype": "Purchase Invoice",
|
||||||
"report_name": "Received Items To Be Billed",
|
"report_name": "Received Items To Be Billed",
|
||||||
"report_type": "Query Report"
|
"report_type": "Query Report"
|
||||||
|
0
accounts/report/supplier_account_head/__init__.py
Normal file
0
accounts/report/supplier_account_head/__init__.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# ERPNext - web based ERP (http://erpnext.com)
|
||||||
|
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import webnotes
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
account_map = get_account_map()
|
||||||
|
columns = get_columns(account_map)
|
||||||
|
data = []
|
||||||
|
suppliers = webnotes.conn.sql("select name from tabSupplier where docstatus < 2")
|
||||||
|
for supplier in suppliers:
|
||||||
|
row = [supplier[0]]
|
||||||
|
for company in sorted(account_map):
|
||||||
|
row.append(account_map[company].get(supplier[0], ''))
|
||||||
|
data.append(row)
|
||||||
|
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
def get_account_map():
|
||||||
|
accounts = webnotes.conn.sql("""select name, company, master_name
|
||||||
|
from `tabAccount` where master_type = 'Supplier'
|
||||||
|
and ifnull(master_name, '') != '' and docstatus < 2""", as_dict=1)
|
||||||
|
|
||||||
|
account_map = {}
|
||||||
|
for acc in accounts:
|
||||||
|
account_map.setdefault(acc.company, {}).setdefault(acc.master_name, {})
|
||||||
|
account_map[acc.company][acc.master_name] = acc.name
|
||||||
|
|
||||||
|
return account_map
|
||||||
|
|
||||||
|
def get_columns(account_map):
|
||||||
|
columns = ["Supplier:Link/Supplier:120"] + \
|
||||||
|
[(company + ":Link/Account:120") for company in sorted(account_map)]
|
||||||
|
|
||||||
|
return columns
|
@ -0,0 +1,21 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"creation": "2013-06-04 12:56:17",
|
||||||
|
"docstatus": 0,
|
||||||
|
"modified": "2013-06-04 12:56:46",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"owner": "Administrator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Report",
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"name": "__common__",
|
||||||
|
"ref_doctype": "Account",
|
||||||
|
"report_name": "Supplier Account Head",
|
||||||
|
"report_type": "Script Report"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Report",
|
||||||
|
"name": "Supplier Account Head"
|
||||||
|
}
|
||||||
|
]
|
@ -202,10 +202,11 @@ class DocType(BuyingController):
|
|||||||
msgprint("Please check Item %s is not present in %s %s ." % (d.item_code, d.prevdoc_doctype, d.prevdoc_docname))
|
msgprint("Please check Item %s is not present in %s %s ." % (d.item_code, d.prevdoc_doctype, d.prevdoc_docname))
|
||||||
raise Exception
|
raise Exception
|
||||||
|
|
||||||
# Check if Warehouse has been modified.
|
if cstr(data[0]['warehouse']) and \
|
||||||
if not cstr(data[0]['warehouse']) == cstr(d.warehouse):
|
not cstr(data[0]['warehouse']) == cstr(d.warehouse):
|
||||||
msgprint("Please check warehouse %s of Item %s which is not present in %s %s ." % (d.warehouse, d.item_code, d.prevdoc_doctype, d.prevdoc_docname))
|
msgprint("""Please check warehouse %s of Item %s
|
||||||
raise Exception
|
which is not present in %s %s""" % (d.warehouse, d.item_code,
|
||||||
|
d.prevdoc_doctype, d.prevdoc_docname), raise_exception=1)
|
||||||
|
|
||||||
# Check if UOM has been modified.
|
# Check if UOM has been modified.
|
||||||
if not cstr(data[0]['uom']) == cstr(d.uom) and not cstr(d.prevdoc_doctype) == 'Material Request':
|
if not cstr(data[0]['uom']) == cstr(d.uom) and not cstr(d.prevdoc_doctype) == 'Material Request':
|
||||||
@ -436,4 +437,4 @@ class DocType(BuyingController):
|
|||||||
for d in getlist(obj.doclist, obj.fname):
|
for d in getlist(obj.doclist, obj.fname):
|
||||||
if d.prevdoc_doctype and d.prevdoc_docname:
|
if d.prevdoc_doctype and d.prevdoc_docname:
|
||||||
dt = sql("select transaction_date from `tab%s` where name = '%s'" % (d.prevdoc_doctype, d.prevdoc_docname))
|
dt = sql("select transaction_date from `tab%s` where name = '%s'" % (d.prevdoc_doctype, d.prevdoc_docname))
|
||||||
d.prevdoc_date = dt and dt[0][0].strftime('%Y-%m-%d') or ''
|
d.prevdoc_date = dt and dt[0][0].strftime('%Y-%m-%d') or ''
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-24 19:29:06",
|
"creation": "2013-05-24 19:29:06",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-05-28 12:13:21",
|
"modified": "2013-05-31 14:26:22",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -377,15 +377,12 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0.00",
|
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "billed_qty",
|
"fieldname": "billed_amt",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Currency",
|
||||||
"hidden": 0,
|
"label": "Billed Amt",
|
||||||
"label": "Billed Quantity",
|
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "billed_qty",
|
"options": "currency",
|
||||||
"oldfieldtype": "Currency",
|
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
|
177
controllers/status_updater.py
Normal file
177
controllers/status_updater.py
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
# ERPNext - web based ERP (http://erpnext.com)
|
||||||
|
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import webnotes
|
||||||
|
from webnotes.utils import flt, cstr
|
||||||
|
from webnotes import msgprint
|
||||||
|
|
||||||
|
from webnotes.model.controller import DocListController
|
||||||
|
|
||||||
|
class StatusUpdater(DocListController):
|
||||||
|
"""
|
||||||
|
Updates the status of the calling records
|
||||||
|
Delivery Note: Update Delivered Qty, Update Percent and Validate over delivery
|
||||||
|
Sales Invoice: Update Billed Amt, Update Percent and Validate over billing
|
||||||
|
Installation Note: Update Installed Qty, Update Percent Qty and Validate over installation
|
||||||
|
"""
|
||||||
|
|
||||||
|
def update_prevdoc_status(self):
|
||||||
|
self.update_qty()
|
||||||
|
self.validate_qty()
|
||||||
|
|
||||||
|
def validate_qty(self):
|
||||||
|
"""
|
||||||
|
Validates qty at row level
|
||||||
|
"""
|
||||||
|
self.tolerance = {}
|
||||||
|
self.global_tolerance = None
|
||||||
|
|
||||||
|
for args in self.status_updater:
|
||||||
|
# get unique transactions to update
|
||||||
|
for d in self.doclist:
|
||||||
|
if d.doctype == args['source_dt'] and d.fields.get(args["join_field"]):
|
||||||
|
args['name'] = d.fields[args['join_field']]
|
||||||
|
|
||||||
|
# get all qty where qty > target_field
|
||||||
|
item = webnotes.conn.sql("""select item_code, `%(target_ref_field)s`,
|
||||||
|
`%(target_field)s`, parenttype, parent from `tab%(target_dt)s`
|
||||||
|
where `%(target_ref_field)s` < `%(target_field)s`
|
||||||
|
and name="%(name)s" and docstatus=1""" % args, as_dict=1)
|
||||||
|
if item:
|
||||||
|
item = item[0]
|
||||||
|
item['idx'] = d.idx
|
||||||
|
item['target_ref_field'] = args['target_ref_field'].replace('_', ' ')
|
||||||
|
|
||||||
|
if not item[args['target_ref_field']]:
|
||||||
|
msgprint("""As %(target_ref_field)s for item: %(item_code)s in \
|
||||||
|
%(parenttype)s: %(parent)s is zero, system will not check \
|
||||||
|
over-delivery or over-billed""" % item)
|
||||||
|
elif args.get('no_tolerance'):
|
||||||
|
item['reduce_by'] = item[args['target_field']] - \
|
||||||
|
item[args['target_ref_field']]
|
||||||
|
if item['reduce_by'] > .01:
|
||||||
|
msgprint("""
|
||||||
|
Row #%(idx)s: Max %(target_ref_field)s allowed for <b>Item \
|
||||||
|
%(item_code)s</b> against <b>%(parenttype)s %(parent)s</b> \
|
||||||
|
is <b>""" % item + cstr(item[args['target_ref_field']]) +
|
||||||
|
"""</b>.<br>You must reduce the %(target_ref_field)s by \
|
||||||
|
%(reduce_by)s""" % item, raise_exception=1)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.check_overflow_with_tolerance(item, args)
|
||||||
|
|
||||||
|
def check_overflow_with_tolerance(self, item, args):
|
||||||
|
"""
|
||||||
|
Checks if there is overflow condering a relaxation tolerance
|
||||||
|
"""
|
||||||
|
|
||||||
|
# check if overflow is within tolerance
|
||||||
|
tolerance = self.get_tolerance_for(item['item_code'])
|
||||||
|
overflow_percent = ((item[args['target_field']] - item[args['target_ref_field']]) /
|
||||||
|
item[args['target_ref_field']]) * 100
|
||||||
|
|
||||||
|
if overflow_percent - tolerance > 0.01:
|
||||||
|
item['max_allowed'] = flt(item[args['target_ref_field']] * (100+tolerance)/100)
|
||||||
|
item['reduce_by'] = item[args['target_field']] - item['max_allowed']
|
||||||
|
|
||||||
|
msgprint("""
|
||||||
|
Row #%(idx)s: Max %(target_ref_field)s allowed for <b>Item %(item_code)s</b> \
|
||||||
|
against <b>%(parenttype)s %(parent)s</b> is <b>%(max_allowed)s</b>.
|
||||||
|
|
||||||
|
If you want to increase your overflow tolerance, please increase tolerance %% in \
|
||||||
|
Global Defaults or Item master.
|
||||||
|
|
||||||
|
Or, you must reduce the %(target_ref_field)s by %(reduce_by)s
|
||||||
|
|
||||||
|
Also, please check if the order item has already been billed in the Sales Order""" %
|
||||||
|
item, raise_exception=1)
|
||||||
|
|
||||||
|
def get_tolerance_for(self, item_code):
|
||||||
|
"""
|
||||||
|
Returns the tolerance for the item, if not set, returns global tolerance
|
||||||
|
"""
|
||||||
|
if self.tolerance.get(item_code): return self.tolerance[item_code]
|
||||||
|
|
||||||
|
tolerance = flt(webnotes.conn.get_value('Item',item_code,'tolerance') or 0)
|
||||||
|
|
||||||
|
if not tolerance:
|
||||||
|
if self.global_tolerance == None:
|
||||||
|
self.global_tolerance = flt(webnotes.conn.get_value('Global Defaults', None,
|
||||||
|
'tolerance'))
|
||||||
|
tolerance = self.global_tolerance
|
||||||
|
|
||||||
|
self.tolerance[item_code] = tolerance
|
||||||
|
return tolerance
|
||||||
|
|
||||||
|
|
||||||
|
def update_qty(self, change_modified=True):
|
||||||
|
"""
|
||||||
|
Updates qty at row level
|
||||||
|
"""
|
||||||
|
for args in self.status_updater:
|
||||||
|
# condition to include current record (if submit or no if cancel)
|
||||||
|
if self.doc.docstatus == 1:
|
||||||
|
args['cond'] = ' or parent="%s"' % self.doc.name
|
||||||
|
else:
|
||||||
|
args['cond'] = ' and parent!="%s"' % self.doc.name
|
||||||
|
|
||||||
|
args['modified_cond'] = ''
|
||||||
|
if change_modified:
|
||||||
|
args['modified_cond'] = ', modified = now()'
|
||||||
|
|
||||||
|
# update quantities in child table
|
||||||
|
for d in self.doclist:
|
||||||
|
if d.doctype == args['source_dt']:
|
||||||
|
# updates qty in the child table
|
||||||
|
args['detail_id'] = d.fields.get(args['join_field'])
|
||||||
|
|
||||||
|
args['second_source_condition'] = ""
|
||||||
|
if args.get('second_source_dt') and args.get('second_source_field') \
|
||||||
|
and args.get('second_join_field'):
|
||||||
|
args['second_source_condition'] = """ + (select sum(%(second_source_field)s)
|
||||||
|
from `tab%(second_source_dt)s`
|
||||||
|
where `%(second_join_field)s`="%(detail_id)s"
|
||||||
|
and (docstatus=1))""" % args
|
||||||
|
|
||||||
|
if args['detail_id']:
|
||||||
|
webnotes.conn.sql("""update `tab%(target_dt)s`
|
||||||
|
set %(target_field)s = (select sum(%(source_field)s)
|
||||||
|
from `tab%(source_dt)s` where `%(join_field)s`="%(detail_id)s"
|
||||||
|
and (docstatus=1 %(cond)s)) %(second_source_condition)s
|
||||||
|
where name='%(detail_id)s'""" % args)
|
||||||
|
|
||||||
|
# get unique transactions to update
|
||||||
|
for name in set([d.fields.get(args['percent_join_field']) for d in self.doclist
|
||||||
|
if d.doctype == args['source_dt']]):
|
||||||
|
if name:
|
||||||
|
args['name'] = name
|
||||||
|
|
||||||
|
# update percent complete in the parent table
|
||||||
|
webnotes.conn.sql("""update `tab%(target_parent_dt)s`
|
||||||
|
set %(target_parent_field)s = (select sum(if(%(target_ref_field)s >
|
||||||
|
ifnull(%(target_field)s, 0), %(target_field)s,
|
||||||
|
%(target_ref_field)s))/sum(%(target_ref_field)s)*100
|
||||||
|
from `tab%(target_dt)s` where parent="%(name)s") %(modified_cond)s
|
||||||
|
where name='%(name)s'""" % args)
|
||||||
|
|
||||||
|
# update field
|
||||||
|
if args.get('status_field'):
|
||||||
|
webnotes.conn.sql("""update `tab%(target_parent_dt)s`
|
||||||
|
set %(status_field)s = if(ifnull(%(target_parent_field)s,0)<0.001,
|
||||||
|
'Not %(keyword)s', if(%(target_parent_field)s>=99.99,
|
||||||
|
'Fully %(keyword)s', 'Partly %(keyword)s'))
|
||||||
|
where name='%(name)s'""" % args)
|
@ -266,22 +266,27 @@ class DocType:
|
|||||||
for b in boms:
|
for b in boms:
|
||||||
if b[0] == self.doc.name:
|
if b[0] == self.doc.name:
|
||||||
msgprint("""Recursion Occured => '%s' cannot be '%s' of '%s'.
|
msgprint("""Recursion Occured => '%s' cannot be '%s' of '%s'.
|
||||||
""" % (cstr(b), cstr(d[2]), self.doc.name), raise_exception = 1)
|
""" % (cstr(b[0]), cstr(d[2]), self.doc.name), raise_exception = 1)
|
||||||
if b[0]:
|
if b[0]:
|
||||||
bom_list.append(b[0])
|
bom_list.append(b[0])
|
||||||
|
|
||||||
def update_cost_and_exploded_items(self):
|
def update_cost_and_exploded_items(self, bom_list=[]):
|
||||||
bom_list = self.traverse_tree()
|
bom_list = self.traverse_tree(bom_list)
|
||||||
for bom in bom_list:
|
for bom in bom_list:
|
||||||
bom_obj = get_obj("BOM", bom, with_children=1)
|
bom_obj = get_obj("BOM", bom, with_children=1)
|
||||||
bom_obj.on_update()
|
bom_obj.on_update()
|
||||||
|
|
||||||
def traverse_tree(self):
|
return bom_list
|
||||||
|
|
||||||
|
def traverse_tree(self, bom_list=[]):
|
||||||
def _get_children(bom_no):
|
def _get_children(bom_no):
|
||||||
return [cstr(d[0]) for d in webnotes.conn.sql("""select bom_no from `tabBOM Item`
|
return [cstr(d[0]) for d in webnotes.conn.sql("""select bom_no from `tabBOM Item`
|
||||||
where parent = %s and ifnull(bom_no, '') != ''""", bom_no)]
|
where parent = %s and ifnull(bom_no, '') != ''""", bom_no)]
|
||||||
|
|
||||||
bom_list, count = [self.doc.name], 0
|
count = 0
|
||||||
|
if self.doc.name not in bom_list:
|
||||||
|
bom_list.append(self.doc.name)
|
||||||
|
|
||||||
while(count < len(bom_list)):
|
while(count < len(bom_list)):
|
||||||
for child_bom in _get_children(bom_list[count]):
|
for child_bom in _get_children(bom_list[count]):
|
||||||
if child_bom not in bom_list:
|
if child_bom not in bom_list:
|
||||||
@ -325,52 +330,50 @@ class DocType:
|
|||||||
|
|
||||||
def get_exploded_items(self):
|
def get_exploded_items(self):
|
||||||
""" Get all raw materials including items from child bom"""
|
""" Get all raw materials including items from child bom"""
|
||||||
self.cur_exploded_items = []
|
self.cur_exploded_items = {}
|
||||||
for d in getlist(self.doclist, 'bom_materials'):
|
for d in getlist(self.doclist, 'bom_materials'):
|
||||||
if d.bom_no:
|
if d.bom_no:
|
||||||
self.get_child_exploded_items(d.bom_no, d.qty)
|
self.get_child_exploded_items(d.bom_no, d.qty)
|
||||||
else:
|
else:
|
||||||
self.cur_exploded_items.append({
|
self.add_to_cur_exploded_items(webnotes._dict({
|
||||||
'item_code' : d.item_code,
|
'item_code' : d.item_code,
|
||||||
'description' : d.description,
|
'description' : d.description,
|
||||||
'stock_uom' : d.stock_uom,
|
'stock_uom' : d.stock_uom,
|
||||||
'qty' : flt(d.qty),
|
'qty' : flt(d.qty),
|
||||||
'rate' : flt(d.rate),
|
'rate' : flt(d.rate),
|
||||||
'amount' : flt(d.amount),
|
}))
|
||||||
'parent_bom' : d.parent,
|
|
||||||
'mat_detail_no' : d.name,
|
def add_to_cur_exploded_items(self, args):
|
||||||
'qty_consumed_per_unit' : flt(d.qty_consumed_per_unit)
|
if self.cur_exploded_items.get(args.item_code):
|
||||||
})
|
self.cur_exploded_items[args.item_code]["qty"] += args.qty
|
||||||
|
else:
|
||||||
|
self.cur_exploded_items[args.item_code] = args
|
||||||
|
|
||||||
def get_child_exploded_items(self, bom_no, qty):
|
def get_child_exploded_items(self, bom_no, qty):
|
||||||
""" Add all items from Flat BOM of child BOM"""
|
""" Add all items from Flat BOM of child BOM"""
|
||||||
|
|
||||||
child_fb_items = sql("""select item_code, description, stock_uom, qty, rate,
|
child_fb_items = sql("""select item_code, description, stock_uom, qty, rate,
|
||||||
amount, parent_bom, mat_detail_no, qty_consumed_per_unit
|
qty_consumed_per_unit from `tabBOM Explosion Item`
|
||||||
from `tabBOM Explosion Item` where parent = '%s' and docstatus = 1""" %
|
where parent = %s and docstatus = 1""", bom_no, as_dict = 1)
|
||||||
bom_no, as_dict = 1)
|
|
||||||
for d in child_fb_items:
|
for d in child_fb_items:
|
||||||
self.cur_exploded_items.append({
|
self.add_to_cur_exploded_items(webnotes._dict({
|
||||||
'item_code' : d['item_code'],
|
'item_code' : d['item_code'],
|
||||||
'description' : d['description'],
|
'description' : d['description'],
|
||||||
'stock_uom' : d['stock_uom'],
|
'stock_uom' : d['stock_uom'],
|
||||||
'qty' : flt(d['qty_consumed_per_unit'])*qty,
|
'qty' : flt(d['qty_consumed_per_unit'])*qty,
|
||||||
'rate' : flt(d['rate']),
|
'rate' : flt(d['rate']),
|
||||||
'amount' : flt(d['amount']),
|
}))
|
||||||
'parent_bom' : d['parent_bom'],
|
|
||||||
'mat_detail_no' : d['mat_detail_no'],
|
|
||||||
'qty_consumed_per_unit' : flt(d['qty_consumed_per_unit'])*qty/flt(self.doc.quantity)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
def add_exploded_items(self):
|
def add_exploded_items(self):
|
||||||
"Add items to Flat BOM table"
|
"Add items to Flat BOM table"
|
||||||
self.doclist = self.doc.clear_table(self.doclist, 'flat_bom_details', 1)
|
self.doclist = self.doc.clear_table(self.doclist, 'flat_bom_details', 1)
|
||||||
for d in self.cur_exploded_items:
|
for d in self.cur_exploded_items:
|
||||||
ch = addchild(self.doc, 'flat_bom_details', 'BOM Explosion Item',
|
ch = addchild(self.doc, 'flat_bom_details', 'BOM Explosion Item', self.doclist)
|
||||||
self.doclist)
|
for i in self.cur_exploded_items[d].keys():
|
||||||
for i in d.keys():
|
ch.fields[i] = self.cur_exploded_items[d][i]
|
||||||
ch.fields[i] = d[i]
|
ch.amount = flt(ch.qty) * flt(ch.rate)
|
||||||
|
ch.qty_consumed_per_unit = flt(ch.qty) / flt(self.doc.quantity)
|
||||||
ch.docstatus = self.doc.docstatus
|
ch.docstatus = self.doc.docstatus
|
||||||
ch.save(1)
|
ch.save(1)
|
||||||
|
|
||||||
|
@ -48,134 +48,4 @@ test_records = [
|
|||||||
"stock_uom": "No."
|
"stock_uom": "No."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# import webnotes.model
|
|
||||||
# from webnotes.utils import nowdate, flt
|
|
||||||
# from accounts.utils import get_fiscal_year
|
|
||||||
# from webnotes.model.doclist import DocList
|
|
||||||
# import copy
|
|
||||||
#
|
|
||||||
# company = webnotes.conn.get_default("company")
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# def load_data():
|
|
||||||
#
|
|
||||||
# # create default warehouse
|
|
||||||
# if not webnotes.conn.exists("Warehouse", "Default Warehouse"):
|
|
||||||
# webnotes.insert({"doctype": "Warehouse",
|
|
||||||
# "warehouse_name": "Default Warehouse",
|
|
||||||
# "warehouse_type": "Stores"})
|
|
||||||
#
|
|
||||||
# # create UOM: Nos.
|
|
||||||
# if not webnotes.conn.exists("UOM", "Nos"):
|
|
||||||
# webnotes.insert({"doctype": "UOM", "uom_name": "Nos"})
|
|
||||||
#
|
|
||||||
# from webnotes.tests import insert_test_data
|
|
||||||
# # create item groups and items
|
|
||||||
# insert_test_data("Item Group",
|
|
||||||
# sort_fn=lambda ig: (ig[0].get('parent_item_group'), ig[0].get('name')))
|
|
||||||
# insert_test_data("Item")
|
|
||||||
#
|
|
||||||
# base_bom_fg = [
|
|
||||||
# {"doctype": "BOM", "item": "Android Jack D", "quantity": 1,
|
|
||||||
# "is_active": "Yes", "is_default": 1, "uom": "Nos"},
|
|
||||||
# {"doctype": "BOM Operation", "operation_no": 1, "parentfield": "bom_operations",
|
|
||||||
# "opn_description": "Development", "hour_rate": 10, "time_in_mins": 90},
|
|
||||||
# {"doctype": "BOM Item", "item_code": "Home Desktop 300", "operation_no": 1,
|
|
||||||
# "qty": 2, "rate": 20, "stock_uom": "Nos", "parentfield": "bom_materials"},
|
|
||||||
# {"doctype": "BOM Item", "item_code": "Home Desktop 100", "operation_no": 1,
|
|
||||||
# "qty": 1, "rate": 300, "stock_uom": "Nos", "parentfield": "bom_materials"},
|
|
||||||
# {"doctype": "BOM Item", "item_code": "Nebula 7", "operation_no": 1,
|
|
||||||
# "qty": 5, "stock_uom": "Nos", "parentfield": "bom_materials"},
|
|
||||||
# ]
|
|
||||||
#
|
|
||||||
# base_bom_child = [
|
|
||||||
# {"doctype": "BOM", "item": "Nebula 7", "quantity": 5,
|
|
||||||
# "is_active": "Yes", "is_default": 1, "uom": "Nos"},
|
|
||||||
# {"doctype": "BOM Operation", "operation_no": 1, "parentfield": "bom_operations",
|
|
||||||
# "opn_description": "Development"},
|
|
||||||
# {"doctype": "BOM Item", "item_code": "Android Jack S", "operation_no": 1,
|
|
||||||
# "qty": 10, "stock_uom": "Nos", "parentfield": "bom_materials"}
|
|
||||||
# ]
|
|
||||||
#
|
|
||||||
# base_bom_grandchild = [
|
|
||||||
# {"doctype": "BOM", "item": "Android Jack S", "quantity": 1,
|
|
||||||
# "is_active": "Yes", "is_default": 1, "uom": "Nos"},
|
|
||||||
# {"doctype": "BOM Operation", "operation_no": 1, "parentfield": "bom_operations",
|
|
||||||
# "opn_description": "Development"},
|
|
||||||
# {"doctype": "BOM Item", "item_code": "Home Desktop 300", "operation_no": 1,
|
|
||||||
# "qty": 3, "rate": 10, "stock_uom": "Nos", "parentfield": "bom_materials"}
|
|
||||||
# ]
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# class TestPurchaseReceipt(unittest.TestCase):
|
|
||||||
# def setUp(self):
|
|
||||||
# webnotes.conn.begin()
|
|
||||||
# load_data()
|
|
||||||
#
|
|
||||||
# def test_bom_validation(self):
|
|
||||||
# # show throw error bacause bom no missing for sub-assembly item
|
|
||||||
# bom_fg = copy.deepcopy(base_bom_fg)
|
|
||||||
# self.assertRaises(webnotes.ValidationError, webnotes.insert, DocList(bom_fg))
|
|
||||||
#
|
|
||||||
# # main item is not a manufacturing item
|
|
||||||
# bom_fg = copy.deepcopy(base_bom_fg)
|
|
||||||
# bom_fg[0]["item"] = "Home Desktop 200"
|
|
||||||
# bom_fg.pop(4)
|
|
||||||
# self.assertRaises(webnotes.ValidationError, webnotes.insert, DocList(bom_fg))
|
|
||||||
#
|
|
||||||
# # operation no mentioed in material table not matching with operation table
|
|
||||||
# bom_fg = copy.deepcopy(base_bom_fg)
|
|
||||||
# bom_fg.pop(4)
|
|
||||||
# bom_fg[2]["operation_no"] = 2
|
|
||||||
# self.assertRaises(webnotes.ValidationError, webnotes.insert, DocList(bom_fg))
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# def test_bom(self):
|
|
||||||
# gc_wrapper = webnotes.insert(DocList(base_bom_grandchild))
|
|
||||||
# gc_wrapper.submit()
|
|
||||||
#
|
|
||||||
# bom_child = copy.deepcopy(base_bom_child)
|
|
||||||
# bom_child[2]["bom_no"] = gc_wrapper.doc.name
|
|
||||||
# child_wrapper = webnotes.insert(DocList(bom_child))
|
|
||||||
# child_wrapper.submit()
|
|
||||||
#
|
|
||||||
# bom_fg = copy.deepcopy(base_bom_fg)
|
|
||||||
# bom_fg[4]["bom_no"] = child_wrapper.doc.name
|
|
||||||
# fg_wrapper = webnotes.insert(DocList(bom_fg))
|
|
||||||
# fg_wrapper.load_from_db()
|
|
||||||
#
|
|
||||||
# self.check_bom_cost(fg_wrapper)
|
|
||||||
#
|
|
||||||
# self.check_flat_bom(fg_wrapper, child_wrapper, gc_wrapper)
|
|
||||||
#
|
|
||||||
# def check_bom_cost(self, fg_wrapper):
|
|
||||||
# expected_values = {
|
|
||||||
# "operating_cost": 15,
|
|
||||||
# "raw_material_cost": 640,
|
|
||||||
# "total_cost": 655
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# for key in expected_values:
|
|
||||||
# self.assertEqual(flt(expected_values[key]), flt(fg_wrapper.doc.fields.get(key)))
|
|
||||||
#
|
|
||||||
# def check_flat_bom(self, fg_wrapper, child_wrapper, gc_wrapper):
|
|
||||||
# expected_flat_bom_items = {
|
|
||||||
# ("Home Desktop 300", fg_wrapper.doc.name): (2, 20),
|
|
||||||
# ("Home Desktop 100", fg_wrapper.doc.name): (1, 300),
|
|
||||||
# ("Home Desktop 300", gc_wrapper.doc.name): (30, 10)
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# self.assertEqual(len(fg_wrapper.doclist.get({"parentfield": "flat_bom_details"})), 3)
|
|
||||||
#
|
|
||||||
# for key, val in expected_flat_bom_items.items():
|
|
||||||
# flat_bom = fg_wrapper.doclist.get({"parentfield": "flat_bom_details",
|
|
||||||
# "item_code": key[0], "parent_bom": key[1]})[0]
|
|
||||||
# self.assertEqual(val, (flat_bom.qty, flat_bom.rate))
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# def tearDown(self):
|
|
||||||
# webnotes.conn.rollback()
|
|
@ -1,8 +1,8 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"creation": "2013-02-22 01:27:48",
|
"creation": "2013-03-07 11:42:57",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-03-07 07:03:18",
|
"modified": "2013-06-04 13:13:28",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -80,25 +80,6 @@
|
|||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "UOM"
|
"options": "UOM"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"doctype": "DocField",
|
|
||||||
"fieldname": "parent_bom",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"label": "Parent BOM",
|
|
||||||
"oldfieldname": "parent_bom",
|
|
||||||
"oldfieldtype": "Link",
|
|
||||||
"options": "BOM",
|
|
||||||
"print_width": "250px",
|
|
||||||
"width": "250px"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"doctype": "DocField",
|
|
||||||
"fieldname": "mat_detail_no",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 1,
|
|
||||||
"label": "Mat Detail No"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "qty_consumed_per_unit",
|
"fieldname": "qty_consumed_per_unit",
|
||||||
|
@ -29,9 +29,10 @@ class DocType:
|
|||||||
self.validate_bom()
|
self.validate_bom()
|
||||||
self.update_new_bom()
|
self.update_new_bom()
|
||||||
bom_list = self.get_parent_boms()
|
bom_list = self.get_parent_boms()
|
||||||
|
updated_bom = []
|
||||||
for bom in bom_list:
|
for bom in bom_list:
|
||||||
bom_obj = get_obj("BOM", bom, with_children=1)
|
bom_obj = get_obj("BOM", bom, with_children=1)
|
||||||
bom_obj.update_cost_and_exploded_items()
|
updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom)
|
||||||
|
|
||||||
webnotes.msgprint(_("BOM replaced"))
|
webnotes.msgprint(_("BOM replaced"))
|
||||||
|
|
||||||
|
@ -241,40 +241,30 @@ class DocType:
|
|||||||
def get_raw_materials(self, bom_dict):
|
def get_raw_materials(self, bom_dict):
|
||||||
""" Get raw materials considering sub-assembly items
|
""" Get raw materials considering sub-assembly items
|
||||||
{
|
{
|
||||||
"item_code": [qty_required, description, stock_uom]
|
"item_code": [qty_required, description, stock_uom, min_order_qty]
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
for bom in bom_dict:
|
for bom in bom_dict:
|
||||||
if self.doc.use_multi_level_bom:
|
if self.doc.use_multi_level_bom:
|
||||||
# get all raw materials with sub assembly childs
|
# get all raw materials with sub assembly childs
|
||||||
fl_bom_items = sql("""
|
fl_bom_items = sql("""select fb.item_code,
|
||||||
select
|
ifnull(sum(fb.qty_consumed_per_unit), 0)*%s as qty,
|
||||||
item_code,ifnull(sum(qty_consumed_per_unit),0)*%s as qty,
|
fb.description, fb.stock_uom, it.min_order_qty
|
||||||
description, stock_uom, min_order_qty
|
from `tabBOM Explosion Item` fb,`tabItem` it
|
||||||
from
|
where it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No'
|
||||||
(
|
and ifnull(it.is_sub_contracted_item, 'No') = 'No'
|
||||||
select distinct fb.name, fb.description, fb.item_code,
|
and fb.docstatus<2 and fb.parent=%s
|
||||||
fb.qty_consumed_per_unit, fb.stock_uom, it.min_order_qty
|
group by item_code, stock_uom""", (flt(bom_dict[bom]), bom))
|
||||||
from `tabBOM Explosion Item` fb,`tabItem` it
|
|
||||||
where it.name = fb.item_code
|
|
||||||
and ifnull(it.is_pro_applicable, 'No') = 'No'
|
|
||||||
and ifnull(it.is_sub_contracted_item, 'No') = 'No'
|
|
||||||
and fb.docstatus<2 and fb.parent=%s
|
|
||||||
) a
|
|
||||||
group by item_code,stock_uom
|
|
||||||
""" , (flt(bom_dict[bom]), bom))
|
|
||||||
else:
|
else:
|
||||||
# Get all raw materials considering SA items as raw materials,
|
# Get all raw materials considering SA items as raw materials,
|
||||||
# so no childs of SA items
|
# so no childs of SA items
|
||||||
fl_bom_items = sql("""
|
fl_bom_items = sql("""select bom_item.item_code,
|
||||||
select bom_item.item_code,
|
|
||||||
ifnull(sum(bom_item.qty_consumed_per_unit), 0) * %s,
|
ifnull(sum(bom_item.qty_consumed_per_unit), 0) * %s,
|
||||||
bom_item.description, bom_item.stock_uom, item.min_order_qty
|
bom_item.description, bom_item.stock_uom, item.min_order_qty
|
||||||
from `tabBOM Item` bom_item, tabItem item
|
from `tabBOM Item` bom_item, tabItem item
|
||||||
where bom_item.parent = %s and bom_item.docstatus < 2
|
where bom_item.parent = %s and bom_item.docstatus < 2
|
||||||
and bom_item.item_code = item.name
|
and bom_item.item_code = item.name
|
||||||
group by item_code
|
group by item_code""", (flt(bom_dict[bom]), bom))
|
||||||
""", (flt(bom_dict[bom]), bom))
|
|
||||||
self.make_items_dict(fl_bom_items)
|
self.make_items_dict(fl_bom_items)
|
||||||
|
|
||||||
def make_items_dict(self, item_list):
|
def make_items_dict(self, item_list):
|
||||||
@ -317,9 +307,9 @@ class DocType:
|
|||||||
|
|
||||||
items_to_be_requested = webnotes._dict()
|
items_to_be_requested = webnotes._dict()
|
||||||
for item in self.item_dict:
|
for item in self.item_dict:
|
||||||
if flt(self.item_dict[item][0]) > item_projected_qty[item]:
|
if flt(self.item_dict[item][0]) > item_projected_qty.get(item, 0):
|
||||||
# shortage
|
# shortage
|
||||||
requested_qty = flt(self.item_dict[item][0]) - item_projected_qty[item]
|
requested_qty = flt(self.item_dict[item][0]) - item_projected_qty.get(item, 0)
|
||||||
# comsider minimum order qty
|
# comsider minimum order qty
|
||||||
requested_qty = requested_qty > flt(self.item_dict[item][3]) and \
|
requested_qty = requested_qty > flt(self.item_dict[item][3]) and \
|
||||||
requested_qty or flt(self.item_dict[item][3])
|
requested_qty or flt(self.item_dict[item][3])
|
||||||
@ -379,4 +369,4 @@ class DocType:
|
|||||||
webnotes.msgprint("Following Material Request created successfully: \n%s" %
|
webnotes.msgprint("Following Material Request created successfully: \n%s" %
|
||||||
"\n".join(pur_req))
|
"\n".join(pur_req))
|
||||||
else:
|
else:
|
||||||
webnotes.msgprint("Nothing to request")
|
webnotes.msgprint("Nothing to request")
|
||||||
|
@ -2,11 +2,13 @@ import webnotes, os, webnotes.utils
|
|||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
files_path = webnotes.utils.get_path("public", "files")
|
files_path = webnotes.utils.get_path("public", "files")
|
||||||
|
webnotes.conn.auto_commit_on_many_writes = 1
|
||||||
|
|
||||||
for f in webnotes.conn.sql("""select name, file_name from
|
for f in webnotes.conn.sql("""select name, file_name from
|
||||||
`tabFile Data`""", as_dict=True):
|
`tabFile Data`""", as_dict=True):
|
||||||
if f.file_name:
|
if f.file_name:
|
||||||
filepath = os.path.join(files_path, f.file_name)
|
filepath = os.path.join(files_path, f.file_name)
|
||||||
if os.path.exists(filepath):
|
if os.path.exists(filepath):
|
||||||
webnotes.conn.set_value("File Data", f.name, "file_size", os.stat(filepath).st_size)
|
webnotes.conn.set_value("File Data", f.name, "file_size", os.stat(filepath).st_size)
|
||||||
|
|
||||||
|
webnotes.conn.auto_commit_on_many_writes = 0
|
@ -2,6 +2,8 @@ import webnotes
|
|||||||
def execute():
|
def execute():
|
||||||
from patches.april_2013.p05_update_file_data import update_file_list, get_single_doctypes
|
from patches.april_2013.p05_update_file_data import update_file_list, get_single_doctypes
|
||||||
|
|
||||||
|
webnotes.conn.auto_commit_on_many_writes = 1
|
||||||
|
|
||||||
singles = get_single_doctypes()
|
singles = get_single_doctypes()
|
||||||
for doctype in webnotes.conn.sql_list("""select table_name from `information_schema`.`columns`
|
for doctype in webnotes.conn.sql_list("""select table_name from `information_schema`.`columns`
|
||||||
where table_schema=%s and column_name='file_list'""", webnotes.conn.cur_db_name):
|
where table_schema=%s and column_name='file_list'""", webnotes.conn.cur_db_name):
|
||||||
@ -13,4 +15,5 @@ def execute():
|
|||||||
|
|
||||||
webnotes.conn.sql("""delete from `tabCustom Field` where fieldname='file_list'
|
webnotes.conn.sql("""delete from `tabCustom Field` where fieldname='file_list'
|
||||||
and parent=%s""", doctype)
|
and parent=%s""", doctype)
|
||||||
|
|
||||||
|
webnotes.conn.auto_commit_on_many_writes = 0
|
0
patches/june_2013/__init__.py
Normal file
0
patches/june_2013/__init__.py
Normal file
29
patches/june_2013/p01_update_bom_exploded_items.py
Normal file
29
patches/june_2013/p01_update_bom_exploded_items.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# ERPNext - web based ERP (http://erpnext.com)
|
||||||
|
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import webnotes
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
updated_bom = []
|
||||||
|
for bom in webnotes.conn.sql("select name from tabBOM where docstatus < 2"):
|
||||||
|
if bom[0] not in updated_bom:
|
||||||
|
try:
|
||||||
|
bom_obj = webnotes.get_obj("BOM", bom[0], with_children=1)
|
||||||
|
updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom)
|
||||||
|
webnotes.conn.commit()
|
||||||
|
except:
|
||||||
|
pass
|
24
patches/may_2013/p06_update_billed_amt_po_pr.py
Normal file
24
patches/may_2013/p06_update_billed_amt_po_pr.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# ERPNext - web based ERP (http://erpnext.com)
|
||||||
|
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
def execute():
|
||||||
|
import webnotes
|
||||||
|
webnotes.reload_doc("buying", "doctype", "purchase_order_item")
|
||||||
|
webnotes.reload_doc("stock", "doctype", "purchase_receipt_item")
|
||||||
|
for pi in webnotes.conn.sql("""select name from `tabPurchase Invoice` where docstatus = 1"""):
|
||||||
|
webnotes.get_obj("Purchase Invoice", pi[0],
|
||||||
|
with_children=1).update_qty(change_modified=False)
|
@ -254,6 +254,8 @@ patch_list = [
|
|||||||
"patches.may_2013.p04_reorder_level",
|
"patches.may_2013.p04_reorder_level",
|
||||||
"patches.may_2013.p05_update_cancelled_gl_entries",
|
"patches.may_2013.p05_update_cancelled_gl_entries",
|
||||||
"patches.may_2013.p06_make_notes",
|
"patches.may_2013.p06_make_notes",
|
||||||
|
"patches.may_2013.p06_update_billed_amt_po_pr",
|
||||||
"patches.may_2013.p07_move_update_stock_to_pos",
|
"patches.may_2013.p07_move_update_stock_to_pos",
|
||||||
"patches.may_2013.p08_change_item_wise_tax",
|
"patches.may_2013.p08_change_item_wise_tax",
|
||||||
|
"patches.june_2013.p01_update_bom_exploded_items",
|
||||||
]
|
]
|
@ -60,6 +60,11 @@ wn.module_page["Projects"] = [
|
|||||||
route: "query-report/Daily Time Log Summary",
|
route: "query-report/Daily Time Log Summary",
|
||||||
doctype: "Time Log"
|
doctype: "Time Log"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label":wn._("Project wise Stock Tracking"),
|
||||||
|
route: "query-report/Project wise Stock Tracking",
|
||||||
|
doctype: "Project"
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
# ERPNext - web based ERP (http://erpnext.com)
|
||||||
|
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import webnotes
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
columns = get_columns()
|
||||||
|
proj_details = get_project_details()
|
||||||
|
pr_item_map = get_purchased_items_cost()
|
||||||
|
se_item_map = get_issued_items_cost()
|
||||||
|
dn_item_map = get_delivered_items_cost()
|
||||||
|
|
||||||
|
data = []
|
||||||
|
for project in proj_details:
|
||||||
|
data.append([project.name, pr_item_map.get(project.name, 0),
|
||||||
|
se_item_map.get(project.name, 0), dn_item_map.get(project.name, 0),
|
||||||
|
project.project_name, project.status, project.company,
|
||||||
|
project.customer, project.project_value, project.project_start_date,
|
||||||
|
project.completion_date])
|
||||||
|
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
def get_columns():
|
||||||
|
return ["Project Id:Link/Project:140", "Cost of Purchased Items:Currency:160",
|
||||||
|
"Cost of Issued Items:Currency:160", "Cost of Delivered Items:Currency:160",
|
||||||
|
"Project Name::120", "Project Status::120", "Company:Link/Company:100",
|
||||||
|
"Customer:Link/Customer:140", "Project Value:Currency:120",
|
||||||
|
"Project Start Date:Date:120", "Completion Date:Date:120"]
|
||||||
|
|
||||||
|
def get_project_details():
|
||||||
|
return webnotes.conn.sql(""" select name, project_name, status, company, customer, project_value,
|
||||||
|
project_start_date, completion_date from tabProject where docstatus < 2""", as_dict=1)
|
||||||
|
|
||||||
|
def get_purchased_items_cost():
|
||||||
|
pr_items = webnotes.conn.sql("""select project_name, sum(amount) as amount
|
||||||
|
from `tabPurchase Receipt Item` where ifnull(project_name, '') != ''
|
||||||
|
and docstatus = 1 group by project_name""", as_dict=1)
|
||||||
|
|
||||||
|
pr_item_map = {}
|
||||||
|
for item in pr_items:
|
||||||
|
pr_item_map.setdefault(item.project_name, item.amount)
|
||||||
|
|
||||||
|
return pr_item_map
|
||||||
|
|
||||||
|
def get_issued_items_cost():
|
||||||
|
se_items = webnotes.conn.sql("""select se.project_name, sum(se_item.amount) as amount
|
||||||
|
from `tabStock Entry` se, `tabStock Entry Detail` se_item
|
||||||
|
where se.name = se_item.parent and se.docstatus = 1 and ifnull(se_item.t_warehouse, '') = ''
|
||||||
|
and ifnull(se.project_name, '') != '' group by se.project_name""", as_dict=1)
|
||||||
|
|
||||||
|
se_item_map = {}
|
||||||
|
for item in se_items:
|
||||||
|
se_item_map.setdefault(item.project_name, item.amount)
|
||||||
|
|
||||||
|
return se_item_map
|
||||||
|
|
||||||
|
def get_delivered_items_cost():
|
||||||
|
dn_items = webnotes.conn.sql("""select dn.project_name, sum(dn_item.amount) as amount
|
||||||
|
from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item
|
||||||
|
where dn.name = dn_item.parent and dn.docstatus = 1 and ifnull(dn.project_name, '') != ''
|
||||||
|
group by dn.project_name""", as_dict=1)
|
||||||
|
|
||||||
|
si_items = webnotes.conn.sql("""select si.project_name, sum(si_item.amount) as amount
|
||||||
|
from `tabSales Invoice` si, `tabSales Invoice Item` si_item
|
||||||
|
where si.name = si_item.parent and si.docstatus = 1 and ifnull(si.update_stock, 0) = 1
|
||||||
|
and ifnull(si.is_pos, 0) = 1 and ifnull(si.project_name, '') != ''
|
||||||
|
group by si.project_name""", as_dict=1)
|
||||||
|
|
||||||
|
|
||||||
|
dn_item_map = {}
|
||||||
|
for item in dn_items:
|
||||||
|
dn_item_map.setdefault(item.project_name, item.amount)
|
||||||
|
|
||||||
|
for item in si_items:
|
||||||
|
dn_item_map.setdefault(item.project_name, item.amount)
|
||||||
|
|
||||||
|
return dn_item_map
|
@ -0,0 +1,21 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"creation": "2013-06-03 17:37:41",
|
||||||
|
"docstatus": 0,
|
||||||
|
"modified": "2013-06-03 17:37:41",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"owner": "Administrator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Report",
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"name": "__common__",
|
||||||
|
"ref_doctype": "Project",
|
||||||
|
"report_name": "Project wise Stock Tracking ",
|
||||||
|
"report_type": "Report Builder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"doctype": "Report",
|
||||||
|
"name": "Project wise Stock Tracking"
|
||||||
|
}
|
||||||
|
]
|
@ -21,10 +21,7 @@ from webnotes.utils import cstr, getdate
|
|||||||
from webnotes.model.bean import getlist
|
from webnotes.model.bean import getlist
|
||||||
from webnotes.model.code import get_obj
|
from webnotes.model.code import get_obj
|
||||||
from webnotes import msgprint
|
from webnotes import msgprint
|
||||||
from stock.utils import get_valid_serial_nos
|
from stock.utils import get_valid_serial_nos
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
|
||||||
|
|
||||||
|
|
||||||
from utilities.transaction_base import TransactionBase
|
from utilities.transaction_base import TransactionBase
|
||||||
|
|
||||||
@ -34,6 +31,19 @@ class DocType(TransactionBase):
|
|||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
self.tname = 'Installation Note Item'
|
self.tname = 'Installation Note Item'
|
||||||
self.fname = 'installed_item_details'
|
self.fname = 'installed_item_details'
|
||||||
|
self.status_updater = [{
|
||||||
|
'source_dt': 'Installation Note Item',
|
||||||
|
'target_dt': 'Delivery Note Item',
|
||||||
|
'target_field': 'installed_qty',
|
||||||
|
'target_ref_field': 'qty',
|
||||||
|
'join_field': 'prevdoc_detail_docname',
|
||||||
|
'target_parent_dt': 'Delivery Note',
|
||||||
|
'target_parent_field': 'per_installed',
|
||||||
|
'source_field': 'qty',
|
||||||
|
'percent_join_field': 'prevdoc_docname',
|
||||||
|
'status_field': 'installation_status',
|
||||||
|
'keyword': 'Installed'
|
||||||
|
}]
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_fiscal_year()
|
self.validate_fiscal_year()
|
||||||
@ -45,153 +55,114 @@ class DocType(TransactionBase):
|
|||||||
self.validate_mandatory()
|
self.validate_mandatory()
|
||||||
self.validate_reference_value()
|
self.validate_reference_value()
|
||||||
|
|
||||||
|
|
||||||
#fetch delivery note details
|
|
||||||
#====================================
|
|
||||||
def pull_delivery_note_details(self):
|
def pull_delivery_note_details(self):
|
||||||
self.validate_prev_docname()
|
self.validate_prev_docname()
|
||||||
self.doclist = get_obj('DocType Mapper', 'Delivery Note-Installation Note').dt_map('Delivery Note', 'Installation Note', self.doc.delivery_note_no, self.doc, self.doclist, "[['Delivery Note', 'Installation Note'],['Delivery Note Item', 'Installation Note Item']]")
|
self.doclist = get_obj('DocType Mapper', 'Delivery Note-Installation Note').dt_map(
|
||||||
|
'Delivery Note', 'Installation Note', self.doc.delivery_note_no,
|
||||||
|
self.doc, self.doclist, "[['Delivery Note', 'Installation Note'], \
|
||||||
|
['Delivery Note Item', 'Installation Note Item']]")
|
||||||
|
|
||||||
# Validates that Delivery Note is not pulled twice
|
|
||||||
#============================================
|
|
||||||
def validate_prev_docname(self):
|
def validate_prev_docname(self):
|
||||||
for d in getlist(self.doclist, 'installed_item_details'):
|
for d in getlist(self.doclist, 'installed_item_details'):
|
||||||
if self.doc.delivery_note_no == d.prevdoc_docname:
|
if self.doc.delivery_note_no == d.prevdoc_docname:
|
||||||
msgprint(cstr(self.doc.delivery_note_no) + " delivery note details have already been pulled. ")
|
msgprint(cstr(self.doc.delivery_note_no) +
|
||||||
raise Exception, "Validation Error. "
|
" delivery note details have already been pulled", raise_exception=1)
|
||||||
|
|
||||||
#Fiscal Year Validation
|
|
||||||
#================================
|
|
||||||
def validate_fiscal_year(self):
|
def validate_fiscal_year(self):
|
||||||
get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.inst_date,'Installation Date')
|
get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year, self.doc.inst_date,
|
||||||
|
'Installation Date')
|
||||||
# Validate Mandatory
|
|
||||||
#===============================
|
|
||||||
def validate_mandatory(self):
|
def validate_mandatory(self):
|
||||||
# Amendment Date
|
|
||||||
if self.doc.amended_from and not self.doc.amendment_date:
|
if self.doc.amended_from and not self.doc.amendment_date:
|
||||||
msgprint("Please Enter Amendment Date")
|
msgprint("Please Enter Amendment Date")
|
||||||
raise Exception, "Validation Error. "
|
raise Exception, "Validation Error. "
|
||||||
|
|
||||||
# Validate values with reference document
|
|
||||||
#----------------------------------------
|
|
||||||
def validate_reference_value(self):
|
def validate_reference_value(self):
|
||||||
get_obj('DocType Mapper', 'Delivery Note-Installation Note', with_children = 1).validate_reference_value(self, self.doc.name)
|
mapper = get_obj('DocType Mapper', 'Delivery Note-Installation Note', with_children = 1)
|
||||||
|
mapper.validate_reference_value(self, self.doc.name)
|
||||||
|
|
||||||
#check if serial no added
|
def is_serial_no_added(self, item_code, serial_no):
|
||||||
#-----------------------------
|
ar_required = webnotes.conn.get_value("Item", item_code, "has_serial_no")
|
||||||
def is_serial_no_added(self,item_code,serial_no):
|
|
||||||
ar_required = sql("select has_serial_no from tabItem where name = '%s'" % item_code)
|
|
||||||
ar_required = ar_required and ar_required[0][0] or ''
|
|
||||||
if ar_required == 'Yes' and not serial_no:
|
if ar_required == 'Yes' and not serial_no:
|
||||||
msgprint("Serial No is mandatory for item: "+ item_code)
|
msgprint("Serial No is mandatory for item: " + item_code, raise_exception=1)
|
||||||
raise Exception
|
|
||||||
elif ar_required != 'Yes' and cstr(serial_no).strip():
|
elif ar_required != 'Yes' and cstr(serial_no).strip():
|
||||||
msgprint("If serial no required, please select 'Yes' in 'Has Serial No' in Item :"+item_code)
|
msgprint("If serial no required, please select 'Yes' in 'Has Serial No' in Item :" +
|
||||||
raise Exception
|
item_code, raise_exception=1)
|
||||||
|
|
||||||
#check if serial no exist in system
|
|
||||||
#-------------------------------------
|
|
||||||
def is_serial_no_exist(self, item_code, serial_no):
|
def is_serial_no_exist(self, item_code, serial_no):
|
||||||
for x in serial_no:
|
for x in serial_no:
|
||||||
chk = sql("select name from `tabSerial No` where name =%s", x)
|
if not webnotes.conn.exists("Serial No", x):
|
||||||
if not chk:
|
msgprint("Serial No " + x + " does not exist in the system", raise_exception=1)
|
||||||
msgprint("Serial No "+x+" does not exist in the system")
|
|
||||||
raise Exception
|
|
||||||
|
|
||||||
#check if serial no already installed
|
|
||||||
#------------------------------------------
|
|
||||||
def is_serial_no_installed(self,cur_s_no,item_code):
|
def is_serial_no_installed(self,cur_s_no,item_code):
|
||||||
for x in cur_s_no:
|
for x in cur_s_no:
|
||||||
status = sql("select status from `tabSerial No` where name = %s", x)
|
status = webnotes.conn.sql("select status from `tabSerial No` where name = %s", x)
|
||||||
status = status and status[0][0] or ''
|
status = status and status[0][0] or ''
|
||||||
|
|
||||||
if status == 'Installed':
|
if status == 'Installed':
|
||||||
msgprint("Item "+item_code+" with serial no. "+x+" already installed")
|
msgprint("Item "+item_code+" with serial no. " + x + " already installed",
|
||||||
raise Exception, "Validation Error."
|
raise_exception=1)
|
||||||
|
|
||||||
#get list of serial no from previous_doc
|
def get_prevdoc_serial_no(self, prevdoc_detail_docname):
|
||||||
#----------------------------------------------
|
serial_nos = webnotes.conn.get_value("Delivery Note Item",
|
||||||
def get_prevdoc_serial_no(self, prevdoc_detail_docname, prevdoc_docname):
|
prevdoc_detail_docname, "serial_no")
|
||||||
res = sql("select serial_no from `tabDelivery Note Item` where name = '%s' and parent ='%s'" % (prevdoc_detail_docname, prevdoc_docname))
|
return get_valid_serial_nos(serial_nos)
|
||||||
return get_valid_serial_nos(res[0][0])
|
|
||||||
|
|
||||||
#check if all serial nos from current record exist in resp delivery note
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
def is_serial_no_match(self, cur_s_no, prevdoc_s_no, prevdoc_docname):
|
def is_serial_no_match(self, cur_s_no, prevdoc_s_no, prevdoc_docname):
|
||||||
for x in cur_s_no:
|
for sr in cur_s_no:
|
||||||
if not(x in prevdoc_s_no):
|
if sr not in prevdoc_s_no:
|
||||||
msgprint("Serial No. "+x+" not present in the Delivery Note "+prevdoc_docname, raise_exception = 1)
|
msgprint("Serial No. " + sr + " is not matching with the Delivery Note " +
|
||||||
raise Exception, "Validation Error."
|
prevdoc_docname, raise_exception = 1)
|
||||||
|
|
||||||
#validate serial number
|
|
||||||
#----------------------------------------
|
|
||||||
def validate_serial_no(self):
|
def validate_serial_no(self):
|
||||||
cur_s_no, prevdoc_s_no, sr_list = [], [], []
|
cur_s_no, prevdoc_s_no, sr_list = [], [], []
|
||||||
for d in getlist(self.doclist, 'installed_item_details'):
|
for d in getlist(self.doclist, 'installed_item_details'):
|
||||||
self.is_serial_no_added(d.item_code, d.serial_no)
|
self.is_serial_no_added(d.item_code, d.serial_no)
|
||||||
|
|
||||||
if d.serial_no:
|
if d.serial_no:
|
||||||
|
|
||||||
sr_list = get_valid_serial_nos(d.serial_no, d.qty, d.item_code)
|
sr_list = get_valid_serial_nos(d.serial_no, d.qty, d.item_code)
|
||||||
self.is_serial_no_exist(d.item_code, sr_list)
|
self.is_serial_no_exist(d.item_code, sr_list)
|
||||||
|
|
||||||
prevdoc_s_no = self.get_prevdoc_serial_no(d.prevdoc_detail_docname, d.prevdoc_docname)
|
prevdoc_s_no = self.get_prevdoc_serial_no(d.prevdoc_detail_docname)
|
||||||
if prevdoc_s_no:
|
if prevdoc_s_no:
|
||||||
self.is_serial_no_match(sr_list, prevdoc_s_no, d.prevdoc_docname)
|
self.is_serial_no_match(sr_list, prevdoc_s_no, d.prevdoc_docname)
|
||||||
|
|
||||||
self.is_serial_no_installed(sr_list, d.item_code)
|
self.is_serial_no_installed(sr_list, d.item_code)
|
||||||
return sr_list
|
return sr_list
|
||||||
|
|
||||||
#validate installation date
|
|
||||||
#-------------------------------
|
|
||||||
def validate_installation_date(self):
|
def validate_installation_date(self):
|
||||||
for d in getlist(self.doclist, 'installed_item_details'):
|
for d in getlist(self.doclist, 'installed_item_details'):
|
||||||
if d.prevdoc_docname:
|
if d.prevdoc_docname:
|
||||||
d_date = sql("select posting_date from `tabDelivery Note` where name=%s", d.prevdoc_docname)
|
d_date = webnotes.conn.get_value("Delivery Note", d.prevdoc_docname, "posting_date")
|
||||||
d_date = d_date and d_date[0][0] or ''
|
|
||||||
|
|
||||||
if d_date > getdate(self.doc.inst_date):
|
if d_date > getdate(self.doc.inst_date):
|
||||||
msgprint("Installation Date can not be before Delivery Date "+cstr(d_date)+" for item "+d.item_code)
|
msgprint("Installation Date can not be before Delivery Date " + cstr(d_date) +
|
||||||
raise Exception
|
" for item "+d.item_code, raise_exception=1)
|
||||||
|
|
||||||
def check_item_table(self):
|
def check_item_table(self):
|
||||||
if not(getlist(self.doclist, 'installed_item_details')):
|
if not(getlist(self.doclist, 'installed_item_details')):
|
||||||
msgprint("Please fetch items from Delivery Note selected")
|
msgprint("Please fetch items from Delivery Note selected", raise_exception=1)
|
||||||
raise Exception
|
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
|
get_obj("Stock Ledger").scrub_serial_nos(self, 'installed_item_details')
|
||||||
webnotes.conn.set(self.doc, 'status', 'Draft')
|
webnotes.conn.set(self.doc, 'status', 'Draft')
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
valid_lst = []
|
valid_lst = []
|
||||||
valid_lst = self.validate_serial_no()
|
valid_lst = self.validate_serial_no()
|
||||||
|
|
||||||
get_obj("Sales Common").update_prevdoc_detail(1,self)
|
|
||||||
|
|
||||||
for x in valid_lst:
|
for x in valid_lst:
|
||||||
wp = sql("select warranty_period from `tabSerial No` where name = '%s'"% x)
|
if webnotes.conn.get_value("Serial No", x, "warranty_period"):
|
||||||
wp = wp and wp[0][0] or 0
|
webnotes.conn.set_value("Serial No", x, "maintenance_status", "Under Warranty")
|
||||||
if wp:
|
webnotes.conn.set_value("Serial No", x, "status", "Installed")
|
||||||
sql("update `tabSerial No` set maintenance_status = 'Under Warranty' where name = '%s'" % x)
|
|
||||||
|
|
||||||
sql("update `tabSerial No` set status = 'Installed' where name = '%s'" % x)
|
|
||||||
|
|
||||||
webnotes.conn.set(self.doc, 'status', 'Submitted')
|
|
||||||
|
|
||||||
|
self.update_prevdoc_status()
|
||||||
|
webnotes.conn.set(self.doc, 'status', 'Submitted')
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
cur_s_no = []
|
|
||||||
sales_com_obj = get_obj(dt = 'Sales Common')
|
|
||||||
sales_com_obj.update_prevdoc_detail(0,self)
|
|
||||||
|
|
||||||
for d in getlist(self.doclist, 'installed_item_details'):
|
for d in getlist(self.doclist, 'installed_item_details'):
|
||||||
if d.serial_no:
|
if d.serial_no:
|
||||||
#get current list of serial no
|
d.serial_no = d.serial_no.replace(",", "\n")
|
||||||
cur_serial_no = d.serial_no.replace(' ', '')
|
for sr_no in d.serial_no.split("\n"):
|
||||||
cur_s_no = cur_serial_no.split(',')
|
webnotes.conn.set_value("Serial No", sr_no, "status", "Delivered")
|
||||||
|
|
||||||
for x in cur_s_no:
|
self.update_prevdoc_status()
|
||||||
sql("update `tabSerial No` set status = 'Delivered' where name = '%s'" % x)
|
|
||||||
|
|
||||||
webnotes.conn.set(self.doc, 'status', 'Cancelled')
|
webnotes.conn.set(self.doc, 'status', 'Cancelled')
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
|
|
||||||
from webnotes.utils import cstr, flt, getdate, cint
|
from webnotes.utils import cstr, flt, cint
|
||||||
from webnotes.model.bean import getlist
|
from webnotes.model.bean import getlist
|
||||||
from webnotes.model.code import get_obj
|
from webnotes.model.code import get_obj
|
||||||
from webnotes import msgprint, _
|
from webnotes import msgprint, _
|
||||||
@ -34,6 +34,19 @@ class DocType(SellingController):
|
|||||||
self.doclist = doclist
|
self.doclist = doclist
|
||||||
self.tname = 'Delivery Note Item'
|
self.tname = 'Delivery Note Item'
|
||||||
self.fname = 'delivery_note_details'
|
self.fname = 'delivery_note_details'
|
||||||
|
self.status_updater = [{
|
||||||
|
'source_dt': 'Delivery Note Item',
|
||||||
|
'target_dt': 'Sales Order Item',
|
||||||
|
'join_field': 'prevdoc_detail_docname',
|
||||||
|
'target_field': 'delivered_qty',
|
||||||
|
'target_parent_dt': 'Sales Order',
|
||||||
|
'target_parent_field': 'per_delivered',
|
||||||
|
'target_ref_field': 'qty',
|
||||||
|
'source_field': 'qty',
|
||||||
|
'percent_join_field': 'prevdoc_docname',
|
||||||
|
'status_field': 'delivery_status',
|
||||||
|
'keyword': 'Delivered'
|
||||||
|
}]
|
||||||
|
|
||||||
def set_customer_defaults(self):
|
def set_customer_defaults(self):
|
||||||
self.get_default_customer_shipping_address()
|
self.get_default_customer_shipping_address()
|
||||||
@ -228,8 +241,8 @@ class DocType(SellingController):
|
|||||||
sl_obj.update_serial_record(self, 'delivery_note_details', is_submit = 1, is_incoming = 0)
|
sl_obj.update_serial_record(self, 'delivery_note_details', is_submit = 1, is_incoming = 0)
|
||||||
sl_obj.update_serial_record(self, 'packing_details', is_submit = 1, is_incoming = 0)
|
sl_obj.update_serial_record(self, 'packing_details', is_submit = 1, is_incoming = 0)
|
||||||
|
|
||||||
# update delivered qty in sales order
|
# update delivered qty in sales order
|
||||||
get_obj("Sales Common").update_prevdoc_detail(1,self)
|
self.update_prevdoc_status()
|
||||||
|
|
||||||
# create stock ledger entry
|
# create stock ledger entry
|
||||||
self.update_stock_ledger(update_stock = 1)
|
self.update_stock_ledger(update_stock = 1)
|
||||||
@ -276,7 +289,8 @@ class DocType(SellingController):
|
|||||||
sl.update_serial_record(self, 'delivery_note_details', is_submit = 0, is_incoming = 0)
|
sl.update_serial_record(self, 'delivery_note_details', is_submit = 0, is_incoming = 0)
|
||||||
sl.update_serial_record(self, 'packing_details', is_submit = 0, is_incoming = 0)
|
sl.update_serial_record(self, 'packing_details', is_submit = 0, is_incoming = 0)
|
||||||
|
|
||||||
sales_com_obj.update_prevdoc_detail(0,self)
|
self.update_prevdoc_status()
|
||||||
|
|
||||||
self.update_stock_ledger(update_stock = -1)
|
self.update_stock_ledger(update_stock = -1)
|
||||||
webnotes.conn.set(self.doc, 'status', 'Cancelled')
|
webnotes.conn.set(self.doc, 'status', 'Cancelled')
|
||||||
self.cancel_packing_slips()
|
self.cancel_packing_slips()
|
||||||
|
@ -33,6 +33,17 @@ class DocType(BuyingController):
|
|||||||
self.tname = 'Purchase Receipt Item'
|
self.tname = 'Purchase Receipt Item'
|
||||||
self.fname = 'purchase_receipt_details'
|
self.fname = 'purchase_receipt_details'
|
||||||
self.count = 0
|
self.count = 0
|
||||||
|
self.status_updater = [{
|
||||||
|
'source_dt': 'Purchase Receipt Item',
|
||||||
|
'target_dt': 'Purchase Order Item',
|
||||||
|
'join_field': 'prevdoc_detail_docname',
|
||||||
|
'target_field': 'received_qty',
|
||||||
|
'target_parent_dt': 'Purchase Order',
|
||||||
|
'target_parent_field': 'per_received',
|
||||||
|
'target_ref_field': 'qty',
|
||||||
|
'source_field': 'qty',
|
||||||
|
'percent_join_field': 'prevdoc_docname',
|
||||||
|
}]
|
||||||
|
|
||||||
def validate_fiscal_year(self):
|
def validate_fiscal_year(self):
|
||||||
get_obj(dt = 'Purchase Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.posting_date,'Transaction Date')
|
get_obj(dt = 'Purchase Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.posting_date,'Transaction Date')
|
||||||
@ -243,8 +254,7 @@ class DocType(BuyingController):
|
|||||||
# Set status as Submitted
|
# Set status as Submitted
|
||||||
webnotes.conn.set(self.doc,'status', 'Submitted')
|
webnotes.conn.set(self.doc,'status', 'Submitted')
|
||||||
|
|
||||||
# Update Previous Doc i.e. update pending_qty and Status accordingly
|
self.update_prevdoc_status()
|
||||||
purchase_controller.update_prevdoc_detail(self, is_submit = 1)
|
|
||||||
|
|
||||||
# Update Serial Record
|
# Update Serial Record
|
||||||
get_obj('Stock Ledger').update_serial_record(self, 'purchase_receipt_details', is_submit = 1, is_incoming = 1)
|
get_obj('Stock Ledger').update_serial_record(self, 'purchase_receipt_details', is_submit = 1, is_incoming = 1)
|
||||||
@ -285,8 +295,7 @@ class DocType(BuyingController):
|
|||||||
# 4.Update Bin
|
# 4.Update Bin
|
||||||
self.update_stock(is_submit = 0)
|
self.update_stock(is_submit = 0)
|
||||||
|
|
||||||
# 5.Update Material Requests Pending Qty and accordingly it's Status
|
self.update_prevdoc_status()
|
||||||
pc_obj.update_prevdoc_detail(self, is_submit = 0)
|
|
||||||
|
|
||||||
# 6. Update last purchase rate
|
# 6. Update last purchase rate
|
||||||
pc_obj.update_last_purchase_rate(self, 0)
|
pc_obj.update_last_purchase_rate(self, 0)
|
||||||
|
@ -6,7 +6,7 @@ wn.listview_settings['Purchase Receipt'] = {
|
|||||||
group_by: "`tabPurchase Receipt`.name",
|
group_by: "`tabPurchase Receipt`.name",
|
||||||
prepare_data: function(data) {
|
prepare_data: function(data) {
|
||||||
if(data.purchase_order_no) {
|
if(data.purchase_order_no) {
|
||||||
data.purchase_order_no = data.purchase_order_no.split(",");
|
data.purchase_order_no = $.unique(data.purchase_order_no.split(","));
|
||||||
var po_list = [];
|
var po_list = [];
|
||||||
$.each(data.purchase_order_no, function(i, v){
|
$.each(data.purchase_order_no, function(i, v){
|
||||||
if(po_list.indexOf(v)==-1) po_list.push(
|
if(po_list.indexOf(v)==-1) po_list.push(
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
{
|
{
|
||||||
"creation": "2013-05-24 19:29:10",
|
"creation": "2013-05-24 19:29:10",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"modified": "2013-05-28 12:13:59",
|
"modified": "2013-05-31 14:26:41",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"owner": "Administrator"
|
"owner": "Administrator"
|
||||||
},
|
},
|
||||||
@ -453,18 +453,14 @@
|
|||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0.00",
|
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
"fieldname": "billed_qty",
|
"fieldname": "billed_amt",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Currency",
|
||||||
"label": "Billed Quantity",
|
"label": "Billed Amt",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "billed_qty",
|
"options": "currency",
|
||||||
"oldfieldtype": "Currency",
|
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "100px",
|
"read_only": 1
|
||||||
"read_only": 1,
|
|
||||||
"width": "100px"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "DocField",
|
"doctype": "DocField",
|
||||||
|
@ -505,17 +505,13 @@ class DocType(StockController):
|
|||||||
|
|
||||||
if self.doc.use_multi_level_bom:
|
if self.doc.use_multi_level_bom:
|
||||||
# get all raw materials with sub assembly childs
|
# get all raw materials with sub assembly childs
|
||||||
fl_bom_sa_child_item = sql("""select
|
fl_bom_sa_child_item = sql("""select fb.item_code,
|
||||||
item_code,ifnull(sum(qty_consumed_per_unit),0)*%s as qty,
|
ifnull(sum(fb.qty_consumed_per_unit),0)*%s as qty, fb.description, fb.stock_uom
|
||||||
description,stock_uom
|
from `tabBOM Explosion Item` fb,`tabItem` it
|
||||||
from ( select distinct fb.name, fb.description, fb.item_code,
|
where it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No'
|
||||||
fb.qty_consumed_per_unit, fb.stock_uom
|
and ifnull(it.is_sub_contracted_item, 'No') = 'No' and fb.docstatus < 2
|
||||||
from `tabBOM Explosion Item` fb,`tabItem` it
|
and fb.parent=%s group by item_code, stock_uom""",
|
||||||
where it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No'
|
(qty, self.doc.bom_no), as_dict=1)
|
||||||
and ifnull(it.is_sub_contracted_item, 'No') = 'No' and fb.docstatus<2
|
|
||||||
and fb.parent=%s
|
|
||||||
) a
|
|
||||||
group by item_code, stock_uom""" , (qty, self.doc.bom_no), as_dict=1)
|
|
||||||
|
|
||||||
if fl_bom_sa_child_item:
|
if fl_bom_sa_child_item:
|
||||||
_make_items_dict(fl_bom_sa_child_item)
|
_make_items_dict(fl_bom_sa_child_item)
|
||||||
@ -523,10 +519,10 @@ class DocType(StockController):
|
|||||||
# Get all raw materials considering multi level BOM,
|
# Get all raw materials considering multi level BOM,
|
||||||
# if multi level bom consider childs of Sub-Assembly items
|
# if multi level bom consider childs of Sub-Assembly items
|
||||||
fl_bom_sa_items = sql("""select item_code,
|
fl_bom_sa_items = sql("""select item_code,
|
||||||
ifnull(sum(qty_consumed_per_unit), 0) * '%s' as qty,
|
ifnull(sum(qty_consumed_per_unit), 0) *%s as qty,
|
||||||
description, stock_uom from `tabBOM Item`
|
description, stock_uom from `tabBOM Item`
|
||||||
where parent = '%s' and docstatus < 2
|
where parent = %s and docstatus < 2
|
||||||
group by item_code""" % (qty, self.doc.bom_no), as_dict=1)
|
group by item_code""", (qty, self.doc.bom_no), as_dict=1)
|
||||||
|
|
||||||
if fl_bom_sa_items:
|
if fl_bom_sa_items:
|
||||||
_make_items_dict(fl_bom_sa_items)
|
_make_items_dict(fl_bom_sa_items)
|
||||||
|
@ -20,9 +20,9 @@ from webnotes import msgprint, _
|
|||||||
from webnotes.utils import load_json, cstr, flt, now_datetime
|
from webnotes.utils import load_json, cstr, flt, now_datetime
|
||||||
from webnotes.model.doc import addchild
|
from webnotes.model.doc import addchild
|
||||||
|
|
||||||
from webnotes.model.controller import DocListController
|
from controllers.status_updater import StatusUpdater
|
||||||
|
|
||||||
class TransactionBase(DocListController):
|
class TransactionBase(StatusUpdater):
|
||||||
def get_default_address_and_contact(self, party_type):
|
def get_default_address_and_contact(self, party_type):
|
||||||
"""get a dict of default field values of address and contact for a given party type
|
"""get a dict of default field values of address and contact for a given party type
|
||||||
party_type can be one of: customer, supplier"""
|
party_type can be one of: customer, supplier"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user