Merge branch 'master' into edge

This commit is contained in:
Nabin Hait 2013-03-26 15:44:41 +05:30
commit 8e64160121
39 changed files with 690 additions and 382 deletions

View File

@ -1,6 +1,11 @@
from __future__ import unicode_literals
test_records = [
[{
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2012",
"year_start_date": "2012-01-01"
}],
[{
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2013",

View File

@ -84,13 +84,13 @@ cur_frm.cscript.update_totals = function(doc) {
var td=0.0; var tc =0.0;
var el = getchildren('Journal Voucher Detail', doc.name, 'entries');
for(var i in el) {
td += flt(el[i].debit);
tc += flt(el[i].credit);
td += flt(el[i].debit, 2);
tc += flt(el[i].credit, 2);
}
var doc = locals[doc.doctype][doc.name];
doc.total_debit = td;
doc.total_credit = tc;
doc.difference = flt(td - tc);
doc.difference = flt((td - tc), 2);
refresh_many(['total_debit','total_credit','difference']);
}

View File

@ -114,8 +114,8 @@ class DocType(AccountsController):
debit, credit = 0.0, 0.0
debit_list, credit_list = [], []
for d in getlist(self.doclist, 'entries'):
debit += flt(d.debit)
credit += flt(d.credit)
debit += flt(d.debit, 2)
credit += flt(d.credit, 2)
if flt(d.debit)>0 and (d.account not in debit_list): debit_list.append(d.account)
if flt(d.credit)>0 and (d.account not in credit_list): credit_list.append(d.account)
@ -289,32 +289,32 @@ class DocType(AccountsController):
if not getlist(self.doclist,'entries'):
msgprint("Please enter atleast 1 entry in 'GL Entries' table")
else:
flag, self.doc.total_debit, self.doc.total_credit = 0,0,0
diff = flt(self.doc.difference)
flag, self.doc.total_debit, self.doc.total_credit = 0, 0, 0
diff = flt(self.doc.difference, 2)
# If any row without amount, set the diff on that row
for d in getlist(self.doclist,'entries'):
if not d.credit and not d.debit and flt(diff) != 0:
if not d.credit and not d.debit and diff != 0:
if diff>0:
d.credit = flt(diff)
d.credit = diff
elif diff<0:
d.debit = flt(diff)
d.debit = diff
flag = 1
# Set the diff in a new row
if flag == 0 and (flt(diff) != 0):
if flag == 0 and diff != 0:
jd = addchild(self.doc, 'entries', 'Journal Voucher Detail', self.doclist)
if diff>0:
jd.credit = flt(abs(diff))
jd.credit = abs(diff)
elif diff<0:
jd.debit = flt(abs(diff))
jd.debit = abs(diff)
# Set the total debit, total credit and difference
for d in getlist(self.doclist,'entries'):
self.doc.total_debit += flt(d.debit)
self.doc.total_credit += flt(d.credit)
self.doc.total_debit += flt(d.debit, 2)
self.doc.total_credit += flt(d.credit, 2)
self.doc.difference = flt(self.doc.total_debit) - flt(self.doc.total_credit)
self.doc.difference = flt(self.doc.total_debit, 2) - flt(self.doc.total_credit, 2)
def get_outstanding_invoices(self):
self.doclist = self.doc.clear_table(self.doclist, 'entries')
@ -375,9 +375,9 @@ def get_against_sales_invoice(doctype, txt, searchfield, start, page_len, filter
(filters["account"], "%%%s%%" % txt, start, page_len))
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
return webnotes.conn.sql("""select name, posting_date, user_remark
return webnotes.conn.sql("""select jv.name, jv.posting_date, jv.user_remark
from `tabJournal Voucher` jv, `tabJournal Voucher Detail` jv_detail
where jv_detail.parent = jv.name and jv_detail.account = %s and docstatus = 1
where jv_detail.parent = jv.name and jv_detail.account = %s and jv.docstatus = 1
and jv.%s like %s order by jv.name desc limit %s, %s""" %
("%s", searchfield, "%s", "%s", "%s"),
(filters["account"], "%%%s%%" % txt, start, page_len))

View File

@ -16,30 +16,37 @@
from __future__ import unicode_literals
import webnotes
from webnotes.model import db_exists
from webnotes.model.bean import copy_doclist
from webnotes import msgprint
sql = webnotes.conn.sql
from webnotes import msgprint, _
from webnotes.utils import cint
class DocType:
def __init__(self,doc,doclist=[]):
self.doc, self.doclist = doc,doclist
#--------------------get naming series from sales invoice-----------------
def get_series(self):
import webnotes.model.doctype
docfield = webnotes.model.doctype.get('Sales Invoice')
series = [d.options for d in docfield if d.doctype == 'DocField' and d.fieldname == 'naming_series']
series = [d.options for d in docfield
if d.doctype == 'DocField' and d.fieldname == 'naming_series']
return series and series[0] or ''
def validate(self):
res = sql("select name, user from `tabPOS Setting` where ifnull(user, '') = '%s' and name != '%s' and company = '%s'" % (self.doc.user, self.doc.name, self.doc.company))
self.check_for_duplicate()
self.validate_expense_account()
def check_for_duplicate(self):
res = webnotes.conn.sql("""select name, user from `tabPOS Setting`
where ifnull(user, '') = %s and name != %s and company = %s""",
(self.doc.user, self.doc.name, self.doc.company))
if res:
if res[0][1]:
msgprint("POS Setting '%s' already created for user: '%s' and company: '%s'"%(res[0][0], res[0][1], self.doc.company), raise_exception=1)
msgprint("POS Setting '%s' already created for user: '%s' and company: '%s'" %
(res[0][0], res[0][1], self.doc.company), raise_exception=1)
else:
msgprint("Global POS Setting already created - %s for this company: '%s'" % (res[0][0], self.doc.company), raise_exception=1)
msgprint("Global POS Setting already created - %s for this company: '%s'" %
(res[0][0], self.doc.company), raise_exception=1)
def validate_expense_account(self):
if cint(webnotes.defaults.get_global_default("auto_inventory_accounting")) \
and not self.doc.expense_account:
msgprint(_("Expense Account is mandatory"), raise_exception=1)

View File

@ -1,8 +1,8 @@
[
{
"creation": "2013-01-24 11:03:29",
"creation": "2013-03-26 11:03:07",
"docstatus": 0,
"modified": "2013-03-25 15:27:52",
"modified": "2013-03-26 12:48:18",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -18,7 +18,8 @@
"parent": "POS Setting",
"parentfield": "fields",
"parenttype": "DocType",
"permlevel": 0
"permlevel": 0,
"read_only": 0
},
{
"doctype": "DocPerm",
@ -141,12 +142,15 @@
"reqd": 1
},
{
"depends_on": "eval:sys_defaults.auto_inventory_accounting",
"doctype": "DocField",
"fieldname": "expense_account",
"fieldtype": "Link",
"hidden": 0,
"label": "Expense Account",
"options": "Account",
"reqd": 1
"print_hide": 1,
"reqd": 0
},
{
"doctype": "DocField",

View File

@ -306,7 +306,9 @@ class DocType(BuyingController):
def set_against_expense_account(self):
auto_inventory_accounting = \
cint(webnotes.defaults.get_global_default("auto_inventory_accounting"))
stock_not_billed_account = self.get_company_default("stock_received_but_not_billed")
if auto_inventory_accounting:
stock_not_billed_account = self.get_company_default("stock_received_but_not_billed")
against_accounts = []
for item in self.doclist.get({"parentfield": "entries"}):

View File

@ -307,35 +307,27 @@ cur_frm.cscript['Make Delivery Note'] = function() {
);
}
// Make Bank Voucher Button
// -------------------------
cur_frm.cscript.make_bank_voucher = function(doc, dt, dn) {
$c('accounts.get_default_bank_account', { company: cur_frm.doc.company }, function(r, rt) {
if(!r.exc) {
cur_frm.cscript.make_jv(cur_frm.doc, null, null, r.message);
cur_frm.cscript.make_bank_voucher = function() {
wn.call({
method: "accounts.doctype.journal_voucher.journal_voucher.get_default_bank_cash_account",
args: {
"company": cur_frm.doc.company,
"voucher_type": "Bank Voucher"
},
callback: function(r) {
cur_frm.cscript.make_jv(cur_frm.doc, null, null, r.message);
}
});
}
/* ***************************** Get Query Functions ************************** */
// Debit To
// ---------
cur_frm.fields_dict.debit_to.get_query = function(doc) {
return 'SELECT tabAccount.name FROM tabAccount WHERE tabAccount.debit_or_credit="Debit" AND tabAccount.is_pl_account = "No" AND tabAccount.group_or_ledger="Ledger" AND tabAccount.docstatus!=2 AND tabAccount.company="'+doc.company+'" AND tabAccount.%(key)s LIKE "%s"'
}
// Cash/bank account
//------------------
cur_frm.fields_dict.cash_bank_account.get_query = function(doc) {
return 'SELECT tabAccount.name FROM tabAccount WHERE tabAccount.debit_or_credit="Debit" AND tabAccount.is_pl_account = "No" AND tabAccount.group_or_ledger="Ledger" AND tabAccount.docstatus!=2 AND tabAccount.company="'+doc.company+'" AND tabAccount.%(key)s LIKE "%s"'
}
// Write off account
//------------------
cur_frm.fields_dict.write_off_account.get_query = function(doc) {
return 'SELECT tabAccount.name FROM tabAccount WHERE tabAccount.debit_or_credit="Debit" AND tabAccount.is_pl_account = "Yes" AND tabAccount.group_or_ledger="Ledger" AND tabAccount.docstatus!=2 AND tabAccount.company="'+doc.company+'" AND tabAccount.%(key)s LIKE "%s"'
}
@ -429,17 +421,24 @@ cur_frm.fields_dict.delivery_note_main.get_query = function(doc) {
cur_frm.cscript.income_account = function(doc, cdt, cdn){
cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "income_account");
}
cur_frm.cscript.expense_account = function(doc, cdt, cdn){
cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "expense_account");
}
cur_frm.cscript.copy_account_in_all_row = function(doc, cdt, cdn, fieldname) {
var d = locals[cdt][cdn];
if(d.income_account){
if(d[fieldname]){
var cl = getchildren('Sales Invoice Item', doc.name, cur_frm.cscript.fname, doc.doctype);
for(var i = 0; i < cl.length; i++){
if(!cl[i].income_account) cl[i].income_account = d.income_account;
if(!cl[i][fieldname]) cl[i][fieldname] = d[fieldname];
}
}
refresh_field(cur_frm.cscript.fname);
}
cur_frm.cscript.cost_center = function(doc, cdt, cdn){
var d = locals[cdt][cdn];
if(d.cost_center){
@ -451,10 +450,6 @@ cur_frm.cscript.cost_center = function(doc, cdt, cdn){
refresh_field(cur_frm.cscript.fname);
}
/* **************************************** Utility Functions *************************************** */
// Details Calculation
// --------------------
cur_frm.cscript.calc_adjustment_amount = function(doc,cdt,cdn) {
var doc = locals[doc.doctype][doc.name];
var el = getchildren('Sales Invoice Advance',doc.name,'advance_adjustment_details');
@ -488,8 +483,9 @@ cur_frm.cscript.make_jv = function(doc, dt, dn, bank_account) {
// credit to bank
var d1 = wn.model.add_child(jv, 'Journal Voucher Detail', 'entries');
d1.account = bank_account;
d1.account = bank_account.account;
d1.debit = doc.outstanding_amount;
d1.balance = bank_account.balance;
loaddoc('Journal Voucher', jv.name);
}

View File

@ -318,9 +318,8 @@ class DocType(SellingController):
@property
def pos_details(self):
if not hasattr(self, "_pos_details"):
dtl = webnotes.conn.sql("""select income_account, warehouse, cost_center,
expense_account from `tabPOS Setting` where user = %s and company = %s""",
(webnotes.session['user'], self.doc.company), as_dict=1)
dtl = webnotes.conn.sql("""select * from `tabPOS Setting` where user = %s
and company = %s""", (webnotes.session['user'], self.doc.company), as_dict=1)
if not dtl:
dtl = webnotes.conn.sql("""select income_account, warehouse, cost_center,
expense_account from `tabPOS Setting` where ifnull(user,'') = ''
@ -641,7 +640,6 @@ class DocType(SellingController):
self.values.append({
'item_code' : d['item_code'],
'warehouse' : wh,
'transaction_date' : getdate(self.doc.modified).strftime('%Y-%m-%d'),
'posting_date' : self.doc.posting_date,
'posting_time' : self.doc.posting_time,
'voucher_type' : 'Sales Invoice',

View File

@ -1,4 +1,5 @@
erpnext.updates = [
["27th March", ["Rename multiple items together. Go to Setup > Rename Tool"]],
["19th March", ["Sales and Purchase Return Tool deprecated. Use Stock Entry instead."]],
["12th March", ["Updates to website module. Added more options in Style Settings and Website Settings."]],
["5th March", ["Refactored Upload Attendance Tool"]],

View File

@ -44,20 +44,17 @@ erpnext.hr.AttendanceControlPanel = wn.ui.form.Controller.extend({
show_upload: function() {
var me = this;
var $wrapper = $(cur_frm.fields_dict.upload_html.wrapper).empty();
var upload_area = $('<div id="dit-upload-area"></div>').appendTo($wrapper);
// upload
wn.upload.make({
parent: $('#dit-upload-area'),
parent: $wrapper,
args: {
method: 'hr.doctype.upload_attendance.upload_attendance.upload'
},
sample_url: "e.g. http://example.com/somefile.csv",
callback: function(r) {
var $log_wrapper = $(cur_frm.fields_dict.import_log.wrapper).empty();
var log_area = $('<div id="dit-output"></div>').appendTo($log_wrapper);
$wrapper.find(".dit-progress-area").toggle(false);
if(!r.messages) r.messages = [];
// replace links if error has occured
if(r.exc || r.error) {
@ -81,7 +78,7 @@ erpnext.hr.AttendanceControlPanel = wn.ui.form.Controller.extend({
console.log(r.messages);
$.each(r.messages, function(i, v) {
var $p = $('<p>').html(v).appendTo('#dit-output');
var $p = $('<p>').html(v).appendTo($log_wrapper);
if(v.substr(0,5)=='Error') {
$p.css('color', 'red');
} else if(v.substr(0,8)=='Inserted') {
@ -96,11 +93,8 @@ erpnext.hr.AttendanceControlPanel = wn.ui.form.Controller.extend({
});
// rename button
$('#dit-upload-area form input[type="submit"]')
$wrapper.find('form input[type="submit"]')
.attr('value', 'Upload and Import')
.click(function() {
$wrapper.find(".dit-progress-area").toggle(true);
});
}
})

View File

@ -3,8 +3,8 @@ import webnotes
def execute():
dn_list = webnotes.conn.sql("""select name from `tabDelivery Note` where docstatus < 2""")
for dn in dn_list:
webnotes.bean("Delivery Note", dn[0]).set_buying_amount()
webnotes.bean("Delivery Note", dn[0]).run_method("set_buying_amount")
si_list = webnotes.conn.sql("""select name from `tabSales Invoice` where docstatus < 2""")
for si in si_list:
webnotes.bean("Sales Invoice", si[0]).set_buying_amount()
webnotes.bean("Sales Invoice", si[0]).run_method("set_buying_amount")

View File

@ -1,7 +1,7 @@
import webnotes
def execute():
for purchase_invoice in webnotes.conn.sql("""select distinct parent
for purchase_invoice in webnotes.conn.sql_list("""select distinct parent
from `tabPurchase Invoice Item` where docstatus = 1 and ifnull(valuation_rate, 0)=0"""):
pi = webnotes.get_obj("Purchase Invoice", purchase_invoice)
pi.calculate_taxes_and_totals()

View File

@ -1,24 +1,59 @@
import webnotes
def execute():
add_group_accounts()
add_ledger_accounts()
def _check(parent_account, company):
def _get_root(is_pl_account, debit_or_credit):
res = webnotes.conn.sql("""select name from `tabAccount`
where company=%s and is_pl_account = %s and debit_or_credit = %s
and ifnull(parent_account, "") ="" """, (company, is_pl_account, debit_or_credit))
return res and res[0][0] or None
if not webnotes.conn.exists("Account", parent_account):
if parent_account.startswith("Current Assets"):
parent_account = _get_root("No", "Debit")
elif parent_account.startswith("Direct Expenses"):
parent_account = _get_root("Yes", "Debit")
elif parent_account.startswith("Current Liabilities"):
parent_account = _get_root("No", "Credit")
return parent_account
def add_group_accounts():
accounts_to_add = [
["Stock Assets", "Current Assets", "Group", ""],
["Stock Expenses", "Direct Expenses", "Group", "Expense Account"],
["Stock Liabilities", "Current Liabilities", "Group", ""],
]
add_accounts(accounts_to_add, _check)
def add_ledger_accounts():
accounts_to_add = [
["Stock In Hand", "Stock Assets", "Ledger", ""],
["Stock Debit But Not Billed", "Stock Assets", "Ledger", ""],
["Stock Expenses", "Direct Expenses", "Group", "Expense Account"],
["Cost of Goods Sold", "Stock Expenses", "Ledger", "Expense Account"],
["Stock Adjustment", "Stock Expenses", "Ledger", "Expense Account"],
["Expenses Included In Valuation", "Stock Expenses", "Ledger", "Expense Account"],
["Stock Liabilities", "Current Liabilities", "Group", ""],
["Stock Received But Not Billed", "Stock Liabilities", "Ledger", ""],
]
add_accounts(accounts_to_add)
for company, abbr in webnotes.conn.sql_list("""select name, abbr from `tabCompany`"""):
def add_accounts(accounts_to_add, check_fn=None):
for company, abbr in webnotes.conn.sql("""select name, abbr from `tabCompany`"""):
for account_name, parent_account_name, group_or_ledger, account_type in accounts_to_add:
if not webnotes.conn.exists("Account", "%s - %s" % (account_name, abbr)):
parent_account = "%s - %s" % (parent_account_name, abbr)
if check_fn:
parent_account = check_fn(parent_account, company)
account = webnotes.bean({
"doctype": "Account",
"account_name": account_name,
"parent_account": "%s - %s" % (parent_account_name, abbr),
"parent_account": parent_account,
"group_or_ledger": group_or_ledger,
"account_type": account_type,
"company": company

View File

@ -0,0 +1,6 @@
import webnotes
def execute():
webnotes.conn.sql("""update `tabProfile` set user_type='System User'
where user_type='Partner' and exists (select name from `tabUserRole`
where parent=`tabProfile`.name)""")

View File

@ -217,5 +217,6 @@ patch_list = [
"execute:webnotes.bean('Global Defaults').save()",
"patches.march_2013.p07_update_project_in_stock_ledger",
"execute:webnotes.bean('Style Settings').save() #2013-03-25",
"execute:webnotes.conn.set_value('Email Settings', None, 'send_print_in_body_and_attachment', 1)"
"execute:webnotes.conn.set_value('Email Settings', None, 'send_print_in_body_and_attachment', 1)",
"patches.march_2013.p09_unset_user_type_partner",
]

View File

@ -26,6 +26,9 @@ cur_frm.cscript.refresh = function(doc) {
.appendTo(cur_frm.fields_dict.project_tasks.wrapper);
cur_frm.gantt_area.empty();
erpnext.show_task_gantt(cur_frm.gantt_area, cur_frm.docname);
} else {
if(cur_frm.gantt_area)
cur_frm.gantt_area.empty();
}
}

View File

@ -1,8 +1,8 @@
[
{
"creation": "2013-01-28 10:06:01",
"creation": "2013-01-28 17:07:01",
"docstatus": 0,
"modified": "2013-01-28 15:28:49",
"modified": "2013-03-26 14:05:01",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -23,18 +23,13 @@
"permlevel": 0
},
{
"amend": 0,
"create": 1,
"doctype": "DocPerm",
"name": "__common__",
"parent": "Lead",
"parentfield": "permissions",
"parenttype": "DocType",
"permlevel": 0,
"read": 1,
"report": 1,
"submit": 0,
"write": 1
"submit": 0
},
{
"doctype": "DocType",
@ -64,6 +59,19 @@
"reqd": 1,
"search_index": 1
},
{
"description": "Name of organization from where lead has come",
"doctype": "DocField",
"fieldname": "company_name",
"fieldtype": "Data",
"in_filter": 1,
"in_list_view": 1,
"label": "Company Name",
"oldfieldname": "company_name",
"oldfieldtype": "Data",
"reqd": 0,
"search_index": 0
},
{
"doctype": "DocField",
"fieldname": "email_id",
@ -105,45 +113,12 @@
"no_copy": 1,
"oldfieldname": "source",
"oldfieldtype": "Select",
"options": "\nAdvertisement\nBlog\nCampaign\nCall\nCustomer\nExhibition\nSupplier\nWebsite\nEmail",
"options": "\nAdvertisement\nBlog Post\nCampaign\nCall\nCustomer\nExhibition\nSupplier\nWebsite\nEmail",
"reqd": 0,
"search_index": 0
},
{
"doctype": "DocField",
"fieldname": "communication_history",
"fieldtype": "Section Break"
},
{
"allow_on_submit": 0,
"doctype": "DocField",
"fieldname": "communication_html",
"fieldtype": "HTML",
"label": "Communication HTML",
"oldfieldname": "follow_up",
"oldfieldtype": "Table"
},
{
"doctype": "DocField",
"fieldname": "sb8",
"fieldtype": "Section Break",
"label": "Lead Details"
},
{
"description": "Name of organization from where lead has come",
"doctype": "DocField",
"fieldname": "company_name",
"fieldtype": "Data",
"in_filter": 1,
"in_list_view": 1,
"label": "Company Name",
"oldfieldname": "company_name",
"oldfieldtype": "Data",
"reqd": 0,
"search_index": 0
},
{
"depends_on": "eval:doc.source == 'Existing Customer'",
"depends_on": "eval:doc.source == 'Customer'",
"description": "Source of th",
"doctype": "DocField",
"fieldname": "customer",
@ -168,19 +143,24 @@
},
{
"doctype": "DocField",
"fieldname": "column_break1",
"fieldtype": "Column Break",
"width": "50%"
"fieldname": "communication_history",
"fieldtype": "Section Break"
},
{
"allow_on_submit": 0,
"doctype": "DocField",
"fieldname": "communication_html",
"fieldtype": "HTML",
"label": "Communication HTML",
"oldfieldname": "follow_up",
"oldfieldtype": "Table"
},
{
"doctype": "DocField",
"fieldname": "type",
"fieldtype": "Select",
"in_filter": 1,
"label": "Lead Type",
"oldfieldname": "type",
"oldfieldtype": "Select",
"options": "\nClient\nChannel Partner\nConsultant"
"fieldname": "contact_info",
"fieldtype": "Section Break",
"label": "Contact Info",
"oldfieldtype": "Column Break"
},
{
"doctype": "DocField",
@ -190,13 +170,6 @@
"oldfieldname": "remark",
"oldfieldtype": "Text"
},
{
"doctype": "DocField",
"fieldname": "contact_info",
"fieldtype": "Section Break",
"label": "Contact Info",
"oldfieldtype": "Column Break"
},
{
"doctype": "DocField",
"fieldname": "phone",
@ -312,6 +285,16 @@
"label": "More Info",
"oldfieldtype": "Section Break"
},
{
"doctype": "DocField",
"fieldname": "type",
"fieldtype": "Select",
"in_filter": 1,
"label": "Lead Type",
"oldfieldname": "type",
"oldfieldtype": "Select",
"options": "\nClient\nChannel Partner\nConsultant"
},
{
"default": "__user",
"doctype": "DocField",
@ -462,18 +445,69 @@
"label": "Blog Subscriber"
},
{
"cancel": 0,
"create": 1,
"doctype": "DocPerm",
"role": "Sales User"
"permlevel": 0,
"report": 1,
"role": "Guest",
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 1,
"report": 0,
"role": "Sales User",
"write": 0
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 1,
"report": 0,
"role": "Sales Manager",
"write": 0
},
{
"amend": 0,
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"role": "Sales Manager"
"permlevel": 0,
"report": 1,
"role": "Sales Manager",
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"doctype": "DocPerm",
"role": "System Manager"
"permlevel": 0,
"report": 1,
"role": "Sales User",
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 1,
"role": "All"
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"doctype": "DocPerm",
"permlevel": 0,
"report": 1,
"role": "System Manager",
"write": 1
}
]

View File

@ -860,9 +860,9 @@ cur_frm.cscript.commission_rate = function(doc, cdt, cdn) {
alert("Commision rate cannot be greater than 100.");
doc.total_commission = 0;
doc.commission_rate = 0;
}
else
} else {
doc.total_commission = doc.net_total * doc.commission_rate / 100;
}
refresh_many(['total_commission','commission_rate']);
}
@ -874,9 +874,9 @@ cur_frm.cscript.total_commission = function(doc, cdt, cdn) {
alert("Total commission cannot be greater than net total.");
doc.total_commission = 0;
doc.commission_rate = 0;
}
else
} else {
doc.commission_rate = doc.total_commission * 100 / doc.net_total;
}
refresh_many(['total_commission','commission_rate']);
}
}

View File

@ -1,10 +1,10 @@
[
{
"creation": "2012-07-12 23:29:44",
"creation": "2013-03-25 17:53:21",
"docstatus": 0,
"modified": "2013-03-25 17:32:05",
"modified": "2013-03-25 18:41:27",
"modified_by": "Administrator",
"owner": "harshada@webnotestech.com"
"owner": "Administrator"
},
{
"allow_copy": 1,
@ -34,9 +34,7 @@
"parenttype": "DocType",
"permlevel": 0,
"read": 1,
"report": 0,
"role": "System Manager",
"submit": 0,
"write": 1
},
{

View File

@ -76,6 +76,12 @@ wn.module_page["Setup"] = [
label: wn._("Manage numbering series"),
"description":wn._("Set multiple numbering series for transactions")
},
{
"route":"Form/Rename Tool",
doctype: "Rename Tool",
label: wn._("Rename Tool"),
"description":wn._("Rename multiple items in one go")
},
]
},
{

View File

@ -1,189 +1,169 @@
[
{
"owner": "Administrator",
"creation": "2013-02-22 01:28:05",
"docstatus": 0,
"creation": "2010-08-08 17:09:35",
"modified": "2013-03-26 07:58:20",
"modified_by": "Administrator",
"modified": "2012-04-02 14:03:39"
"owner": "Administrator"
},
{
"doctype": "Table Mapper Detail",
"name": "__common__",
"parent": "Purchase Order-Purchase Receipt",
"doctype": "Table Mapper Detail",
"parenttype": "DocType Mapper",
"parentfield": "table_mapper_details"
"parentfield": "table_mapper_details",
"parenttype": "DocType Mapper"
},
{
"doctype": "Field Mapper Detail",
"map": "Yes",
"name": "__common__",
"parent": "Purchase Order-Purchase Receipt",
"doctype": "Field Mapper Detail",
"parenttype": "DocType Mapper",
"parentfield": "field_mapper_details"
"parentfield": "field_mapper_details",
"parenttype": "DocType Mapper"
},
{
"name": "__common__",
"to_doctype": "Purchase Receipt",
"module": "Stock",
"doctype": "DocType Mapper",
"from_doctype": "Purchase Order",
"module": "Stock",
"name": "__common__",
"ref_doc_submitted": 1,
"from_doctype": "Purchase Order"
"to_doctype": "Purchase Receipt"
},
{
"name": "Purchase Order-Purchase Receipt",
"doctype": "DocType Mapper"
"doctype": "DocType Mapper",
"name": "Purchase Order-Purchase Receipt"
},
{
"match_id": 0,
"to_field": "supplier",
"checking_operator": "=",
"doctype": "Field Mapper Detail",
"from_field": "supplier",
"checking_operator": "="
"match_id": 0,
"to_field": "supplier"
},
{
"match_id": 0,
"to_field": "company",
"checking_operator": "=",
"doctype": "Field Mapper Detail",
"from_field": "company",
"checking_operator": "="
"match_id": 0,
"to_field": "company"
},
{
"match_id": 0,
"to_field": "currency",
"checking_operator": "=",
"doctype": "Field Mapper Detail",
"from_field": "currency",
"checking_operator": "="
"match_id": 0,
"to_field": "currency"
},
{
"to_field": "prevdoc_detail_docname",
"doctype": "Field Mapper Detail",
"from_field": "name",
"match_id": 1,
"from_field": "name"
"to_field": "prevdoc_detail_docname"
},
{
"to_field": "prevdoc_docname",
"doctype": "Field Mapper Detail",
"from_field": "parent",
"match_id": 1,
"from_field": "parent"
"to_field": "prevdoc_docname"
},
{
"to_field": "prevdoc_doctype",
"doctype": "Field Mapper Detail",
"from_field": "parenttype",
"match_id": 1,
"from_field": "parenttype"
"to_field": "prevdoc_doctype"
},
{
"match_id": 1,
"to_field": "item_code",
"checking_operator": "=",
"doctype": "Field Mapper Detail",
"from_field": "item_code",
"checking_operator": "="
},
{
"to_field": "received_qty",
"doctype": "Field Mapper Detail",
"match_id": 1,
"from_field": "eval:(flt(obj.qty) - flt(obj.received_qty)) "
"to_field": "item_code"
},
{
"to_field": "qty",
"doctype": "Field Mapper Detail",
"from_field": "eval:(flt(obj.qty) - flt(obj.received_qty)) ",
"match_id": 1,
"from_field": "eval:(flt(obj.qty) - flt(obj.received_qty)) "
"to_field": "received_qty"
},
{
"to_field": "stock_qty",
"doctype": "Field Mapper Detail",
"from_field": "eval:(flt(obj.qty) - flt(obj.received_qty)) ",
"match_id": 1,
"from_field": "eval:(flt(obj.qty) - flt(obj.received_qty)) * flt(obj.conversion_factor)"
"to_field": "qty"
},
{
"to_field": "import_amount",
"doctype": "Field Mapper Detail",
"from_field": "eval:(flt(obj.qty) - flt(obj.received_qty)) * flt(obj.conversion_factor)",
"match_id": 1,
"from_field": "eval:(flt(obj.qty) - flt(obj.received_qty)) * flt(obj.import_rate)"
"to_field": "stock_qty"
},
{
"to_field": "amount",
"doctype": "Field Mapper Detail",
"from_field": "eval:(flt(obj.qty) - flt(obj.received_qty)) * flt(obj.import_rate)",
"match_id": 1,
"from_field": "eval:(flt(obj.qty) - flt(obj.received_qty)) * flt(obj.purchase_rate)"
"to_field": "import_amount"
},
{
"to_field": "schedule_date",
"doctype": "Field Mapper Detail",
"from_field": "eval:(flt(obj.qty) - flt(obj.received_qty)) * flt(obj.purchase_rate)",
"match_id": 1,
"from_field": "schedule_date"
"to_field": "amount"
},
{
"to_field": "net_total",
"doctype": "Field Mapper Detail",
"from_field": "schedule_date",
"match_id": 1,
"to_field": "schedule_date"
},
{
"doctype": "Field Mapper Detail",
"from_field": "net_total",
"match_id": 0,
"from_field": "net_total"
"to_field": "net_total"
},
{
"to_field": "grand_total",
"doctype": "Field Mapper Detail",
"from_field": "grand_total",
"match_id": 0,
"from_field": "grand_total"
"to_field": "grand_total"
},
{
"to_field": "total_tax",
"doctype": "Field Mapper Detail",
"from_field": "total_tax",
"match_id": 0,
"from_field": "total_tax"
"to_field": "total_tax"
},
{
"to_field": "conversion_rate",
"doctype": "Field Mapper Detail",
"from_field": "conversion_rate",
"match_id": 0,
"from_field": "conversion_rate"
"to_field": "conversion_rate"
},
{
"reference_key": "prevdoc_detail_docname",
"match_id": 1,
"reference_doctype_key": "prevdoc_doctype",
"to_field": "purchase_receipt_details",
"doctype": "Table Mapper Detail",
"from_field": "po_details",
"from_table": "Purchase Order Item",
"match_id": 1,
"reference_doctype_key": "prevdoc_doctype",
"reference_key": "prevdoc_detail_docname",
"to_field": "purchase_receipt_details",
"to_table": "Purchase Receipt Item",
"validation_logic": "docstatus=1 and qty > ifnull(received_qty,0)"
},
{
"reference_key": "prevdoc_detail_docname",
"match_id": 1,
"reference_doctype_key": "prevdoc_doctype",
"to_field": "purchase_receipt_details",
"doctype": "Table Mapper Detail",
"from_field": "po_details",
"from_table": "Purchase Order Item",
"to_table": "Purchase Receipt Item",
"validation_logic": "docstatus=1 and qty > ifnull(received_qty,0)"
},
{
"reference_key": "prevdoc_docname",
"match_id": 0,
"doctype": "Table Mapper Detail",
"from_table": "Purchase Order",
"match_id": 0,
"reference_key": "prevdoc_docname",
"to_table": "Purchase Receipt",
"validation_logic": "docstatus = 1"
},
{
"match_id": 2,
"to_field": "purchase_tax_details",
"doctype": "Table Mapper Detail",
"from_field": "purchase_tax_details",
"from_table": "Purchase Taxes and Charges",
"to_table": "Purchase Taxes and Charges",
"validation_logic": "docstatus = 1"
},
{
"match_id": 2,
"to_field": "purchase_tax_details",
"doctype": "Table Mapper Detail",
"from_field": "purchase_tax_details",
"from_table": "Purchase Taxes and Charges",
"to_table": "Purchase Taxes and Charges",
"validation_logic": "docstatus = 1"
}

View File

@ -310,6 +310,17 @@ cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
}
}
cur_frm.cscript.expense_account = function(doc, cdt, cdn){
var d = locals[cdt][cdn];
if(d.expense_account) {
var cl = getchildren('Delivery Note Item', doc.name, cur_frm.cscript.fname, doc.doctype);
for(var i = 0; i < cl.length; i++){
if(!cl[i].expense_account) cl[i].expense_account = d.expense_account;
}
}
refresh_field(cur_frm.cscript.fname);
}
// expense account
cur_frm.fields_dict['delivery_note_details'].grid.get_field('expense_account').get_query = function(doc) {
return {

View File

@ -377,7 +377,6 @@ class DocType(SellingController):
self.values.append({
'item_code' : d['item_code'],
'warehouse' : wh,
'transaction_date' : getdate(self.doc.modified).strftime('%Y-%m-%d'),
'posting_date' : self.doc.posting_date,
'posting_time' : self.doc.posting_time,
'voucher_type' : 'Delivery Note',

View File

@ -146,4 +146,23 @@ test_records = [
"is_sub_contracted_item": "No",
"stock_uom": "_Test UOM"
}],
[{
"doctype": "Item",
"item_code": "_Test Serialized Item",
"item_name": "_Test Serialized Item",
"description": "_Test Serialized Item",
"item_group": "_Test Item Group Desktops",
"is_stock_item": "Yes",
"is_asset_item": "No",
"has_batch_no": "No",
"has_serial_no": "Yes",
"is_purchase_item": "Yes",
"is_sales_item": "Yes",
"is_service_item": "No",
"is_sample_item": "No",
"inspection_required": "No",
"is_pro_applicable": "No",
"is_sub_contracted_item": "No",
"stock_uom": "_Test UOM"
}],
]

View File

@ -19,14 +19,11 @@ import webnotes
from webnotes.utils import cint, getdate, nowdate
import datetime
sql = webnotes.conn.sql
msgprint = webnotes.msgprint
from webnotes import msgprint, _
from controllers.stock_controller import StockController
from utilities.transaction_base import TransactionBase
class DocType(TransactionBase):
class DocType(StockController):
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
@ -54,21 +51,14 @@ class DocType(TransactionBase):
"""
Validate whether serial no is required for this item
"""
item = sql("select name, has_serial_no from tabItem where name = '%s'" % self.doc.item_code)
item = webnotes.conn.sql("select name, has_serial_no from tabItem where name = '%s'" % self.doc.item_code)
if not item:
msgprint("Item is not exists in the system", raise_exception=1)
elif item[0][1] == 'No':
msgprint("To proceed please select 'Yes' in 'Has Serial No' in Item master: '%s'" % self.doc.item_code, raise_exception=1)
# ---------
# validate
# ---------
def validate(self):
# import utilities
# utilities.validate_status(self.doc.status, ["In Store", "Delivered",
# "Not in Use", "Purchase Returned"])
self.validate_warranty_status()
self.validate_amc_status()
self.validate_warehouse()
@ -77,10 +67,12 @@ class DocType(TransactionBase):
def on_update(self):
if self.doc.warehouse and self.doc.status == 'In Store' \
and cint(self.doc.sle_exists) == 0 and \
not sql("""select name from `tabStock Ledger Entry` where serial_no = %s and
ifnull(is_cancelled, 'No') = 'No'""", self.doc.name):
not webnotes.conn.sql("""select name from `tabStock Ledger Entry`
where serial_no = %s and ifnull(is_cancelled, 'No') = 'No'""", self.doc.name):
self.make_stock_ledger_entry(1)
webnotes.conn.set(self.doc, 'sle_exists', 1)
self.make_gl_entries()
def make_stock_ledger_entry(self, qty):
from webnotes.model.code import get_obj
@ -105,15 +97,13 @@ class DocType(TransactionBase):
get_obj('Stock Ledger').update_stock(values)
# ---------
# on trash
# ---------
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)
elif self.doc.status == 'In Store':
webnotes.conn.set(self.doc, 'status', 'Not in Use')
self.make_stock_ledger_entry(-1)
self.make_gl_entries(cancel=True)
def on_cancel(self):
@ -121,6 +111,7 @@ class DocType(TransactionBase):
def on_restore(self):
self.make_stock_ledger_entry(1)
self.make_gl_entries()
def on_rename(self, new, old):
"""rename serial_no text fields"""
@ -135,7 +126,16 @@ class DocType(TransactionBase):
where name=%s""" % (dt[0], '%s', '%s'),
('\n'.join(serial_nos), item[0]))
def make_gl_entries(self, cancel=False):
if not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")):
return
from accounts.general_ledger import make_gl_entries
against_stock_account = self.get_company_default("stock_adjustment_account")
gl_entries = self.get_gl_entries_for_stock(against_stock_account, self.doc.purchase_rate)
for entry in gl_entries:
entry["posting_date"] = self.doc.purchase_date
if gl_entries:
make_gl_entries(gl_entries, cancel)

View File

@ -1,93 +1,102 @@
# 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/>.
# For license information, please see license.txt
from __future__ import unicode_literals
import unittest
import webnotes
from webnotes.tests import insert_test_data
company = webnotes.conn.get_default("company")
import webnotes, unittest
class TestSerialNo(unittest.TestCase):
def setUp(self):
webnotes.conn.begin()
self.insert_test_data()
def tearDown(self):
# print "Message Log:", "\n--\n".join(webnotes.message_log)
# print "Debug Log:", "\n--\n".join(webnotes.debug_log)
webnotes.conn.rollback()
def test_aii_gl_entries_for_serial_no_in_store(self):
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
def test_serialized_stock_entry(self):
data = [["2012-01-01", "01:00", "10001", 400, 400],
["2012-01-01", "03:00", "10002", 500, 700],
["2012-01-01", "04:00", "10003", 700, 700],
["2012-01-01", "05:00", "10004", 1200, 800],
["2012-01-01", "05:00", "10005", 800, 800],
["2012-01-01", "02:00", "10006", 1200, 800],
["2012-01-01", "06:00", "10007", 1500, 900]]
for d in data:
webnotes.bean([{
"doctype": "Serial No",
"item_code": "Nebula 8",
"warehouse": "Default Warehouse",
"status": "In Store",
"sle_exists": 0,
"purchase_date": d[0],
"purchase_time": d[1],
"serial_no": d[2],
"purchase_rate": d[3],
"company": company,
}]).insert()
sr = webnotes.bean(copy=test_records[0])
sr.doc.serial_no = "_Test Serial No 1"
sr.insert()
stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company",
"stock_in_hand_account")
against_stock_account = webnotes.conn.get_value("Company", "_Test Company",
"stock_adjustment_account")
# check stock ledger entries
sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry`
where voucher_type = 'Serial No' and voucher_no = %s""", sr.doc.name, as_dict=1)[0]
self.assertTrue(sle)
self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty],
["_Test Serialized Item", "_Test Warehouse", 1.0])
for d in data:
res = webnotes.conn.sql("""select valuation_rate from `tabStock Ledger Entry`
where posting_date=%s and posting_time=%s and actual_qty=1 and serial_no=%s""",
(d[0], d[1], d[2]))
self.assertEquals(res[0][0], d[4])
# check gl entries
gl_entries = webnotes.conn.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Serial No' and voucher_no=%s
order by account desc""", sr.doc.name, as_dict=1)
self.assertTrue(gl_entries)
print "deleted"
webnotes.delete_doc("Serial No", "10002")
expected_values = [
[stock_in_hand_account, 1000.0, 0.0],
[against_stock_account, 0.0, 1000.0]
]
test_data = [["10001", 400, 400],
["10003", 700, 766.666667],
["10004", 1200, 875],
["10005", 800, 860],
["10006", 1200, 800],
["10007", 1500, 966.666667]]
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_values[i][0], gle.account)
self.assertEquals(expected_values[i][1], gle.debit)
self.assertEquals(expected_values[i][2], gle.credit)
for d in test_data:
res = webnotes.conn.sql("""select valuation_rate from `tabStock Ledger Entry`
where actual_qty=1 and serial_no=%s""", (d[0],))
self.assertEquals(res[0][0], d[2])
sr.load_from_db()
self.assertEquals(sr.doc.sle_exists, 1)
# save again
sr.save()
gl_entries = webnotes.conn.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Serial No' and voucher_no=%s
order by account desc""", sr.doc.name, as_dict=1)
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_values[i][0], gle.account)
self.assertEquals(expected_values[i][1], gle.debit)
self.assertEquals(expected_values[i][2], gle.credit)
# trash/cancel
sr.submit()
sr.cancel()
gl_count = webnotes.conn.sql("""select count(name) from `tabGL Entry`
where voucher_type='Serial No' and voucher_no=%s and ifnull(is_cancelled, 'No') = 'Yes'
order by account asc, name asc""", sr.doc.name)
self.assertEquals(gl_count[0][0], 4)
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
def test_aii_gl_entries_for_serial_no_delivered(self):
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
sr = webnotes.bean(copy=test_records[0])
sr.doc.serial_no = "_Test Serial No 2"
sr.doc.status = "Delivered"
sr.insert()
gl_entries = webnotes.conn.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Serial No' and voucher_no=%s
order by account desc""", sr.doc.name, as_dict=1)
self.assertFalse(gl_entries)
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
def insert_test_data(self):
# 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"})
# 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")
test_records = [
[
{
"company": "_Test Company",
"doctype": "Serial No",
"serial_no": "_Test Serial No",
"status": "In Store",
"item_code": "_Test Serialized Item",
"item_group": "_Test Item Group",
"warehouse": "_Test Warehouse",
"purchase_rate": 1000.0,
"purchase_time": "11:37:39",
"purchase_date": "2013-02-26",
'fiscal_year': "_Test Fiscal Year 2013"
}
]
]

View File

@ -55,6 +55,7 @@ class DocType(StockController):
self.validate_finished_goods()
self.validate_return_reference_doc()
self.validate_with_material_request()
self.validate_fiscal_year()
def on_submit(self):
self.update_serial_no(1)
@ -68,6 +69,11 @@ class DocType(StockController):
self.update_production_order(0)
self.make_gl_entries()
def validate_fiscal_year(self):
import accounts.utils
accounts.utils.validate_fiscal_year(self.doc.posting_date, self.doc.fiscal_year,
self.meta.get_label("posting_date"))
def validate_purpose(self):
valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer",
"Manufacture/Repack", "Subcontract", "Sales Return", "Purchase Return"]
@ -604,7 +610,8 @@ class DocType(StockController):
'is_cancelled': (is_cancelled ==1) and 'Yes' or 'No',
'batch_no': cstr(d.batch_no).strip(),
'serial_no': cstr(d.serial_no).strip(),
"project": self.doc.project_name
"project": self.doc.project_name,
"fiscal_year": self.doc.fiscal_year,
})
def get_cust_values(self):
@ -776,8 +783,6 @@ def make_return_jv(stock_entry):
from accounts.utils import get_balance_on
for r in result:
if not r.get("account"):
print result
jv_list.append({
"__islocal": 1,
"doctype": "Journal Voucher Detail",

View File

@ -1,8 +1,8 @@
[
{
"creation": "2013-03-11 12:34:40",
"creation": "2013-03-26 06:51:17",
"docstatus": 0,
"modified": "2013-03-19 17:48:29",
"modified": "2013-03-26 07:24:53",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -542,6 +542,16 @@
"reqd": 0,
"search_index": 0
},
{
"doctype": "DocField",
"fieldname": "fiscal_year",
"fieldtype": "Select",
"in_filter": 0,
"label": "Fiscal Year",
"options": "link:Fiscal Year",
"print_hide": 1,
"reqd": 1
},
{
"allow_on_submit": 0,
"doctype": "DocField",
@ -610,13 +620,5 @@
{
"doctype": "DocPerm",
"role": "Manufacturing User"
},
{
"doctype": "DocPerm",
"role": "Manufacturing Manager"
},
{
"doctype": "DocPerm",
"role": "Material Manager"
}
]

View File

@ -230,6 +230,7 @@ class TestStockEntry(unittest.TestCase):
se.doc.purpose = "Sales Return"
se.doc.sales_invoice_no = si.doc.name
se.doc.posting_date = "2013-03-10"
se.doc.fiscal_year = "_Test Fiscal Year 2013"
se.doclist[1].item_code = "_Test Item Home Desktop 200"
se.doclist[1].qty = returned_qty
se.doclist[1].transfer_qty = returned_qty
@ -241,6 +242,7 @@ class TestStockEntry(unittest.TestCase):
se = webnotes.bean(copy=test_records[0])
se.doc.purpose = "Sales Return"
se.doc.posting_date = "2013-03-10"
se.doc.fiscal_year = "_Test Fiscal Year 2013"
se.doc.sales_invoice_no = si.doc.name
se.doclist[1].qty = returned_qty
se.doclist[1].transfer_qty = returned_qty
@ -300,6 +302,7 @@ class TestStockEntry(unittest.TestCase):
se.doc.purpose = "Sales Return"
se.doc.delivery_note_no = dn.doc.name
se.doc.posting_date = "2013-03-10"
se.doc.fiscal_year = "_Test Fiscal Year 2013"
se.doclist[1].qty = se.doclist[1].transfer_qty = returned_qty
se.insert()
@ -399,6 +402,7 @@ class TestStockEntry(unittest.TestCase):
se.doc.purpose = "Sales Return"
se.doc.delivery_note_no = dn.doc.name
se.doc.posting_date = "2013-03-10"
se.doc.fiscal_year = "_Test Fiscal Year 2013"
se.doclist[1].qty = se.doclist[1].transfer_qty = returned_qty
se.insert()
@ -449,6 +453,7 @@ class TestStockEntry(unittest.TestCase):
se.doc.purpose = "Purchase Return"
se.doc.purchase_receipt_no = pr.doc.name
se.doc.posting_date = "2013-03-01"
se.doc.fiscal_year = "_Test Fiscal Year 2013"
se.doclist[1].qty = se.doclist[1].transfer_qty = 5
se.doclist[1].s_warehouse = "_Test Warehouse"
se.insert()
@ -471,6 +476,7 @@ class TestStockEntry(unittest.TestCase):
se.doc.purpose = "Purchase Return"
se.doc.purchase_receipt_no = pr_docname
se.doc.posting_date = "2013-03-01"
se.doc.fiscal_year = "_Test Fiscal Year 2013"
se.doclist[1].qty = se.doclist[1].transfer_qty = 6
se.doclist[1].s_warehouse = "_Test Warehouse"
@ -490,7 +496,7 @@ class TestStockEntry(unittest.TestCase):
def test_make_return_jv_for_purchase_receipt(self):
se, pr_name = self.test_purchase_receipt_return()
self._test_purchase_return_jv(se)
se, pr_name = self._test_purchase_return_return_against_purchase_order()
self._test_purchase_return_jv(se)
@ -547,6 +553,7 @@ class TestStockEntry(unittest.TestCase):
se.doc.purpose = "Purchase Return"
se.doc.purchase_receipt_no = pr.doc.name
se.doc.posting_date = "2013-03-01"
se.doc.fiscal_year = "_Test Fiscal Year 2013"
se.doclist[1].qty = se.doclist[1].transfer_qty = 5
se.doclist[1].s_warehouse = "_Test Warehouse"
se.insert()

View File

@ -16,17 +16,13 @@
from __future__ import unicode_literals
import webnotes
from webnotes import _
from webnotes import _, msgprint
from webnotes.utils import cint, flt, getdate
sql = webnotes.conn.sql
msgprint = webnotes.msgprint
from accounts.utils import get_fiscal_year
from webnotes.model.controller import DocListController
class InvalidWarehouseCompany(Exception): pass
class DocType:
class DocType(DocListController):
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
@ -39,12 +35,14 @@ class DocType:
self.actual_amt_check()
self.check_stock_frozen_date()
self.scrub_posting_time()
self.doc.fiscal_year = get_fiscal_year(self.doc.posting_date)[0]
from accounts.utils import validate_fiscal_year
validate_fiscal_year(self.doc.posting_date, self.doc.fiscal_year, self.meta.get_label("posting_date"))
#check for item quantity available in stock
def actual_amt_check(self):
if self.doc.batch_no:
batch_bal = flt(sql("select sum(actual_qty) from `tabStock Ledger Entry` where warehouse = '%s' and item_code = '%s' and batch_no = '%s'"%(self.doc.warehouse,self.doc.item_code,self.doc.batch_no))[0][0])
batch_bal = flt(webnotes.conn.sql("select sum(actual_qty) from `tabStock Ledger Entry` where warehouse = '%s' and item_code = '%s' and batch_no = '%s'"%(self.doc.warehouse,self.doc.item_code,self.doc.batch_no))[0][0])
self.doc.fields.update({'batch_bal': batch_bal})
if (batch_bal + self.doc.actual_qty) < 0:
@ -77,11 +75,11 @@ class DocType:
if self.doc.fields.get(k)==None:
msgprint("Stock Ledger Entry: '%s' is mandatory" % k, raise_exception = 1)
elif k == 'warehouse':
if not sql("select name from tabWarehouse where name = '%s'" % self.doc.fields.get(k)):
if not webnotes.conn.sql("select name from tabWarehouse where name = '%s'" % self.doc.fields.get(k)):
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 = sql("""select name, has_batch_no, docstatus,
item_det = webnotes.conn.sql("""select name, has_batch_no, docstatus,
ifnull(is_stock_item, 'No') from tabItem where name=%s""",
self.doc.item_code)
@ -106,7 +104,7 @@ class DocType:
raise Exception
# check if batch belongs to item
if not sql("select name from `tabBatch` where item='%s' and name ='%s' and docstatus != 2" % (self.doc.item_code, self.doc.batch_no)):
if not webnotes.conn.sql("select name from `tabBatch` where item='%s' and name ='%s' and docstatus != 2" % (self.doc.item_code, self.doc.batch_no)):
msgprint("'%s' is not a valid Batch Number for Item '%s'" % (self.doc.batch_no, self.doc.item_code), raise_exception = 1)
# Nobody can do SL Entries where posting date is before freezing date except authorized person

View File

@ -101,22 +101,25 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
show_upload: function() {
var me = this;
var $wrapper = $(cur_frm.fields_dict.upload_html.wrapper).empty();
var upload_area = $('<div id="dit-upload-area"></div>').appendTo($wrapper);
// upload
wn.upload.make({
parent: $('#dit-upload-area'),
parent: $wrapper,
args: {
method: 'stock.doctype.stock_reconciliation.stock_reconciliation.upload'
},
sample_url: "e.g. http://example.com/somefile.csv",
callback: function(r) {
$wrapper.find(".dit-progress-area").toggle(false);
me.frm.set_value("reconciliation_json", JSON.stringify(r));
me.show_reconciliation_data();
me.frm.save();
}
});
// rename button
$wrapper.find('form input[type="submit"]')
.attr('value', 'Upload')
},
show_download_reconciliation_data: function() {

View File

@ -252,7 +252,8 @@ class DocType(StockController):
"voucher_no": self.doc.name,
"company": self.doc.company,
"is_cancelled": "No",
"voucher_detail_no": row.voucher_detail_no
"voucher_detail_no": row.voucher_detail_no,
"fiscal_year": self.doc.fiscal_year,
})
args.update(opts)
# create stock ledger entry

View File

@ -1,8 +1,8 @@
[
{
"creation": "2013-01-22 16:50:41",
"creation": "2013-03-26 06:51:17",
"docstatus": 0,
"modified": "2013-03-18 12:48:42",
"modified": "2013-03-26 08:32:03",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -30,7 +30,6 @@
"permlevel": 0
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
@ -41,7 +40,6 @@
"permlevel": 0,
"read": 1,
"report": 1,
"role": "Material Manager",
"submit": 1,
"write": 1
},
@ -81,6 +79,15 @@
"print_hide": 1,
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "fiscal_year",
"fieldtype": "Select",
"label": "Fiscal Year",
"options": "link:Fiscal Year",
"print_hide": 1,
"reqd": 1
},
{
"doctype": "DocField",
"fieldname": "company",
@ -145,6 +152,12 @@
"print_hide": 1
},
{
"doctype": "DocPerm"
"amend": 0,
"doctype": "DocPerm",
"role": "Material Manager"
},
{
"doctype": "DocPerm",
"role": "System Manager"
}
]

View File

@ -228,35 +228,40 @@ class TestStockReconciliation(unittest.TestCase):
"voucher_type": "Stock Entry", "voucher_no": "TEST",
"item_code": "_Test Item", "warehouse": "_Test Warehouse",
"posting_date": "2012-12-12", "posting_time": "01:00",
"actual_qty": 20, "incoming_rate": 1000, "company": "_Test Company"
"actual_qty": 20, "incoming_rate": 1000, "company": "_Test Company",
"fiscal_year": "_Test Fiscal Year 2012",
},
{
"doctype": "Stock Ledger Entry", "__islocal": 1,
"voucher_type": "Stock Entry", "voucher_no": "TEST",
"item_code": "_Test Item", "warehouse": "_Test Warehouse",
"posting_date": "2012-12-15", "posting_time": "02:00",
"actual_qty": 10, "incoming_rate": 700, "company": "_Test Company"
"actual_qty": 10, "incoming_rate": 700, "company": "_Test Company",
"fiscal_year": "_Test Fiscal Year 2012",
},
{
"doctype": "Stock Ledger Entry", "__islocal": 1,
"voucher_type": "Stock Entry", "voucher_no": "TEST",
"item_code": "_Test Item", "warehouse": "_Test Warehouse",
"posting_date": "2012-12-25", "posting_time": "03:00",
"actual_qty": -15, "company": "_Test Company"
"actual_qty": -15, "company": "_Test Company",
"fiscal_year": "_Test Fiscal Year 2012",
},
{
"doctype": "Stock Ledger Entry", "__islocal": 1,
"voucher_type": "Stock Entry", "voucher_no": "TEST",
"item_code": "_Test Item", "warehouse": "_Test Warehouse",
"posting_date": "2012-12-31", "posting_time": "08:00",
"actual_qty": -20, "company": "_Test Company"
"actual_qty": -20, "company": "_Test Company",
"fiscal_year": "_Test Fiscal Year 2012",
},
{
"doctype": "Stock Ledger Entry", "__islocal": 1,
"voucher_type": "Stock Entry", "voucher_no": "TEST",
"item_code": "_Test Item", "warehouse": "_Test Warehouse",
"posting_date": "2013-01-05", "posting_time": "07:00",
"actual_qty": 15, "incoming_rate": 1200, "company": "_Test Company"
"actual_qty": 15, "incoming_rate": 1200, "company": "_Test Company",
"fiscal_year": "_Test Fiscal Year 2013",
},
]

View File

@ -0,0 +1,47 @@
cur_frm.cscript.refresh = function(doc) {
wn.call({
method:"utilities.doctype.rename_tool.rename_tool.get_doctypes",
callback: function(r) {
cur_frm.set_df_property("select_doctype", "options", r.message);
cur_frm.cscript.setup_upload();
}
});
}
cur_frm.cscript.select_doctype = function() {
cur_frm.cscript.setup_upload();
}
cur_frm.cscript.setup_upload = function() {
var me = this;
var $wrapper = $(cur_frm.fields_dict.upload_html.wrapper).empty()
.html("<hr><div class='alert'>" +
wn._("Upload a .csv file with two columns: the old name and the new name. Max 500 rows.")
+ "</div>");
var $log = $(cur_frm.fields_dict.rename_log.wrapper).empty();
// upload
wn.upload.make({
parent: $wrapper,
args: {
method: 'utilities.doctype.rename_tool.rename_tool.upload',
select_doctype: cur_frm.doc.select_doctype
},
sample_url: "e.g. http://example.com/somefile.csv",
callback: function(r) {
$log.empty().html("<hr>");
$.each(r, function(i, v) {
$("<div>" + v + "</div>").appendTo($log);
});
}
});
// rename button
$wrapper.find('form input[type="submit"]')
.click(function() {
$log.html("Working...");
})
.addClass("btn-info")
.attr('value', 'Upload and Rename')
}

View File

@ -0,0 +1,49 @@
# For license information, please see license.txt
from __future__ import unicode_literals
import webnotes
from webnotes import _
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d, dl
@webnotes.whitelist()
def get_doctypes():
return webnotes.conn.sql_list("""select name from tabDocType
where ifnull(allow_rename,0)=1 and module!='Core' order by name""")
@webnotes.whitelist(allow_roles=["System Manager"])
def upload(select_doctype=None, rows=None):
from webnotes.utils.datautils import read_csv_content_from_uploaded_file
from webnotes.modules import scrub
from webnotes.model.rename_doc import rename_doc
if not select_doctype:
select_doctype = webnotes.form_dict.select_doctype
if not rows:
rows = read_csv_content_from_uploaded_file()
if not rows:
webnotes.msgprint(_("Please select a valid csv file with data."))
raise Exception
if len(rows) > 500:
webnotes.msgprint(_("Max 500 rows only."))
raise Exception
rename_log = []
for row in rows:
if len(row) > 2:
try:
if rename_doc(select_doctype, row[0], row[1]):
rename_log.append(_("Successful: ") + row[0] + " -> " + row[1])
webnotes.conn.commit()
else:
rename_log.append(_("Ignored: ") + row[0] + " -> " + row[1])
except Exception, e:
rename_log.append("<span style='color: RED'>" + \
_("Failed: ") + row[0] + " -> " + row[1] + "</span>")
rename_log.append("<span style='margin-left: 20px;'>" + repr(e) + "</span>")
return rename_log

View File

@ -0,0 +1,69 @@
[
{
"creation": "2012-12-03 10:25:59",
"docstatus": 0,
"modified": "2013-03-26 12:46:07",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"allow_attach": 0,
"allow_email": 1,
"allow_print": 1,
"doctype": "DocType",
"hide_heading": 0,
"hide_toolbar": 1,
"issingle": 1,
"max_attachments": 1,
"module": "Utilities",
"name": "__common__"
},
{
"doctype": "DocField",
"name": "__common__",
"parent": "Rename Tool",
"parentfield": "fields",
"parenttype": "DocType",
"permlevel": 0
},
{
"create": 1,
"doctype": "DocPerm",
"name": "__common__",
"parent": "Rename Tool",
"parentfield": "permissions",
"parenttype": "DocType",
"permlevel": 0,
"read": 1,
"report": 0,
"role": "System Manager",
"submit": 0,
"write": 1
},
{
"doctype": "DocType",
"name": "Rename Tool"
},
{
"description": "Type of document to rename.",
"doctype": "DocField",
"fieldname": "select_doctype",
"fieldtype": "Select",
"label": "Select DocType"
},
{
"doctype": "DocField",
"fieldname": "upload_html",
"fieldtype": "HTML",
"label": "Upload HTML"
},
{
"doctype": "DocField",
"fieldname": "rename_log",
"fieldtype": "HTML",
"label": "Rename Log"
},
{
"doctype": "DocPerm"
}
]

View File

@ -250,4 +250,5 @@ class TransactionBase(DocListController):
def validate_posting_time(self):
if not self.doc.posting_time:
self.doc.posting_time = now_datetime().strftime('%H:%M:%S')
self.doc.posting_time = now_datetime().strftime('%H:%M:%S')