Merged master into wsgi
This commit is contained in:
parent
b604eddbfd
commit
373680bbae
@ -107,7 +107,7 @@ class DocType:
|
||||
_(" does not belong to the company") + ": " + self.doc.company)
|
||||
|
||||
def check_negative_balance(account, adv_adj=False):
|
||||
if not adv_adj:
|
||||
if not adv_adj and account:
|
||||
account_details = webnotes.conn.get_value("Account", account,
|
||||
["allow_negative_balance", "debit_or_credit"], as_dict=True)
|
||||
if not account_details["allow_negative_balance"]:
|
||||
|
@ -337,7 +337,7 @@ class DocType(BuyingController):
|
||||
)
|
||||
|
||||
# tax table gl entries
|
||||
valuation_tax = 0
|
||||
valuation_tax = {}
|
||||
for tax in self.doclist.get({"parentfield": "purchase_tax_details"}):
|
||||
if tax.category in ("Total", "Valuation and Total") and flt(tax.tax_amount):
|
||||
gl_entries.append(
|
||||
@ -352,8 +352,11 @@ class DocType(BuyingController):
|
||||
)
|
||||
|
||||
# accumulate valuation tax
|
||||
if tax.category in ("Valuation", "Valuation and Total") and flt(tax.tax_amount):
|
||||
valuation_tax += (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.tax_amount)
|
||||
if tax.category in ("Valuation", "Valuation and Total") and flt(tax.tax_amount) \
|
||||
and tax.cost_center:
|
||||
valuation_tax.setdefault(tax.cost_center, 0)
|
||||
valuation_tax[tax.cost_center] += \
|
||||
(tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.tax_amount)
|
||||
|
||||
# item gl entries
|
||||
stock_item_and_auto_accounting_for_stock = False
|
||||
@ -394,15 +397,19 @@ class DocType(BuyingController):
|
||||
if stock_item_and_auto_accounting_for_stock and valuation_tax:
|
||||
# credit valuation tax amount in "Expenses Included In Valuation"
|
||||
# this will balance out valuation amount included in cost of goods sold
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.get_company_default("expenses_included_in_valuation"),
|
||||
"cost_center": self.get_company_default("cost_center"),
|
||||
"against": self.doc.credit_to,
|
||||
"credit": valuation_tax,
|
||||
"remarks": self.doc.remarks or "Accounting Entry for Stock"
|
||||
})
|
||||
)
|
||||
expenses_included_in_valuation = \
|
||||
self.get_company_default("expenses_included_in_valuation")
|
||||
|
||||
for cost_center, amount in valuation_tax.items():
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
"account": expenses_included_in_valuation,
|
||||
"cost_center": cost_center,
|
||||
"against": self.doc.credit_to,
|
||||
"credit": amount,
|
||||
"remarks": self.doc.remarks or "Accounting Entry for Stock"
|
||||
})
|
||||
)
|
||||
|
||||
# writeoff account includes petty difference in the invoice amount
|
||||
# and the amount that is paid
|
||||
|
@ -83,7 +83,6 @@ class DocType(SellingController):
|
||||
def on_submit(self):
|
||||
if cint(self.doc.update_stock) == 1:
|
||||
self.update_stock_ledger()
|
||||
self.update_serial_nos()
|
||||
else:
|
||||
# Check for Approving Authority
|
||||
if not self.doc.recurring_id:
|
||||
@ -111,7 +110,6 @@ class DocType(SellingController):
|
||||
def on_cancel(self):
|
||||
if cint(self.doc.update_stock) == 1:
|
||||
self.update_stock_ledger()
|
||||
self.update_serial_nos(cancel = True)
|
||||
|
||||
sales_com_obj = get_obj(dt = 'Sales Common')
|
||||
sales_com_obj.check_stop_sales_order(self)
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-24 19:29:05",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-10-02 14:24:50",
|
||||
"modified": "2013-10-03 18:54:31",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -181,7 +181,6 @@
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"default": "Today",
|
||||
"description": "Enter the date by which payments from customer is expected against this invoice.",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "due_date",
|
||||
|
@ -81,12 +81,12 @@ def get_tax_accounts(item_list, columns):
|
||||
if account_head not in tax_accounts:
|
||||
tax_accounts.append(account_head)
|
||||
|
||||
invoice = item_tax.setdefault(parent, {})
|
||||
if item_wise_tax_detail:
|
||||
try:
|
||||
item_wise_tax_detail = json.loads(item_wise_tax_detail)
|
||||
for item, tax_amount in item_wise_tax_detail.items():
|
||||
invoice.setdefault(item, {})[account_head] = flt(tax_amount)
|
||||
item_tax.setdefault(parent, {}).setdefault(item, {})[account_head] = \
|
||||
flt(tax_amount[1])
|
||||
|
||||
except ValueError:
|
||||
continue
|
||||
|
@ -9,7 +9,7 @@ def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
columns = get_columns()
|
||||
last_col = len(columns)
|
||||
|
||||
|
||||
item_list = get_items(filters)
|
||||
item_tax, tax_accounts = get_tax_accounts(item_list, columns)
|
||||
|
||||
@ -21,7 +21,7 @@ def execute(filters=None):
|
||||
|
||||
for tax in tax_accounts:
|
||||
row.append(item_tax.get(d.parent, {}).get(d.item_code, {}).get(tax, 0))
|
||||
|
||||
|
||||
total_tax = sum(row[last_col:])
|
||||
row += [total_tax, d.amount + total_tax]
|
||||
|
||||
@ -71,19 +71,19 @@ def get_tax_accounts(item_list, columns):
|
||||
tax_details = webnotes.conn.sql("""select parent, account_head, item_wise_tax_detail
|
||||
from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice'
|
||||
and docstatus = 1 and ifnull(account_head, '') != ''
|
||||
and parent in (%s)""" % ', '.join(['%s']*len(item_list)), tuple([item.parent for item in item_list]))
|
||||
and parent in (%s)""" % ', '.join(['%s']*len(item_list)),
|
||||
tuple([item.parent for item in item_list]))
|
||||
|
||||
for parent, account_head, item_wise_tax_detail in tax_details:
|
||||
if account_head not in tax_accounts:
|
||||
tax_accounts.append(account_head)
|
||||
|
||||
invoice = item_tax.setdefault(parent, {})
|
||||
|
||||
if item_wise_tax_detail:
|
||||
try:
|
||||
item_wise_tax_detail = json.loads(item_wise_tax_detail)
|
||||
for item, tax_amount in item_wise_tax_detail.items():
|
||||
invoice.setdefault(item, {})[account_head] = flt(tax_amount)
|
||||
|
||||
item_tax.setdefault(parent, {}).setdefault(item, {})[account_head] = \
|
||||
flt(tax_amount[1])
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
|
@ -145,6 +145,11 @@ wn.module_page["Buying"] = [
|
||||
route: "query-report/Purchase Order Trends",
|
||||
doctype: "Purchase Order"
|
||||
},
|
||||
{
|
||||
"label":wn._("Supplier Addresses And Contacts"),
|
||||
route: "query-report/Supplier Addresses and Contacts",
|
||||
doctype: "Supplier"
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-10-09 10:38:40",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-10-09 10:53:52",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"doctype": "Report",
|
||||
"is_standard": "Yes",
|
||||
"name": "__common__",
|
||||
"query": "SELECT\n `tabSupplier`.name as \"Supplier:Link/Supplier:120\",\n\t`tabSupplier`.supplier_name as \"Supplier Name::120\",\n\t`tabSupplier`.supplier_type as \"Supplier Type:Link/Supplier Type:120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2), \n\t\ttabAddress.state, tabAddress.pincode, tabAddress.country\n\t) as 'Address::180',\n concat_ws(', ', `tabContact`.first_name, `tabContact`.last_name) as 'Contact Name::180',\n\t`tabContact`.phone as \"Phone\",\n\t`tabContact`.mobile_no as \"Mobile No\",\n\t`tabContact`.email_id as \"Email Id::120\",\n\t`tabContact`.is_primary_contact as \"Is Primary Contact::120\"\nFROM\n\t`tabSupplier`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.supplier=`tabSupplier`.name\n\t)\n\tleft join `tabContact` on (\n\t\t`tabContact`.supplier=`tabSupplier`.name\n\t)\nWHERE\n\t`tabSupplier`.docstatus<2\nORDER BY\n\t`tabSupplier`.name asc",
|
||||
"ref_doctype": "Supplier",
|
||||
"report_name": "Supplier Addresses and Contacts",
|
||||
"report_type": "Query Report"
|
||||
},
|
||||
{
|
||||
"doctype": "Report",
|
||||
"name": "Supplier Addresses and Contacts"
|
||||
}
|
||||
]
|
@ -24,7 +24,7 @@ class BuyingController(StockController):
|
||||
self.doc.supplier_name = webnotes.conn.get_value("Supplier",
|
||||
self.doc.supplier, "supplier_name")
|
||||
self.validate_stock_or_nonstock_items()
|
||||
self.validate_warehouse_belongs_to_company()
|
||||
self.validate_warehouse()
|
||||
|
||||
def set_missing_values(self, for_validate=False):
|
||||
super(BuyingController, self).set_missing_values(for_validate)
|
||||
@ -49,17 +49,20 @@ class BuyingController(StockController):
|
||||
if supplier:
|
||||
self.doc.supplier = supplier
|
||||
break
|
||||
|
||||
def validate_warehouse(self):
|
||||
from stock.utils import validate_warehouse_user, validate_warehouse_company
|
||||
|
||||
warehouses = list(set([d.warehouse for d in
|
||||
self.doclist.get({"doctype": self.tname}) if d.warehouse]))
|
||||
|
||||
for w in warehouses:
|
||||
validate_warehouse_user(w)
|
||||
validate_warehouse_company(w, self.doc.company)
|
||||
|
||||
def get_purchase_tax_details(self):
|
||||
self.doclist = self.doc.clear_table(self.doclist, "purchase_tax_details")
|
||||
self.set_taxes("purchase_tax_details", "purchase_other_charges")
|
||||
|
||||
def validate_warehouse_belongs_to_company(self):
|
||||
for warehouse, company in webnotes.conn.get_values("Warehouse",
|
||||
self.doclist.get_distinct_values("warehouse"), "company").items():
|
||||
if company and company != self.doc.company:
|
||||
webnotes.msgprint(_("Company mismatch for Warehouse") + (": %s" % (warehouse,)),
|
||||
raise_exception=WrongWarehouseCompany)
|
||||
|
||||
def validate_stock_or_nonstock_items(self):
|
||||
if not self.get_stock_items():
|
||||
|
@ -236,34 +236,4 @@ class SellingController(StockController):
|
||||
self.doc.order_type = "Sales"
|
||||
elif self.doc.order_type not in valid_types:
|
||||
msgprint(_(self.meta.get_label("order_type")) + " " +
|
||||
_("must be one of") + ": " + comma_or(valid_types),
|
||||
raise_exception=True)
|
||||
|
||||
def update_serial_nos(self, cancel=False):
|
||||
from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos
|
||||
update_serial_nos_after_submit(self, self.doc.doctype, self.fname)
|
||||
update_serial_nos_after_submit(self, self.doc.doctype, "packing_details")
|
||||
|
||||
for table_fieldname in (self.fname, "packing_details"):
|
||||
for d in self.doclist.get({"parentfield": table_fieldname}):
|
||||
for serial_no in get_serial_nos(d.serial_no):
|
||||
sr = webnotes.bean("Serial No", serial_no)
|
||||
if cancel:
|
||||
sr.doc.status = "Available"
|
||||
for fieldname in ("warranty_expiry_date", "delivery_document_type",
|
||||
"delivery_document_no", "delivery_date", "delivery_time", "customer",
|
||||
"customer_name"):
|
||||
sr.doc.fields[fieldname] = None
|
||||
else:
|
||||
sr.doc.delivery_document_type = self.doc.doctype
|
||||
sr.doc.delivery_document_no = self.doc.name
|
||||
sr.doc.delivery_date = self.doc.posting_date
|
||||
sr.doc.delivery_time = self.doc.posting_time
|
||||
sr.doc.customer = self.doc.customer
|
||||
sr.doc.customer_name = self.doc.customer_name
|
||||
if sr.doc.warranty_period:
|
||||
sr.doc.warranty_expiry_date = add_days(cstr(self.doc.posting_date),
|
||||
cint(sr.doc.warranty_period))
|
||||
sr.doc.status = 'Delivered'
|
||||
|
||||
sr.save()
|
||||
_("must be one of") + ": " + comma_or(valid_types), raise_exception=True)
|
||||
|
@ -4,7 +4,6 @@
|
||||
wn.provide("erpnext.hr");
|
||||
erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({
|
||||
setup: function() {
|
||||
this.setup_leave_approver_select();
|
||||
this.frm.fields_dict.user_id.get_query = function(doc,cdt,cdn) {
|
||||
return { query:"core.doctype.profile.profile.profile_query"} }
|
||||
this.frm.fields_dict.reports_to.get_query = function(doc,cdt,cdn) {
|
||||
@ -12,6 +11,7 @@ erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({
|
||||
},
|
||||
|
||||
onload: function() {
|
||||
this.setup_leave_approver_select();
|
||||
this.frm.toggle_display(["esic_card_no", "gratuity_lic_id", "pan_number", "pf_number"],
|
||||
wn.control_panel.country==="India");
|
||||
if(this.frm.doc.__islocal) this.frm.set_value("employee_name", "");
|
||||
|
@ -21,13 +21,14 @@ class DocType:
|
||||
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
|
||||
"In Process", "Completed", "Cancelled"])
|
||||
|
||||
if self.doc.production_item :
|
||||
item_detail = webnotes.conn.sql("select name from `tabItem` where name = '%s' and docstatus != 2"
|
||||
% self.doc.production_item, as_dict = 1)
|
||||
if not item_detail:
|
||||
msgprint("Item '%s' does not exist or cancelled in the system."
|
||||
% cstr(self.doc.production_item), raise_exception=1)
|
||||
|
||||
self.validate_bom_no()
|
||||
self.validate_sales_order()
|
||||
self.validate_warehouse()
|
||||
|
||||
from utilities.transaction_base import validate_uom_is_integer
|
||||
validate_uom_is_integer(self.doclist, "stock_uom", ["qty", "produced_qty"])
|
||||
|
||||
def validate_bom_no(self):
|
||||
if self.doc.bom_no:
|
||||
bom = webnotes.conn.sql("""select name from `tabBOM` where name=%s and docstatus=1
|
||||
and is_active=1 and item=%s"""
|
||||
@ -37,16 +38,20 @@ class DocType:
|
||||
May be BOM not exists or inactive or not submitted
|
||||
or for some other item.""" % cstr(self.doc.bom_no), raise_exception=1)
|
||||
|
||||
def validate_sales_order(self):
|
||||
if self.doc.sales_order:
|
||||
if not webnotes.conn.sql("""select name from `tabSales Order`
|
||||
where name=%s and docstatus = 1""", self.doc.sales_order):
|
||||
msgprint("Sales Order: %s is not valid" % self.doc.sales_order, raise_exception=1)
|
||||
|
||||
|
||||
self.validate_production_order_against_so()
|
||||
|
||||
from utilities.transaction_base import validate_uom_is_integer
|
||||
validate_uom_is_integer(self.doclist, "stock_uom", ["qty", "produced_qty"])
|
||||
|
||||
|
||||
def validate_warehouse(self):
|
||||
from stock.utils import validate_warehouse_user, validate_warehouse_company
|
||||
|
||||
for w in [self.doc.fg_warehouse, self.doc.wip_warehouse]:
|
||||
validate_warehouse_user(w)
|
||||
validate_warehouse_company(w, self.doc.company)
|
||||
|
||||
def validate_production_order_against_so(self):
|
||||
# already ordered qty
|
||||
|
18
patches/october_2013/p01_fix_serial_no_status.py
Normal file
18
patches/october_2013/p01_fix_serial_no_status.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.utils import flt
|
||||
|
||||
def execute():
|
||||
serial_nos = webnotes.conn.sql("""select name from `tabSerial No` where status!='Not in Use'
|
||||
and docstatus=0""")
|
||||
for sr in serial_nos:
|
||||
sr_bean = webnotes.bean("Serial No", sr[0])
|
||||
sr_bean.make_controller().via_stock_ledger = True
|
||||
sr_bean.run_method("validate")
|
||||
sr_bean.save()
|
||||
|
||||
webnotes.conn.sql("""update `tabSerial No` set warehouse='' where status in
|
||||
('Delivered', 'Purchase Returned')""")
|
@ -0,0 +1,86 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.utils import nowdate, nowtime, cstr
|
||||
from accounts.utils import get_fiscal_year
|
||||
|
||||
def execute():
|
||||
item_map = {}
|
||||
for item in webnotes.conn.sql("""select * from tabItem""", as_dict=1):
|
||||
item_map.setdefault(item.name, item)
|
||||
|
||||
warehouse_map = get_warehosue_map()
|
||||
naming_series = "STE/13/"
|
||||
|
||||
for company in webnotes.conn.sql("select name from tabCompany"):
|
||||
stock_entry = [{
|
||||
"doctype": "Stock Entry",
|
||||
"naming_series": naming_series,
|
||||
"posting_date": nowdate(),
|
||||
"posting_time": nowtime(),
|
||||
"purpose": "Material Transfer",
|
||||
"company": company[0],
|
||||
"remarks": "Material Transfer to activate perpetual inventory",
|
||||
"fiscal_year": get_fiscal_year(nowdate())[0]
|
||||
}]
|
||||
expense_account = "Cost of Goods Sold - NISL"
|
||||
cost_center = "Default CC Ledger - NISL"
|
||||
|
||||
for bin in webnotes.conn.sql("""select * from tabBin bin where ifnull(item_code, '')!=''
|
||||
and ifnull(warehouse, '') in (%s) and ifnull(actual_qty, 0) != 0
|
||||
and (select company from tabWarehouse where name=bin.warehouse)=%s""" %
|
||||
(', '.join(['%s']*len(warehouse_map)), '%s'),
|
||||
(warehouse_map.keys() + [company[0]]), as_dict=1):
|
||||
item_details = item_map[bin.item_code]
|
||||
new_warehouse = warehouse_map[bin.warehouse].get("fixed_asset_warehouse") \
|
||||
if cstr(item_details.is_asset_item) == "Yes" \
|
||||
else warehouse_map[bin.warehouse].get("current_asset_warehouse")
|
||||
|
||||
if item_details.has_serial_no == "Yes":
|
||||
serial_no = "\n".join([d[0] for d in webnotes.conn.sql("""select name
|
||||
from `tabSerial No` where item_code = %s and warehouse = %s
|
||||
and status in ('Available', 'Sales Returned')""",
|
||||
(bin.item_code, bin.warehouse))])
|
||||
else:
|
||||
serial_no = None
|
||||
|
||||
stock_entry.append({
|
||||
"doctype": "Stock Entry Detail",
|
||||
"parentfield": "mtn_details",
|
||||
"s_warehouse": bin.warehouse,
|
||||
"t_warehouse": new_warehouse,
|
||||
"item_code": bin.item_code,
|
||||
"description": item_details.description,
|
||||
"qty": bin.actual_qty,
|
||||
"transfer_qty": bin.actual_qty,
|
||||
"uom": item_details.stock_uom,
|
||||
"stock_uom": item_details.stock_uom,
|
||||
"conversion_factor": 1,
|
||||
"expense_account": expense_account,
|
||||
"cost_center": cost_center,
|
||||
"serial_no": serial_no
|
||||
})
|
||||
|
||||
webnotes.bean(stock_entry).insert()
|
||||
|
||||
def get_warehosue_map():
|
||||
return {
|
||||
"MAHAPE": {
|
||||
"current_asset_warehouse": "Mahape-New - NISL",
|
||||
"fixed_asset_warehouse": ""
|
||||
},
|
||||
"DROP SHIPMENT": {
|
||||
"current_asset_warehouse": "Drop Shipment-New - NISL",
|
||||
"fixed_asset_warehouse": ""
|
||||
},
|
||||
"TRANSIT": {
|
||||
"current_asset_warehouse": "Transit-New - NISL",
|
||||
"fixed_asset_warehouse": ""
|
||||
},
|
||||
"ASSET - MAHAPE": {
|
||||
"current_asset_warehouse": "",
|
||||
"fixed_asset_warehouse": "Assets-New - NISL"
|
||||
}
|
||||
}
|
10
patches/october_2013/set_stock_value_diff_in_sle.py
Normal file
10
patches/october_2013/set_stock_value_diff_in_sle.py
Normal file
@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.utils import cint
|
||||
|
||||
def execute():
|
||||
from patches.september_2012 import repost_stock
|
||||
repost_stock.execute()
|
@ -121,4 +121,4 @@ def make_opportunity(source_name, target_doclist=None):
|
||||
}
|
||||
}}, target_doclist)
|
||||
|
||||
return [d.fields for d in doclist]
|
||||
return [d if isinstance(d, dict) else d.fields for d in doclist]
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-04-10 11:45:37",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-10-03 17:24:33",
|
||||
"modified": "2013-10-09 15:27:54",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -159,8 +159,63 @@
|
||||
"doctype": "DocField",
|
||||
"fieldname": "communication_history",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Communication History",
|
||||
"options": "icon-comments"
|
||||
"label": "Communication",
|
||||
"options": "icon-comments",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"default": "__user",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "lead_owner",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"label": "Lead Owner",
|
||||
"oldfieldname": "lead_owner",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Profile",
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "col_break123",
|
||||
"fieldtype": "Column Break",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"description": "Your sales person who will contact the lead in future",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "contact_by",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"in_filter": 1,
|
||||
"label": "Next Contact By",
|
||||
"oldfieldname": "contact_by",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Profile",
|
||||
"print_hide": 0,
|
||||
"reqd": 0,
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"description": "Your sales person will get a reminder on this date to contact the lead",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "contact_date",
|
||||
"fieldtype": "Date",
|
||||
"in_filter": 1,
|
||||
"label": "Next Contact Date",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "contact_date",
|
||||
"oldfieldtype": "Date",
|
||||
"reqd": 0,
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "sec_break123",
|
||||
"fieldtype": "Section Break",
|
||||
"options": "Simple"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@ -273,18 +328,6 @@
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nClient\nChannel Partner\nConsultant"
|
||||
},
|
||||
{
|
||||
"default": "__user",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "lead_owner",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"label": "Lead Owner",
|
||||
"oldfieldname": "lead_owner",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Profile",
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "market_segment",
|
||||
@ -334,49 +377,6 @@
|
||||
"oldfieldtype": "Column Break",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"description": "Your sales person who will contact the lead in future",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "contact_by",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"in_filter": 1,
|
||||
"label": "Next Contact By",
|
||||
"oldfieldname": "contact_by",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Profile",
|
||||
"print_hide": 0,
|
||||
"reqd": 0,
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"description": "Your sales person will get a reminder on this date to contact the lead",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "contact_date",
|
||||
"fieldtype": "Date",
|
||||
"in_filter": 1,
|
||||
"label": "Next Contact Date",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "contact_date",
|
||||
"oldfieldtype": "Date",
|
||||
"reqd": 0,
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"description": "Date on which the lead was last contacted",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "last_contact_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Last Contact Date",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "last_contact_date",
|
||||
"oldfieldtype": "Date",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "company",
|
||||
|
@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.utils import cstr, getdate, cint
|
||||
from webnotes.utils import cstr, cint
|
||||
from webnotes.model.bean import getlist
|
||||
from webnotes import msgprint, _
|
||||
|
||||
@ -17,7 +17,7 @@ class DocType(TransactionBase):
|
||||
self.doclist = doclist
|
||||
self.fname = 'enq_details'
|
||||
self.tname = 'Opportunity Item'
|
||||
|
||||
|
||||
self._prev = webnotes._dict({
|
||||
"contact_date": webnotes.conn.get_value("Opportunity", self.doc.name, "contact_date") if \
|
||||
(not cint(self.doc.fields.get("__islocal"))) else None,
|
||||
@ -70,10 +70,6 @@ class DocType(TransactionBase):
|
||||
|
||||
|
||||
def on_update(self):
|
||||
# Add to calendar
|
||||
if self.doc.contact_date and self.doc.contact_date_ref != self.doc.contact_date:
|
||||
webnotes.conn.set(self.doc, 'contact_date_ref',self.doc.contact_date)
|
||||
|
||||
self.add_calendar_event()
|
||||
|
||||
def add_calendar_event(self, opts=None, force=False):
|
||||
@ -101,14 +97,6 @@ class DocType(TransactionBase):
|
||||
|
||||
super(DocType, self).add_calendar_event(opts, force)
|
||||
|
||||
def set_last_contact_date(self):
|
||||
if self.doc.contact_date_ref and self.doc.contact_date_ref != self.doc.contact_date:
|
||||
if getdate(self.doc.contact_date_ref) < getdate(self.doc.contact_date):
|
||||
self.doc.last_contact_date=self.doc.contact_date_ref
|
||||
else:
|
||||
msgprint("Contact Date Cannot be before Last Contact Date")
|
||||
raise Exception
|
||||
|
||||
def validate_item_details(self):
|
||||
if not getlist(self.doclist, 'enquiry_details'):
|
||||
msgprint("Please select items for which enquiry needs to be made")
|
||||
@ -122,7 +110,6 @@ class DocType(TransactionBase):
|
||||
|
||||
def validate(self):
|
||||
self.set_status()
|
||||
self.set_last_contact_date()
|
||||
self.validate_item_details()
|
||||
self.validate_uom_is_integer("uom", "qty")
|
||||
self.validate_lead_cust()
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-03-07 18:50:30",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-10-03 16:30:58",
|
||||
"modified": "2013-10-09 15:26:29",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -404,20 +404,6 @@
|
||||
"oldfieldtype": "Date",
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"description": "Date on which the lead was last contacted",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "last_contact_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Last Contact Date",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "last_contact_date",
|
||||
"oldfieldtype": "Date",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "to_discuss",
|
||||
|
@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.utils import cstr, getdate
|
||||
from webnotes.utils import cstr
|
||||
from webnotes.model.bean import getlist
|
||||
from webnotes.model.code import get_obj
|
||||
from webnotes import _, msgprint
|
||||
@ -97,24 +97,9 @@ class DocType(SellingController):
|
||||
msgprint("You can not select non sales item "+d.item_code+" in Sales Quotation")
|
||||
raise Exception
|
||||
|
||||
#--------------Validation For Last Contact Date-----------------
|
||||
# ====================================================================================================================
|
||||
def set_last_contact_date(self):
|
||||
#if not self.doc.contact_date_ref:
|
||||
#self.doc.contact_date_ref=self.doc.contact_date
|
||||
#self.doc.last_contact_date=self.doc.contact_date_ref
|
||||
if self.doc.contact_date_ref and self.doc.contact_date_ref != self.doc.contact_date:
|
||||
if getdate(self.doc.contact_date_ref) < getdate(self.doc.contact_date):
|
||||
self.doc.last_contact_date=self.doc.contact_date_ref
|
||||
else:
|
||||
msgprint("Contact Date Cannot be before Last Contact Date")
|
||||
raise Exception
|
||||
|
||||
def validate(self):
|
||||
super(DocType, self).validate()
|
||||
|
||||
self.set_status()
|
||||
self.set_last_contact_date()
|
||||
self.validate_order_type()
|
||||
self.validate_for_items()
|
||||
|
||||
|
@ -126,7 +126,7 @@ class DocType(SellingController):
|
||||
self.validate_po()
|
||||
self.validate_uom_is_integer("stock_uom", "qty")
|
||||
self.validate_for_items()
|
||||
self.validate_warehouse_user()
|
||||
self.validate_warehouse()
|
||||
sales_com_obj = get_obj(dt = 'Sales Common')
|
||||
sales_com_obj.check_active_sales_items(self)
|
||||
sales_com_obj.check_conversion_rate(self)
|
||||
@ -147,14 +147,15 @@ class DocType(SellingController):
|
||||
if not self.doc.delivery_status: self.doc.delivery_status = 'Not Delivered'
|
||||
|
||||
|
||||
def validate_warehouse_user(self):
|
||||
from stock.utils import validate_warehouse_user
|
||||
def validate_warehouse(self):
|
||||
from stock.utils import validate_warehouse_user, validate_warehouse_company
|
||||
|
||||
warehouses = list(set([d.reserved_warehouse for d in
|
||||
self.doclist.get({"doctype": self.tname}) if d.reserved_warehouse]))
|
||||
|
||||
for w in warehouses:
|
||||
validate_warehouse_user(w)
|
||||
validate_warehouse_company(w, self.doc.company)
|
||||
|
||||
def validate_with_previous_doc(self):
|
||||
super(DocType, self).validate_with_previous_doc(self.tname, {
|
||||
|
@ -74,7 +74,7 @@ def get_item_details(args):
|
||||
out.update(apply_pos_settings(pos_settings, out))
|
||||
|
||||
if args.doctype in ("Sales Invoice", "Delivery Note"):
|
||||
if item_bean.doc.has_serial_no and not args.serial_no:
|
||||
if item_bean.doc.has_serial_no == "Yes" and not args.serial_no:
|
||||
out.serial_no = _get_serial_nos_by_fifo(args, item_bean)
|
||||
|
||||
return out
|
||||
|
@ -186,7 +186,6 @@ class DocType(SellingController):
|
||||
|
||||
# create stock ledger entry
|
||||
self.update_stock_ledger()
|
||||
self.update_serial_nos()
|
||||
|
||||
self.credit_limit()
|
||||
|
||||
@ -204,42 +203,12 @@ class DocType(SellingController):
|
||||
self.update_prevdoc_status()
|
||||
|
||||
self.update_stock_ledger()
|
||||
self.update_serial_nos(cancel=True)
|
||||
|
||||
webnotes.conn.set(self.doc, 'status', 'Cancelled')
|
||||
self.cancel_packing_slips()
|
||||
|
||||
self.make_cancel_gl_entries()
|
||||
|
||||
def update_serial_nos(self, cancel=False):
|
||||
from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos
|
||||
update_serial_nos_after_submit(self, "Delivery Note", "delivery_note_details")
|
||||
update_serial_nos_after_submit(self, "Delivery Note", "packing_details")
|
||||
|
||||
for table_fieldname in ("delivery_note_details", "packing_details"):
|
||||
for d in self.doclist.get({"parentfield": table_fieldname}):
|
||||
for serial_no in get_serial_nos(d.serial_no):
|
||||
sr = webnotes.bean("Serial No", serial_no)
|
||||
if cancel:
|
||||
sr.doc.status = "Available"
|
||||
for fieldname in ("warranty_expiry_date", "delivery_document_type",
|
||||
"delivery_document_no", "delivery_date", "delivery_time", "customer",
|
||||
"customer_name"):
|
||||
sr.doc.fields[fieldname] = None
|
||||
else:
|
||||
sr.doc.delivery_document_type = "Delivery Note"
|
||||
sr.doc.delivery_document_no = self.doc.name
|
||||
sr.doc.delivery_date = self.doc.posting_date
|
||||
sr.doc.delivery_time = self.doc.posting_time
|
||||
sr.doc.customer = self.doc.customer
|
||||
sr.doc.customer_name = self.doc.customer_name
|
||||
if sr.doc.warranty_period:
|
||||
sr.doc.warranty_expiry_date = add_days(cstr(self.doc.posting_date),
|
||||
cint(sr.doc.warranty_period))
|
||||
sr.doc.status = 'Delivered'
|
||||
|
||||
sr.save()
|
||||
|
||||
def validate_packed_qty(self):
|
||||
"""
|
||||
Validate that if packed qty exists, it should be equal to qty
|
||||
|
@ -85,7 +85,6 @@ class DocType:
|
||||
pr_bean = webnotes.bean("Purchase Receipt", pr)
|
||||
|
||||
pr_bean.run_method("update_ordered_qty", is_cancelled="Yes")
|
||||
pr_bean.run_method("update_serial_nos", cancel=True)
|
||||
|
||||
webnotes.conn.sql("""delete from `tabStock Ledger Entry`
|
||||
where voucher_type='Purchase Receipt' and voucher_no=%s""", pr)
|
||||
@ -97,5 +96,4 @@ class DocType:
|
||||
pr_bean = webnotes.bean("Purchase Receipt", pr)
|
||||
pr_bean.run_method("update_ordered_qty")
|
||||
pr_bean.run_method("update_stock")
|
||||
pr_bean.run_method("update_serial_nos")
|
||||
pr_bean.run_method("make_gl_entries")
|
||||
pr_bean.run_method("make_gl_entries")
|
@ -68,22 +68,14 @@ class DocType(BuyingController):
|
||||
self.doc.status = "Draft"
|
||||
|
||||
import utilities
|
||||
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped",
|
||||
"Cancelled"])
|
||||
utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped", "Cancelled"])
|
||||
|
||||
# restrict material request type
|
||||
self.validate_value("material_request_type", "in", ["Purchase", "Transfer"])
|
||||
|
||||
# Get Purchase Common Obj
|
||||
pc_obj = get_obj(dt='Purchase Common')
|
||||
|
||||
|
||||
# Validate for items
|
||||
pc_obj.validate_for_items(self)
|
||||
|
||||
# Validate qty against SO
|
||||
self.validate_qty_against_so()
|
||||
|
||||
self.validate_qty_against_so()
|
||||
|
||||
def update_bin(self, is_submit, is_stopped):
|
||||
""" Update Quantity Requested for Purchase in Bin for Material Request of type 'Purchase'"""
|
||||
|
@ -246,26 +246,12 @@ class DocType(BuyingController):
|
||||
|
||||
self.update_stock()
|
||||
|
||||
self.update_serial_nos()
|
||||
from stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
|
||||
update_serial_nos_after_submit(self, "Purchase Receipt", "purchase_receipt_details")
|
||||
|
||||
purchase_controller.update_last_purchase_rate(self, 1)
|
||||
|
||||
self.make_gl_entries()
|
||||
|
||||
def update_serial_nos(self, cancel=False):
|
||||
from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos
|
||||
update_serial_nos_after_submit(self, "Purchase Receipt", "purchase_receipt_details")
|
||||
|
||||
for d in self.doclist.get({"parentfield": "purchase_receipt_details"}):
|
||||
for serial_no in get_serial_nos(d.serial_no):
|
||||
sr = webnotes.bean("Serial No", serial_no)
|
||||
if cancel:
|
||||
sr.doc.supplier = None
|
||||
sr.doc.supplier_name = None
|
||||
else:
|
||||
sr.doc.supplier = self.doc.supplier
|
||||
sr.doc.supplier_name = self.doc.supplier_name
|
||||
sr.save()
|
||||
|
||||
def check_next_docstatus(self):
|
||||
submit_rv = webnotes.conn.sql("select t1.name from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2 where t1.name = t2.parent and t2.purchase_receipt = '%s' and t1.docstatus = 1" % (self.doc.name))
|
||||
@ -292,7 +278,6 @@ class DocType(BuyingController):
|
||||
self.update_ordered_qty()
|
||||
|
||||
self.update_stock()
|
||||
self.update_serial_nos(cancel=True)
|
||||
|
||||
self.update_prevdoc_status()
|
||||
pc_obj.update_last_purchase_rate(self, 0)
|
||||
@ -308,7 +293,7 @@ class DocType(BuyingController):
|
||||
|
||||
def get_rate(self,arg):
|
||||
return get_obj('Purchase Common').get_rate(arg,self)
|
||||
|
||||
|
||||
def get_gl_entries_for_stock(self, warehouse_account=None):
|
||||
against_stock_account = self.get_company_default("stock_received_but_not_billed")
|
||||
|
||||
|
@ -4,14 +4,22 @@
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.utils import cint, getdate, nowdate
|
||||
from webnotes.utils import cint, getdate, nowdate, cstr, flt, add_days
|
||||
import datetime
|
||||
from webnotes import msgprint, _
|
||||
from webnotes import msgprint, _, ValidationError
|
||||
|
||||
from controllers.stock_controller import StockController
|
||||
|
||||
class SerialNoCannotCreateDirectError(webnotes.ValidationError): pass
|
||||
class SerialNoCannotCannotChangeError(webnotes.ValidationError): pass
|
||||
class SerialNoCannotCreateDirectError(ValidationError): pass
|
||||
class SerialNoCannotCannotChangeError(ValidationError): pass
|
||||
class SerialNoNotRequiredError(ValidationError): pass
|
||||
class SerialNoRequiredError(ValidationError): pass
|
||||
class SerialNoQtyError(ValidationError): pass
|
||||
class SerialNoItemError(ValidationError): pass
|
||||
class SerialNoWarehouseError(ValidationError): pass
|
||||
class SerialNoStatusError(ValidationError): pass
|
||||
class SerialNoNotExistsError(ValidationError): pass
|
||||
class SerialNoDuplicateError(ValidationError): pass
|
||||
|
||||
class DocType(StockController):
|
||||
def __init__(self, doc, doclist=None):
|
||||
@ -21,13 +29,18 @@ class DocType(StockController):
|
||||
|
||||
def validate(self):
|
||||
if self.doc.fields.get("__islocal") and self.doc.warehouse:
|
||||
webnotes.throw(_("New Serial No cannot have Warehouse. Warehouse must be set by Stock Entry or Purchase Receipt"),
|
||||
SerialNoCannotCreateDirectError)
|
||||
webnotes.throw(_("New Serial No cannot have Warehouse. Warehouse must be \
|
||||
set by Stock Entry or Purchase Receipt"), SerialNoCannotCreateDirectError)
|
||||
|
||||
self.validate_warranty_status()
|
||||
self.validate_amc_status()
|
||||
self.validate_warehouse()
|
||||
self.validate_item()
|
||||
|
||||
if self.via_stock_ledger:
|
||||
self.set_status()
|
||||
self.set_purchase_details()
|
||||
self.set_sales_details()
|
||||
|
||||
def validate_amc_status(self):
|
||||
"""
|
||||
@ -41,7 +54,8 @@ class DocType(StockController):
|
||||
validate warranty status
|
||||
"""
|
||||
if (self.doc.maintenance_status == 'Out of Warranty' and self.doc.warranty_expiry_date and getdate(self.doc.warranty_expiry_date) >= datetime.date.today()) or (self.doc.maintenance_status == 'Under Warranty' and (not self.doc.warranty_expiry_date or getdate(self.doc.warranty_expiry_date) < datetime.date.today())):
|
||||
msgprint("Warranty expiry date and maintenance status mismatch. Please verify", raise_exception=1)
|
||||
msgprint("Warranty expiry date and maintenance status mismatch. Please verify",
|
||||
raise_exception=1)
|
||||
|
||||
|
||||
def validate_warehouse(self):
|
||||
@ -49,10 +63,11 @@ class DocType(StockController):
|
||||
item_code, warehouse = webnotes.conn.get_value("Serial No",
|
||||
self.doc.name, ["item_code", "warehouse"])
|
||||
if item_code != self.doc.item_code:
|
||||
webnotes.throw(_("Item Code cannot be changed for Serial No."), SerialNoCannotCannotChangeError)
|
||||
webnotes.throw(_("Item Code cannot be changed for Serial No."),
|
||||
SerialNoCannotCannotChangeError)
|
||||
if not self.via_stock_ledger and warehouse != self.doc.warehouse:
|
||||
webnotes.throw(_("Warehouse cannot be changed for Serial No."), SerialNoCannotCannotChangeError)
|
||||
|
||||
webnotes.throw(_("Warehouse cannot be changed for Serial No."),
|
||||
SerialNoCannotCannotChangeError)
|
||||
|
||||
def validate_item(self):
|
||||
"""
|
||||
@ -67,16 +82,89 @@ class DocType(StockController):
|
||||
self.doc.item_name = item.item_name
|
||||
self.doc.brand = item.brand
|
||||
self.doc.warranty_period = item.warranty_period
|
||||
|
||||
|
||||
def set_status(self):
|
||||
last_sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry`
|
||||
where (serial_no like %s or serial_no like %s or serial_no=%s)
|
||||
and item_code=%s and ifnull(is_cancelled, 'No')='No'
|
||||
order by name desc limit 1""",
|
||||
("%%%s%%" % (self.doc.name+"\n"), "%%%s%%" % ("\n"+self.doc.name), self.doc.name,
|
||||
self.doc.item_code), as_dict=1)
|
||||
|
||||
if last_sle:
|
||||
if last_sle[0].voucher_type == "Stock Entry":
|
||||
document_type = webnotes.conn.get_value("Stock Entry", last_sle[0].voucher_no,
|
||||
"purpose")
|
||||
else:
|
||||
document_type = last_sle[0].voucher_type
|
||||
|
||||
if last_sle[0].actual_qty > 0:
|
||||
if document_type == "Sales Return":
|
||||
self.doc.status = "Sales Returned"
|
||||
else:
|
||||
self.doc.status = "Available"
|
||||
else:
|
||||
if document_type == "Purchase Return":
|
||||
self.doc.status = "Purchase Returned"
|
||||
elif last_sle[0].voucher_type in ("Delivery Note", "Sales Invoice"):
|
||||
self.doc.status = "Delivered"
|
||||
else:
|
||||
self.doc.status = "Not Available"
|
||||
|
||||
def set_purchase_details(self):
|
||||
purchase_sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry`
|
||||
where (serial_no like %s or serial_no like %s or serial_no=%s)
|
||||
and item_code=%s and actual_qty > 0
|
||||
and ifnull(is_cancelled, 'No')='No' order by name asc limit 1""",
|
||||
("%%%s%%" % (self.doc.name+"\n"), "%%%s%%" % ("\n"+self.doc.name), self.doc.name,
|
||||
self.doc.item_code), as_dict=1)
|
||||
|
||||
if purchase_sle:
|
||||
self.doc.purchase_document_type = purchase_sle[0].voucher_type
|
||||
self.doc.purchase_document_no = purchase_sle[0].voucher_no
|
||||
self.doc.purchase_date = purchase_sle[0].posting_date
|
||||
self.doc.purchase_time = purchase_sle[0].posting_time
|
||||
self.doc.purchase_rate = purchase_sle[0].incoming_rate
|
||||
if purchase_sle[0].voucher_type == "Purchase Receipt":
|
||||
self.doc.supplier, self.doc.supplier_name = \
|
||||
webnotes.conn.get_value("Purchase Receipt", purchase_sle[0].voucher_no,
|
||||
["supplier", "supplier_name"])
|
||||
else:
|
||||
for fieldname in ("purchase_document_type", "purchase_document_no",
|
||||
"purchase_date", "purchase_time", "purchase_rate", "supplier", "supplier_name"):
|
||||
self.doc.fields[fieldname] = None
|
||||
|
||||
def set_sales_details(self):
|
||||
delivery_sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry`
|
||||
where (serial_no like %s or serial_no like %s or serial_no=%s)
|
||||
and item_code=%s and actual_qty<0
|
||||
and voucher_type in ('Delivery Note', 'Sales Invoice')
|
||||
and ifnull(is_cancelled, 'No')='No' order by name desc limit 1""",
|
||||
("%%%s%%" % (self.doc.name+"\n"), "%%%s%%" % ("\n"+self.doc.name), self.doc.name,
|
||||
self.doc.item_code), as_dict=1)
|
||||
if delivery_sle:
|
||||
self.doc.delivery_document_type = delivery_sle[0].voucher_type
|
||||
self.doc.delivery_document_no = delivery_sle[0].voucher_no
|
||||
self.doc.delivery_date = delivery_sle[0].posting_date
|
||||
self.doc.delivery_time = delivery_sle[0].posting_time
|
||||
self.doc.customer, self.doc.customer_name = \
|
||||
webnotes.conn.get_value(delivery_sle[0].voucher_type, delivery_sle[0].voucher_no,
|
||||
["customer", "customer_name"])
|
||||
if self.doc.warranty_period:
|
||||
self.doc.warranty_expiry_date = add_days(cstr(delivery_sle[0].posting_date),
|
||||
cint(self.doc.warranty_period))
|
||||
else:
|
||||
for fieldname in ("delivery_document_type", "delivery_document_no",
|
||||
"delivery_date", "delivery_time", "customer", "customer_name",
|
||||
"warranty_expiry_date"):
|
||||
self.doc.fields[fieldname] = None
|
||||
|
||||
def on_trash(self):
|
||||
if self.doc.status == 'Delivered':
|
||||
msgprint("Cannot trash Serial No : %s as it is already Delivered" % (self.doc.name), raise_exception = 1)
|
||||
webnotes.throw(_("Delivered Serial No ") + self.doc.name + _(" can not be deleted"))
|
||||
if self.doc.warehouse:
|
||||
webnotes.throw(_("Cannot delete Serial No in warehouse. First remove from warehouse, then delete.") + \
|
||||
": " + self.doc.name)
|
||||
|
||||
def on_cancel(self):
|
||||
self.on_trash()
|
||||
webnotes.throw(_("Cannot delete Serial No in warehouse. \
|
||||
First remove from warehouse, then delete.") + ": " + self.doc.name)
|
||||
|
||||
def on_rename(self, new, old, merge=False):
|
||||
"""rename serial_no text fields"""
|
||||
@ -93,3 +181,106 @@ class DocType(StockController):
|
||||
webnotes.conn.sql("""update `tab%s` set serial_no = %s
|
||||
where name=%s""" % (dt[0], '%s', '%s'),
|
||||
('\n'.join(serial_nos), item[0]))
|
||||
|
||||
def process_serial_no(sle):
|
||||
item_det = get_item_details(sle.item_code)
|
||||
validate_serial_no(sle, item_det)
|
||||
update_serial_nos(sle, item_det)
|
||||
|
||||
def validate_serial_no(sle, item_det):
|
||||
if item_det.has_serial_no=="No":
|
||||
if sle.serial_no:
|
||||
webnotes.throw(_("Serial Number should be blank for Non Serialized Item" + ": "
|
||||
+ sle.item_code), SerialNoNotRequiredError)
|
||||
else:
|
||||
if sle.serial_no:
|
||||
serial_nos = get_serial_nos(sle.serial_no)
|
||||
if cint(sle.actual_qty) != flt(sle.actual_qty):
|
||||
webnotes.throw(_("Serial No qty cannot be a fraction") + \
|
||||
(": %s (%s)" % (sle.item_code, sle.actual_qty)))
|
||||
if len(serial_nos) and len(serial_nos) != abs(cint(sle.actual_qty)):
|
||||
webnotes.throw(_("Serial Nos do not match with qty") + \
|
||||
(": %s (%s)" % (sle.item_code, sle.actual_qty)), SerialNoQtyError)
|
||||
|
||||
for serial_no in serial_nos:
|
||||
if webnotes.conn.exists("Serial No", serial_no):
|
||||
sr = webnotes.bean("Serial No", serial_no)
|
||||
|
||||
if sr.doc.item_code!=sle.item_code:
|
||||
webnotes.throw(_("Serial No does not belong to Item") +
|
||||
(": %s (%s)" % (sle.item_code, serial_no)), SerialNoItemError)
|
||||
|
||||
if sr.doc.warehouse and sle.actual_qty > 0:
|
||||
webnotes.throw(_("Same Serial No") + ": " + sr.doc.name +
|
||||
_(" can not be received twice"), SerialNoDuplicateError)
|
||||
|
||||
if sle.actual_qty < 0:
|
||||
if sr.doc.warehouse!=sle.warehouse:
|
||||
webnotes.throw(_("Serial No") + ": " + serial_no +
|
||||
_(" does not belong to Warehouse") + ": " + sle.warehouse,
|
||||
SerialNoWarehouseError)
|
||||
|
||||
if sle.voucher_type in ("Delivery Note", "Sales Invoice") \
|
||||
and sr.doc.status != "Available":
|
||||
webnotes.throw(_("Serial No status must be 'Available' to Deliver")
|
||||
+ ": " + serial_no, SerialNoStatusError)
|
||||
elif sle.actual_qty < 0:
|
||||
# transfer out
|
||||
webnotes.throw(_("Serial No must exist to transfer out.") + \
|
||||
": " + serial_no, SerialNoNotExistsError)
|
||||
elif not item_det.serial_no_series:
|
||||
webnotes.throw(_("Serial Number Required for Serialized Item" + ": "
|
||||
+ sle.item_code), SerialNoRequiredError)
|
||||
|
||||
def update_serial_nos(sle, item_det):
|
||||
if sle.serial_no:
|
||||
serial_nos = get_serial_nos(sle.serial_no)
|
||||
for serial_no in serial_nos:
|
||||
if webnotes.conn.exists("Serial No", serial_no):
|
||||
sr = webnotes.bean("Serial No", serial_no)
|
||||
sr.make_controller().via_stock_ledger = True
|
||||
sr.doc.warehouse = sle.warehouse if sle.actual_qty > 0 else None
|
||||
sr.save()
|
||||
elif sle.actual_qty > 0:
|
||||
make_serial_no(serial_no, sle)
|
||||
elif sle.actual_qty > 0 and item_det.serial_no_series:
|
||||
from webnotes.model.doc import make_autoname
|
||||
serial_nos = []
|
||||
for i in xrange(cint(sle.actual_qty)):
|
||||
serial_nos.append(make_serial_no(make_autoname(item_det.serial_no_series), sle))
|
||||
sle.serial_no = "\n".join(serial_nos)
|
||||
|
||||
def get_item_details(item_code):
|
||||
return webnotes.conn.sql("""select name, has_batch_no, docstatus,
|
||||
is_stock_item, has_serial_no, serial_no_series
|
||||
from tabItem where name=%s""", item_code, as_dict=True)[0]
|
||||
|
||||
def get_serial_nos(serial_no):
|
||||
return [s.strip() for s in cstr(serial_no).strip().replace(',', '\n').split('\n') if s.strip()]
|
||||
|
||||
def make_serial_no(serial_no, sle):
|
||||
sr = webnotes.new_bean("Serial No")
|
||||
sr.doc.serial_no = serial_no
|
||||
sr.doc.item_code = sle.item_code
|
||||
sr.make_controller().via_stock_ledger = True
|
||||
sr.insert()
|
||||
sr.doc.warehouse = sle.warehouse
|
||||
sr.doc.status = "Available"
|
||||
sr.save()
|
||||
webnotes.msgprint(_("Serial No created") + ": " + sr.doc.name)
|
||||
return sr.doc.name
|
||||
|
||||
def update_serial_nos_after_submit(controller, parenttype, parentfield):
|
||||
if not hasattr(webnotes, "new_stock_ledger_entries"):
|
||||
return
|
||||
|
||||
for d in controller.doclist.get({"parentfield": parentfield}):
|
||||
serial_no = None
|
||||
for sle in webnotes.new_stock_ledger_entries:
|
||||
if sle.voucher_detail_no==d.name:
|
||||
serial_no = sle.serial_no
|
||||
break
|
||||
|
||||
if d.serial_no != serial_no:
|
||||
d.serial_no = serial_no
|
||||
webnotes.conn.set_value(d.doctype, d.name, "serial_no", serial_no)
|
||||
|
@ -51,13 +51,15 @@ class DocType(StockController):
|
||||
|
||||
def on_submit(self):
|
||||
self.update_stock_ledger()
|
||||
self.update_serial_no(1)
|
||||
|
||||
from stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
|
||||
update_serial_nos_after_submit(self, "Stock Entry", "mtn_details")
|
||||
|
||||
self.update_production_order(1)
|
||||
self.make_gl_entries()
|
||||
|
||||
def on_cancel(self):
|
||||
self.update_stock_ledger()
|
||||
self.update_serial_no(0)
|
||||
self.update_production_order(0)
|
||||
self.make_cancel_gl_entries()
|
||||
|
||||
@ -293,24 +295,6 @@ class DocType(StockController):
|
||||
from `tabStock Entry Detail` where parent in (
|
||||
select name from `tabStock Entry` where `%s`=%s and docstatus=1)
|
||||
group by item_code""" % (ref_fieldname, "%s"), (self.doc.fields.get(ref_fieldname),)))
|
||||
|
||||
def update_serial_no(self, is_submit):
|
||||
"""Create / Update Serial No"""
|
||||
|
||||
from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos
|
||||
update_serial_nos_after_submit(self, "Stock Entry", "mtn_details")
|
||||
|
||||
for d in getlist(self.doclist, 'mtn_details'):
|
||||
for serial_no in get_serial_nos(d.serial_no):
|
||||
if self.doc.purpose == 'Purchase Return':
|
||||
sr = webnotes.bean("Serial No", serial_no)
|
||||
sr.doc.status = "Purchase Returned" if is_submit else "Available"
|
||||
sr.save()
|
||||
|
||||
if self.doc.purpose == "Sales Return":
|
||||
sr = webnotes.bean("Serial No", serial_no)
|
||||
sr.doc.status = "Sales Returned" if is_submit else "Delivered"
|
||||
sr.save()
|
||||
|
||||
def update_stock_ledger(self):
|
||||
sl_entries = []
|
||||
|
@ -7,7 +7,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import webnotes, unittest
|
||||
from webnotes.utils import flt
|
||||
from stock.doctype.stock_ledger_entry.stock_ledger_entry import *
|
||||
from stock.doctype.serial_no.serial_no import *
|
||||
from stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ class TestStockEntry(unittest.TestCase):
|
||||
webnotes.bean("Profile", "test2@example.com").get_controller()\
|
||||
.add_roles("Sales User", "Sales Manager", "Material User", "Material Manager")
|
||||
|
||||
from stock.doctype.stock_ledger_entry.stock_ledger_entry import InvalidWarehouseCompany
|
||||
from stock.utils import InvalidWarehouseCompany
|
||||
st1 = webnotes.bean(copy=test_records[0])
|
||||
st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1"
|
||||
st1.insert()
|
||||
@ -721,6 +721,18 @@ class TestStockEntry(unittest.TestCase):
|
||||
se.insert()
|
||||
self.assertRaises(SerialNoNotExistsError, se.submit)
|
||||
|
||||
def test_serial_duplicate(self):
|
||||
self._clear_stock_account_balance()
|
||||
self.test_serial_by_series()
|
||||
|
||||
se = webnotes.bean(copy=test_records[0])
|
||||
se.doclist[1].item_code = "_Test Serialized Item With Series"
|
||||
se.doclist[1].qty = 1
|
||||
se.doclist[1].serial_no = "ABCD00001"
|
||||
se.doclist[1].transfer_qty = 1
|
||||
se.insert()
|
||||
self.assertRaises(SerialNoDuplicateError, se.submit)
|
||||
|
||||
def test_serial_by_series(self):
|
||||
self._clear_stock_account_balance()
|
||||
se = make_serialized_item()
|
||||
|
@ -3,29 +3,17 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _, msgprint, ValidationError
|
||||
from webnotes import _, msgprint
|
||||
from webnotes.utils import cint, flt, getdate, cstr
|
||||
from webnotes.model.controller import DocListController
|
||||
|
||||
class InvalidWarehouseCompany(ValidationError): pass
|
||||
class SerialNoNotRequiredError(ValidationError): pass
|
||||
class SerialNoRequiredError(ValidationError): pass
|
||||
class SerialNoQtyError(ValidationError): pass
|
||||
class SerialNoItemError(ValidationError): pass
|
||||
class SerialNoWarehouseError(ValidationError): pass
|
||||
class SerialNoStatusError(ValidationError): pass
|
||||
class SerialNoNotExistsError(ValidationError): pass
|
||||
|
||||
def get_serial_nos(serial_no):
|
||||
return [s.strip() for s in cstr(serial_no).strip().replace(',', '\n').split('\n') if s.strip()]
|
||||
|
||||
class DocType(DocListController):
|
||||
def __init__(self, doc, doclist=[]):
|
||||
self.doc = doc
|
||||
self.doclist = doclist
|
||||
|
||||
def validate(self):
|
||||
from stock.utils import validate_warehouse_user
|
||||
from stock.utils import validate_warehouse_user, validate_warehouse_company
|
||||
if not hasattr(webnotes, "new_stock_ledger_entries"):
|
||||
webnotes.new_stock_ledger_entries = []
|
||||
|
||||
@ -33,7 +21,7 @@ class DocType(DocListController):
|
||||
self.validate_mandatory()
|
||||
self.validate_item()
|
||||
validate_warehouse_user(self.doc.warehouse)
|
||||
self.validate_warehouse_company()
|
||||
validate_warehouse_company(self.doc.warehouse, self.doc.company)
|
||||
self.scrub_posting_time()
|
||||
|
||||
from accounts.utils import validate_fiscal_year
|
||||
@ -42,7 +30,9 @@ class DocType(DocListController):
|
||||
def on_submit(self):
|
||||
self.check_stock_frozen_date()
|
||||
self.actual_amt_check()
|
||||
self.validate_serial_no()
|
||||
|
||||
from stock.doctype.serial_no.serial_no import process_serial_no
|
||||
process_serial_no(self.doc)
|
||||
|
||||
#check for item quantity available in stock
|
||||
def actual_amt_check(self):
|
||||
@ -63,13 +53,6 @@ class DocType(DocListController):
|
||||
as on %(posting_date)s %(posting_time)s""" % self.doc.fields)
|
||||
|
||||
sself.doc.fields.pop('batch_bal')
|
||||
|
||||
def validate_warehouse_company(self):
|
||||
warehouse_company = webnotes.conn.get_value("Warehouse", self.doc.warehouse, "company")
|
||||
if warehouse_company and warehouse_company != self.doc.company:
|
||||
webnotes.msgprint(_("Warehouse does not belong to company.") + " (" + \
|
||||
self.doc.warehouse + ", " + self.doc.company +")",
|
||||
raise_exception=InvalidWarehouseCompany)
|
||||
|
||||
def validate_mandatory(self):
|
||||
mandatory = ['warehouse','posting_date','voucher_type','voucher_no','actual_qty','company']
|
||||
@ -81,7 +64,10 @@ class DocType(DocListController):
|
||||
msgprint("Warehouse: '%s' does not exist in the system. Please check." % self.doc.fields.get(k), raise_exception = 1)
|
||||
|
||||
def validate_item(self):
|
||||
item_det = self.get_item_details()
|
||||
item_det = webnotes.conn.sql("""select name, has_batch_no, docstatus,
|
||||
is_stock_item, has_serial_no, serial_no_series
|
||||
from tabItem where name=%s""",
|
||||
self.doc.item_code, as_dict=True)[0]
|
||||
|
||||
if item_det.is_stock_item != 'Yes':
|
||||
webnotes.throw("""Item: "%s" is not a Stock Item.""" % self.doc.item_code)
|
||||
@ -99,95 +85,6 @@ class DocType(DocListController):
|
||||
if not self.doc.stock_uom:
|
||||
self.doc.stock_uom = item_det.stock_uom
|
||||
|
||||
def get_item_details(self):
|
||||
return webnotes.conn.sql("""select name, has_batch_no, docstatus,
|
||||
is_stock_item, has_serial_no, serial_no_series
|
||||
from tabItem where name=%s""",
|
||||
self.doc.item_code, as_dict=True)[0]
|
||||
|
||||
def validate_serial_no(self):
|
||||
item_det = self.get_item_details()
|
||||
|
||||
if item_det.has_serial_no=="No":
|
||||
if self.doc.serial_no:
|
||||
webnotes.throw(_("Serial Number should be blank for Non Serialized Item" + ": " + self.doc.item),
|
||||
SerialNoNotRequiredError)
|
||||
else:
|
||||
if self.doc.serial_no:
|
||||
serial_nos = get_serial_nos(self.doc.serial_no)
|
||||
if cint(self.doc.actual_qty) != flt(self.doc.actual_qty):
|
||||
webnotes.throw(_("Serial No qty cannot be a fraction") + \
|
||||
(": %s (%s)" % (self.doc.item_code, self.doc.actual_qty)))
|
||||
if len(serial_nos) and len(serial_nos) != abs(cint(self.doc.actual_qty)):
|
||||
webnotes.throw(_("Serial Nos do not match with qty") + \
|
||||
(": %s (%s)" % (self.doc.item_code, self.doc.actual_qty)), SerialNoQtyError)
|
||||
|
||||
# check serial no exists, if yes then source
|
||||
for serial_no in serial_nos:
|
||||
if webnotes.conn.exists("Serial No", serial_no):
|
||||
sr = webnotes.bean("Serial No", serial_no)
|
||||
|
||||
if sr.doc.item_code!=self.doc.item_code:
|
||||
webnotes.throw(_("Serial No does not belong to Item") + \
|
||||
(": %s (%s)" % (self.doc.item_code, serial_no)), SerialNoItemError)
|
||||
|
||||
sr.make_controller().via_stock_ledger = True
|
||||
|
||||
if self.doc.actual_qty < 0:
|
||||
if sr.doc.warehouse!=self.doc.warehouse:
|
||||
webnotes.throw(_("Serial No") + ": " + serial_no +
|
||||
_(" does not belong to Warehouse") + ": " + self.doc.warehouse,
|
||||
SerialNoWarehouseError)
|
||||
|
||||
if self.doc.voucher_type in ("Delivery Note", "Sales Invoice") \
|
||||
and sr.doc.status != "Available":
|
||||
webnotes.throw(_("Serial No status must be 'Available' to Deliver")
|
||||
+ ": " + serial_no, SerialNoStatusError)
|
||||
|
||||
|
||||
sr.doc.warehouse = None
|
||||
sr.save()
|
||||
else:
|
||||
sr.doc.warehouse = self.doc.warehouse
|
||||
sr.save()
|
||||
else:
|
||||
if self.doc.actual_qty < 0:
|
||||
# transfer out
|
||||
webnotes.throw(_("Serial No must exist to transfer out.") + \
|
||||
": " + serial_no, SerialNoNotExistsError)
|
||||
else:
|
||||
# transfer in
|
||||
self.make_serial_no(serial_no)
|
||||
else:
|
||||
if item_det.serial_no_series:
|
||||
from webnotes.model.doc import make_autoname
|
||||
serial_nos = []
|
||||
for i in xrange(cint(self.doc.actual_qty)):
|
||||
serial_nos.append(self.make_serial_no(make_autoname(item_det.serial_no_series)))
|
||||
self.doc.serial_no = "\n".join(serial_nos)
|
||||
else:
|
||||
webnotes.throw(_("Serial Number Required for Serialized Item" + ": " + self.doc.item),
|
||||
SerialNoRequiredError)
|
||||
|
||||
def make_serial_no(self, serial_no):
|
||||
sr = webnotes.new_bean("Serial No")
|
||||
sr.doc.serial_no = serial_no
|
||||
sr.doc.item_code = self.doc.item_code
|
||||
sr.doc.purchase_rate = self.doc.incoming_rate
|
||||
sr.doc.purchase_document_type = self.doc.voucher_type
|
||||
sr.doc.purchase_document_no = self.doc.voucher_no
|
||||
sr.doc.purchase_date = self.doc.posting_date
|
||||
sr.doc.purchase_time = self.doc.posting_time
|
||||
sr.make_controller().via_stock_ledger = True
|
||||
sr.insert()
|
||||
|
||||
# set warehouse
|
||||
sr.doc.warehouse = self.doc.warehouse
|
||||
sr.doc.status = "Available"
|
||||
sr.save()
|
||||
webnotes.msgprint(_("Serial No created") + ": " + sr.doc.name)
|
||||
return sr.doc.name
|
||||
|
||||
def check_stock_frozen_date(self):
|
||||
stock_frozen_upto = webnotes.conn.get_value('Stock Settings', None, 'stock_frozen_upto') or ''
|
||||
if stock_frozen_upto:
|
||||
@ -199,21 +96,6 @@ class DocType(DocListController):
|
||||
if not self.doc.posting_time or self.doc.posting_time == '00:0':
|
||||
self.doc.posting_time = '00:00'
|
||||
|
||||
def update_serial_nos_after_submit(controller, parenttype, parentfield):
|
||||
if not hasattr(webnotes, "new_stock_ledger_entries"):
|
||||
return
|
||||
|
||||
for d in controller.doclist.get({"parentfield": parentfield}):
|
||||
serial_no = None
|
||||
for sle in webnotes.new_stock_ledger_entries:
|
||||
if sle.voucher_detail_no==d.name:
|
||||
serial_no = sle.serial_no
|
||||
break
|
||||
|
||||
if d.serial_no != serial_no:
|
||||
d.serial_no = serial_no
|
||||
webnotes.conn.set_value(d.doctype, d.name, "serial_no", serial_no)
|
||||
|
||||
def on_doctype_update():
|
||||
if not webnotes.conn.sql("""show index from `tabStock Ledger Entry`
|
||||
where Key_name="posting_sort_index" """):
|
||||
|
@ -9,6 +9,7 @@ from webnotes.defaults import get_global_default
|
||||
from webnotes.utils.email_lib import sendmail
|
||||
|
||||
class UserNotAllowedForWarehouse(webnotes.ValidationError): pass
|
||||
class InvalidWarehouseCompany(webnotes.ValidationError): pass
|
||||
|
||||
def get_stock_balance_on(warehouse, posting_date=None):
|
||||
if not posting_date: posting_date = nowdate()
|
||||
@ -216,6 +217,12 @@ def validate_warehouse_user(warehouse):
|
||||
if warehouse_users and not (webnotes.session.user in warehouse_users):
|
||||
webnotes.throw(_("Not allowed entry in Warehouse") \
|
||||
+ ": " + warehouse, UserNotAllowedForWarehouse)
|
||||
|
||||
def validate_warehouse_company(warehouse, company):
|
||||
warehouse_company = webnotes.conn.get_value("Warehouse", warehouse, "company")
|
||||
if warehouse_company and warehouse_company != company:
|
||||
webnotes.msgprint(_("Warehouse does not belong to company.") + " (" + \
|
||||
warehouse + ", " + company +")", raise_exception=InvalidWarehouseCompany)
|
||||
|
||||
def get_sales_bom_buying_amount(item_code, warehouse, voucher_type, voucher_no, voucher_detail_no,
|
||||
stock_ledger_entries, item_sales_bom):
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-06 14:25:21",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-05-06 14:32:47",
|
||||
"modified": "2013-10-09 12:23:27",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -10,7 +10,7 @@
|
||||
"doctype": "Report",
|
||||
"is_standard": "Yes",
|
||||
"name": "__common__",
|
||||
"query": "SELECT\n ms_item.scheduled_date as \"Schedule Date:Date:120\",\n\tms_item.item_code as \"Item Code:Link/Item:120\",\n\tms_item.item_name as \"Item Name::120\",\n\tms_item.serial_no as \"Serial No::120\",\n\tms_item.incharge_name as \"Incharge::120\",\n\tms.customer_name as \"Customer:Link/Customer:120\",\n\tms.address_display as \"Customer Address::120\",\n\tms.sales_order_no as \"Sales Order:Link/Sales Order:120\",\n\tms.company as \"Company:Link/Company:120\"\n\t\nFROM\n\t`tabMaintenance Schedule` ms, `tabMaintenance Schedule Detail` ms_item\nWHERE\n\tms.name = ms_item.parent and ms.docstatus = 1\nORDER BY\n\tms_item.scheduled_date asc, ms_item.item_code asc",
|
||||
"query": "SELECT\n ms_sch.scheduled_date as \"Schedule Date:Date:120\",\n\tms_sch.item_code as \"Item Code:Link/Item:120\",\n\tms_sch.item_name as \"Item Name::120\",\n\tms_sch.serial_no as \"Serial No::120\",\n\tms_sch.incharge_name as \"Incharge::120\",\n\tms.customer_name as \"Customer:Link/Customer:120\",\n\tms.address_display as \"Customer Address::120\",\n\tms_item.prevdoc_docname as \"Sales Order:Link/Sales Order:120\",\n\tms.company as \"Company:Link/Company:120\"\n\t\nFROM\n\t`tabMaintenance Schedule` ms, \n `tabMaintenance Schedule Detail` ms_sch, \n `tabMaintenance Schedule Item` ms_item\nWHERE\n\tms.name = ms_sch.parent and ms.name = ms_item.parent and ms.docstatus = 1\nORDER BY\n\tms_sch.scheduled_date asc, ms_sch.item_code asc",
|
||||
"ref_doctype": "Maintenance Schedule",
|
||||
"report_name": "Maintenance Schedules",
|
||||
"report_type": "Query Report"
|
||||
|
Loading…
x
Reference in New Issue
Block a user