diff --git a/.gitignore b/.gitignore index 95255be8b5c..29bb6241155 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ *.pyc *.comp.js .DS_Store -user_files +files patch.log lib conf.py diff --git a/css/all-app.css b/css/all-app.css index 8ee043f90d7..41feae8e40c 100644 --- a/css/all-app.css +++ b/css/all-app.css @@ -1728,7 +1728,6 @@ body { padding: 0px; font-size: 14px; color: #000; - background-color: #e2e2e2; } /* font settings */ @@ -1848,12 +1847,12 @@ div.comment { color: #444; } div#body_div { display: none; padding-right: 7px; - width: 900px; - margin: auto; - margin-top: 56px; + padding-top: 70px; + padding-bottom: 50px; } .content { + margin: auto; width: 900px; } @@ -1864,23 +1863,19 @@ div#body_div { transition: background 1s ease-in; } -footer { - width: 900px; - margin: auto; -} header .container { width: 900px; margin: auto; } @media (max-width: 1200px) { - div#body_div, header .container, .content, #opened-page-selector, footer { + header .container, .content { width: 900px; } } @media (min-width: 1200px) { - div#body_div, header .container, .content, #opened-page-selector, footer { + header .container, .content { width: 1100px; } } @@ -1931,7 +1926,6 @@ div.std-footer-item { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; - margin-bottom: 30px; overflow: hidden; } @@ -3581,7 +3575,6 @@ span, div, td, input, textarea, button, select { } body { - background: url(../images/redbeech.jpg) repeat; color: #616161; } diff --git a/css/all-web.css b/css/all-web.css index cf8fe990ed0..c3139d41662 100644 --- a/css/all-web.css +++ b/css/all-web.css @@ -1195,6 +1195,387 @@ button.btn.small, input[type="submit"].btn.small { margin-bottom: 0; } +/* + * lib/css/bootstrap/icons.css + */ +[class^="icon-"], [class*=" icon-"] { + display: inline-block; + width: 14px; + height: 14px; + line-height: 14px; + vertical-align: text-top; + background-image: url("../lib/images/icons/glyphicons-halflings.png"); + background-position: 14px 14px; + background-repeat: no-repeat; + *margin-right: .3em; +} +[class^="icon-"]:last-child, [class*=" icon-"]:last-child { + *margin-left: 0; +} +.icon-white { + background-image: url("../lib/images/icons/glyphicons-halflings-white.png"); +} +.icon-glass { + background-position: 0 0; +} +.icon-music { + background-position: -24px 0; +} +.icon-search { + background-position: -48px 0; +} +.icon-envelope { + background-position: -72px 0; +} +.icon-heart { + background-position: -96px 0; +} +.icon-star { + background-position: -120px 0; +} +.icon-star-empty { + background-position: -144px 0; +} +.icon-user { + background-position: -168px 0; +} +.icon-film { + background-position: -192px 0; +} +.icon-th-large { + background-position: -216px 0; +} +.icon-th { + background-position: -240px 0; +} +.icon-th-list { + background-position: -264px 0; +} +.icon-ok { + background-position: -288px 0; +} +.icon-remove { + background-position: -312px 0; +} +.icon-zoom-in { + background-position: -336px 0; +} +.icon-zoom-out { + background-position: -360px 0; +} +.icon-off { + background-position: -384px 0; +} +.icon-signal { + background-position: -408px 0; +} +.icon-cog { + background-position: -432px 0; +} +.icon-trash { + background-position: -456px 0; +} +.icon-home { + background-position: 0 -24px; +} +.icon-file { + background-position: -24px -24px; +} +.icon-time { + background-position: -48px -24px; +} +.icon-road { + background-position: -72px -24px; +} +.icon-download-alt { + background-position: -96px -24px; +} +.icon-download { + background-position: -120px -24px; +} +.icon-upload { + background-position: -144px -24px; +} +.icon-inbox { + background-position: -168px -24px; +} +.icon-play-circle { + background-position: -192px -24px; +} +.icon-repeat { + background-position: -216px -24px; +} +.icon-refresh { + background-position: -240px -24px; +} +.icon-list-alt { + background-position: -264px -24px; +} +.icon-lock { + background-position: -287px -24px; +} +.icon-flag { + background-position: -312px -24px; +} +.icon-headphones { + background-position: -336px -24px; +} +.icon-volume-off { + background-position: -360px -24px; +} +.icon-volume-down { + background-position: -384px -24px; +} +.icon-volume-up { + background-position: -408px -24px; +} +.icon-qrcode { + background-position: -432px -24px; +} +.icon-barcode { + background-position: -456px -24px; +} +.icon-tag { + background-position: 0 -48px; +} +.icon-tags { + background-position: -25px -48px; +} +.icon-book { + background-position: -48px -48px; +} +.icon-bookmark { + background-position: -72px -48px; +} +.icon-print { + background-position: -96px -48px; +} +.icon-camera { + background-position: -120px -48px; +} +.icon-font { + background-position: -144px -48px; +} +.icon-bold { + background-position: -167px -48px; +} +.icon-italic { + background-position: -192px -48px; +} +.icon-text-height { + background-position: -216px -48px; +} +.icon-text-width { + background-position: -240px -48px; +} +.icon-align-left { + background-position: -264px -48px; +} +.icon-align-center { + background-position: -288px -48px; +} +.icon-align-right { + background-position: -312px -48px; +} +.icon-align-justify { + background-position: -336px -48px; +} +.icon-list { + background-position: -360px -48px; +} +.icon-indent-left { + background-position: -384px -48px; +} +.icon-indent-right { + background-position: -408px -48px; +} +.icon-facetime-video { + background-position: -432px -48px; +} +.icon-picture { + background-position: -456px -48px; +} +.icon-pencil { + background-position: 0 -72px; +} +.icon-map-marker { + background-position: -24px -72px; +} +.icon-adjust { + background-position: -48px -72px; +} +.icon-tint { + background-position: -72px -72px; +} +.icon-edit { + background-position: -96px -72px; +} +.icon-share { + background-position: -120px -72px; +} +.icon-check { + background-position: -144px -72px; +} +.icon-move { + background-position: -168px -72px; +} +.icon-step-backward { + background-position: -192px -72px; +} +.icon-fast-backward { + background-position: -216px -72px; +} +.icon-backward { + background-position: -240px -72px; +} +.icon-play { + background-position: -264px -72px; +} +.icon-pause { + background-position: -288px -72px; +} +.icon-stop { + background-position: -312px -72px; +} +.icon-forward { + background-position: -336px -72px; +} +.icon-fast-forward { + background-position: -360px -72px; +} +.icon-step-forward { + background-position: -384px -72px; +} +.icon-eject { + background-position: -408px -72px; +} +.icon-chevron-left { + background-position: -432px -72px; +} +.icon-chevron-right { + background-position: -456px -72px; +} +.icon-plus-sign { + background-position: 0 -96px; +} +.icon-minus-sign { + background-position: -24px -96px; +} +.icon-remove-sign { + background-position: -48px -96px; +} +.icon-ok-sign { + background-position: -72px -96px; +} +.icon-question-sign { + background-position: -96px -96px; +} +.icon-info-sign { + background-position: -120px -96px; +} +.icon-screenshot { + background-position: -144px -96px; +} +.icon-remove-circle { + background-position: -168px -96px; +} +.icon-ok-circle { + background-position: -192px -96px; +} +.icon-ban-circle { + background-position: -216px -96px; +} +.icon-arrow-left { + background-position: -240px -96px; +} +.icon-arrow-right { + background-position: -264px -96px; +} +.icon-arrow-up { + background-position: -289px -96px; +} +.icon-arrow-down { + background-position: -312px -96px; +} +.icon-share-alt { + background-position: -336px -96px; +} +.icon-resize-full { + background-position: -360px -96px; +} +.icon-resize-small { + background-position: -384px -96px; +} +.icon-plus { + background-position: -408px -96px; +} +.icon-minus { + background-position: -433px -96px; +} +.icon-asterisk { + background-position: -456px -96px; +} +.icon-exclamation-sign { + background-position: 0 -120px; +} +.icon-gift { + background-position: -24px -120px; +} +.icon-leaf { + background-position: -48px -120px; +} +.icon-fire { + background-position: -72px -120px; +} +.icon-eye-open { + background-position: -96px -120px; +} +.icon-eye-close { + background-position: -120px -120px; +} +.icon-warning-sign { + background-position: -144px -120px; +} +.icon-plane { + background-position: -168px -120px; +} +.icon-calendar { + background-position: -192px -120px; +} +.icon-random { + background-position: -216px -120px; +} +.icon-comment { + background-position: -240px -120px; +} +.icon-magnet { + background-position: -264px -120px; +} +.icon-chevron-up { + background-position: -288px -120px; +} +.icon-chevron-down { + background-position: -313px -119px; +} +.icon-retweet { + background-position: -336px -120px; +} +.icon-shopping-cart { + background-position: -360px -120px; +} +.icon-folder-close { + background-position: -384px -120px; +} +.icon-folder-open { + background-position: -408px -120px; +} +.icon-resize-vertical { + background-position: -432px -119px; +} +.icon-resize-horizontal { + background-position: -456px -118px; +} + /* * lib/css/legacy/body.css */ @@ -1208,7 +1589,6 @@ body { padding: 0px; font-size: 14px; color: #000; - background-color: #e2e2e2; } /* font settings */ @@ -1328,12 +1708,12 @@ div.comment { color: #444; } div#body_div { display: none; padding-right: 7px; - width: 900px; - margin: auto; - margin-top: 56px; + padding-top: 70px; + padding-bottom: 50px; } .content { + margin: auto; width: 900px; } @@ -1344,23 +1724,19 @@ div#body_div { transition: background 1s ease-in; } -footer { - width: 900px; - margin: auto; -} header .container { width: 900px; margin: auto; } @media (max-width: 1200px) { - div#body_div, header .container, .content, #opened-page-selector, footer { + header .container, .content { width: 900px; } } @media (min-width: 1200px) { - div#body_div, header .container, .content, #opened-page-selector, footer { + header .container, .content { width: 1100px; } } @@ -1411,7 +1787,6 @@ div.std-footer-item { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; - margin-bottom: 30px; overflow: hidden; } @@ -1898,7 +2273,6 @@ span, div, td, input, textarea, button, select { } body { - background: url(../images/redbeech.jpg) repeat; color: #616161; } @@ -1952,12 +2326,13 @@ body { /* * erpnext/website/css/website.css */ -div#body_div, header .container, .content, #opened-page-selector, footer { +header .container, .content { width: 900px; } div#body_div { - margin-top: 90px; + padding-top: 90px; + min-height: 400px; } p, li { @@ -2016,19 +2391,23 @@ pre { background-color: #444; } + footer { - color: #777; + background-color: #eee; + box-shadow: inset 0 10px 10px rgba(0,0,0,0.3), inset 0 3px 3px rgba(0,0,0,0.3); + border-top: 1px solid #555; + padding-top: 10px; + text-align: center; } .web-footer { color: inherit; - text-align: center; - margin: 10px; + padding: 10px; line-height: 1.7; } .web-footer div, .web-footer a { - font-size: 14px; + font-size: 12px; } .web-footer-menu { @@ -2047,10 +2426,20 @@ footer { border-right: 1px solid #999; } +.web-footer-menu ul li:first-child { + padding-left: 0px; +} + .web-footer-menu ul li:last-child { border-right: 0px solid #777 !important; } +.web-footer-powered { + color: #888; + float: right; + margin-top: -12px; +} + /* slide view */ .next-slide { diff --git a/erpnext/accounts/doctype/gl_control/gl_control.py b/erpnext/accounts/doctype/gl_control/gl_control.py index 84fea75a909..2edd2dc2d33 100644 --- a/erpnext/accounts/doctype/gl_control/gl_control.py +++ b/erpnext/accounts/doctype/gl_control/gl_control.py @@ -198,10 +198,17 @@ class DocType: # ---------------- def save_entries(self, cancel, adv_adj, update_outstanding): for le in self.entries: - # cancel - if cancel or flt(le.debit) < 0 or flt(le.credit) < 0: + #toggle debit, credit if negative entry + if flt(le.debit) < 0 or flt(le.credit) < 0: tmp=le.debit le.debit, le.credit = abs(flt(le.credit)), abs(flt(tmp)) + + # toggled debit/credit in two separate condition because both should be executed at the + # time of cancellation when there is negative amount (tax discount) + if cancel: + tmp=le.debit + le.debit, le.credit = abs(flt(le.credit)), abs(flt(tmp)) + le_obj = get_obj(doc=le) # validate except on_cancel diff --git a/erpnext/accounts/doctype/multi_ledger_report/multi_ledger_report.py b/erpnext/accounts/doctype/multi_ledger_report/multi_ledger_report.py index 88a31f2226c..79ccfa9d2dc 100755 --- a/erpnext/accounts/doctype/multi_ledger_report/multi_ledger_report.py +++ b/erpnext/accounts/doctype/multi_ledger_report/multi_ledger_report.py @@ -49,14 +49,14 @@ class DocType: def add_header(self): title = 'Ledger Balances Between ' + getdate(self.doc.from_date).strftime('%d-%m-%Y') + ' and ' + getdate(self.doc.to_date).strftime('%d-%m-%Y') - return [[title], ['Account', 'Opening(Dr)', 'Opening (Cr)', 'Debit', 'Credit', 'Closing(Dr)', 'Closing(Cr)'], ['', '', '', '', '', '', '', 'Posting Date', 'Voucher Type', 'Voucher No', 'Debit', 'Credit', 'Remarks']] + return [[title], ['Account', 'Posting Date', 'Voucher Type', 'Voucher No', 'Debit', 'Credit', 'Remarks']] def get_account_subtree(self, acc): return sql(""" SELECT - CONCAT(REPEAT(' ', COUNT(parent.name) - (sub_tree.depth + 1)), node.name) as account, + CONCAT(REPEAT(' ', COUNT(parent.name) - (sub_tree.depth + 1)), node.name) as account, node.lft AS lft, node.rgt AS rgt, node.debit_or_credit as dr_or_cr, node.group_or_ledger as group_or_ledger, node.is_pl_account as is_pl_account FROM tabAccount AS node, @@ -78,7 +78,7 @@ class DocType: - def show_acc_summary(self, glc, acc_det): + def get_acc_summary(self, glc, acc_det): from_date_year = self.get_year(add_days(self.doc.from_date, -1)) to_date_year = self.get_year(self.doc.to_date) acc = acc_det['account'].strip() @@ -104,8 +104,8 @@ class DocType: if acc_det['dr_or_cr'] == 'Credit': opening, closing = -1*opening, -1*closing - return [acc_det['account'], flt(opening>0 and opening or 0), flt(opening<0 and -opening or 0), - debit, credit, flt(closing>0.01 and closing or 0), flt(closing<-0.01 and -closing or 0)] + return flt(opening>0 and opening or 0), flt(opening<0 and -opening or 0), \ + debit, credit, flt(closing>0.01 and closing or 0), flt(closing<-0.01 and -closing or 0) def show_gl_entries(self, acc): @@ -113,7 +113,7 @@ class DocType: gle = sql("select posting_date, voucher_type, voucher_no, debit, credit, remarks from `tabGL Entry` WHERE account = %s and posting_date >= %s AND posting_date <= %s and ifnull(is_opening, 'No') = 'No' and ifnull(is_cancelled, 'No') = 'No'", (acc, self.doc.from_date, self.doc.to_date), as_dict=1) entries, dr, cr = [], 0, 0 for d in gle: - entries.append(['', '', '', '', '', '', '', d['posting_date'], d['voucher_type'], d['voucher_no'], d['debit'], d['credit'], d['remarks']]) + entries.append(['', d['posting_date'], d['voucher_type'], d['voucher_no'], d['debit'], d['credit'], d['remarks']]) return entries @@ -133,13 +133,17 @@ class DocType: sub_tree = self.get_account_subtree(d.account) for acc_det in sub_tree: - acc_summary = self.show_acc_summary(glc, acc_det) - res.append(acc_summary) - - # Show gl entries if account is ledger - if acc_det['group_or_ledger'] == 'Ledger' and (acc_summary[3] or acc_summary[4]): - gle = self.show_gl_entries(acc_det['account'].strip()) - res += gle - + acc_summary = self.get_acc_summary(glc, acc_det) + if acc_summary[0] or acc_summary[1] or acc_summary[2] or acc_summary[3] or acc_summary[4] or acc_summary[5]: + res.append([acc_det['account']]) + # Show gl entries if account is ledger + if acc_det['group_or_ledger'] == 'Ledger' and (acc_summary[2] or acc_summary[3]): + gle = self.show_gl_entries(acc_det['account'].strip()) + res += gle + + # Totals + res.append(['', '', '', 'Total Debit/Credit', acc_summary[2], acc_summary[3]]) + res.append(['', '', '', 'Opening Balance', acc_summary[0], acc_summary[1]]) + res.append(['', '', '', 'Closing Balance', acc_summary[4], acc_summary[5]]) return res diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.txt b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.txt index 666cd1c02c7..18bd7898c48 100755 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.txt +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.txt @@ -5,7 +5,7 @@ { 'creation': '2012-04-13 11:56:17', 'docstatus': 0, - 'modified': '2012-04-23 12:08:52', + 'modified': '2012-04-27 11:21:21', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -186,20 +186,6 @@ 'trigger': u'Client' }, - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'amended_from', - 'fieldtype': u'Link', - 'label': u'Amended From', - 'no_copy': 1, - 'oldfieldname': u'amended_from', - 'oldfieldtype': u'Link', - 'options': u'Purchase Invoice', - 'permlevel': 1, - 'print_hide': 1 - }, - # DocField { 'colour': u'White:FFF', @@ -359,6 +345,20 @@ 'search_index': 1 }, + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'amended_from', + 'fieldtype': u'Link', + 'label': u'Amended From', + 'no_copy': 1, + 'oldfieldname': u'amended_from', + 'oldfieldtype': u'Link', + 'options': u'Purchase Invoice', + 'permlevel': 1, + 'print_hide': 1 + }, + # DocField { 'description': u'The date at which current entry is corrected in the system.', diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index 33dc481776d..096fec83107 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -60,22 +60,10 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { if (!cur_frm.cscript.is_onload) cur_frm.cscript.dynamic_label(doc, cdt, cdn); if(doc.docstatus == 1 && doc.status != 'Stopped'){ - var ch = getchildren('Purchase Order Item',doc.name,'po_details'); - var allow_billing = 0; var allow_receipt = 0; - cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); - - for(var i in ch){ - if(ch[i].qty > ch[i].received_qty) allow_receipt = 1; - if(ch[i].qty > ch[i].billed_qty) allow_billing = 1; - } - if(allow_receipt) - cur_frm.add_custom_button('Make Purchase Receipt', cur_frm.cscript['Make Purchase Receipt']); - - if(allow_billing) - cur_frm.add_custom_button('Make Invoice', cur_frm.cscript['Make Purchase Invoice']); - - if(allow_billing || allow_receipt) - cur_frm.add_custom_button('Stop', cur_frm.cscript['Stop Purchase Order']); + cur_frm.add_custom_button('Send SMS', cur_frm.cscript['Send SMS']); + if(doc.per_received < 100) cur_frm.add_custom_button('Make Purchase Receipt', cur_frm.cscript['Make Purchase Receipt']); + if(doc.per_billed < 100) cur_frm.add_custom_button('Make Invoice', cur_frm.cscript['Make Purchase Invoice']); + if(doc.per_billed < 100 || doc.per_received < 100) cur_frm.add_custom_button('Stop', cur_frm.cscript['Stop Purchase Order']); } if(doc.docstatus == 1 && doc.status == 'Stopped') diff --git a/erpnext/buying/doctype/purchase_request/purchase_request.js b/erpnext/buying/doctype/purchase_request/purchase_request.js index d20d50aeeaa..8e6654376a6 100644 --- a/erpnext/buying/doctype/purchase_request/purchase_request.js +++ b/erpnext/buying/doctype/purchase_request/purchase_request.js @@ -46,19 +46,10 @@ cur_frm.cscript.get_item_defaults = function(doc) { //======================= Refresh ===================================== cur_frm.cscript.refresh = function(doc, cdt, cdn) { - - // Unhide Fields in Next Steps - // --------------------------------- - cur_frm.clear_custom_buttons(); if(doc.docstatus == 1 && doc.status != 'Stopped'){ - var ch = getchildren('Purchase Request Item',doc.name,'indent_details'); - var is_closed = 1; - for(var i in ch){ - if(flt(ch[i].qty) > flt(ch[i].ordered_qty)) is_closed = 0; - } - if(!is_closed) { + if(doc.per_ordered < 100) { cur_frm.add_custom_button('Make Purchase Order', cur_frm.cscript['Make Purchase Order']) cur_frm.add_custom_button('Stop Purchase Request', cur_frm.cscript['Stop Purchase Request']) } diff --git a/erpnext/patches/april_2012/after_sync_cleanup.py b/erpnext/patches/april_2012/after_sync_cleanup.py index ab9e70e2ff2..33840a00e82 100644 --- a/erpnext/patches/april_2012/after_sync_cleanup.py +++ b/erpnext/patches/april_2012/after_sync_cleanup.py @@ -1,5 +1,5 @@ def execute(): import webnotes from webnotes.model import delete_doc - + webnotes.conn.sql("update `tabDocType` set module = 'Utilities' where name in ('Question', 'Answer')") delete_doc('Module Def', 'Knowledge Base') diff --git a/erpnext/patches/april_2012/change_cacheitem_schema.py b/erpnext/patches/april_2012/change_cacheitem_schema.py index ab127e33963..dc3c2536895 100644 --- a/erpnext/patches/april_2012/change_cacheitem_schema.py +++ b/erpnext/patches/april_2012/change_cacheitem_schema.py @@ -1,3 +1,5 @@ def execute(): import webnotes + webnotes.conn.commit() webnotes.conn.sql("alter table __CacheItem modify `value` longtext") + webnotes.conn.begin() diff --git a/erpnext/patches/april_2012/remove_default_from_rv_detail.py b/erpnext/patches/april_2012/remove_default_from_rv_detail.py new file mode 100644 index 00000000000..cf81f6d2a78 --- /dev/null +++ b/erpnext/patches/april_2012/remove_default_from_rv_detail.py @@ -0,0 +1,3 @@ +def execute(): + import webnotes + webnotes.conn.sql("update `tabDocField` set `default` = '' where fieldname = 'cost_center' and parent = 'RV Detail' and `default` = 'Purchase - TC'") diff --git a/erpnext/patches/april_2012/serial_no_fixes.py b/erpnext/patches/april_2012/serial_no_fixes.py new file mode 100644 index 00000000000..b4fcf759bd7 --- /dev/null +++ b/erpnext/patches/april_2012/serial_no_fixes.py @@ -0,0 +1,6 @@ +def execute(): + import webnotes + from webnotes.modules.module_manager import reload_doc + reload_doc('stock', 'doctype', 'serial_no') + + webnotes.conn.sql("update `tabSerial No` set sle_exists = 1") diff --git a/erpnext/patches/april_2012/update_appraisal_permission.py b/erpnext/patches/april_2012/update_appraisal_permission.py new file mode 100644 index 00000000000..bd4578f5e45 --- /dev/null +++ b/erpnext/patches/april_2012/update_appraisal_permission.py @@ -0,0 +1,14 @@ +def execute(): + import webnotes + from webnotes.model.doc import addchild + from webnotes.model.code import get_obj + + webnotes.conn.sql("delete from `tabDocPerm` where role = 'All' and permlevel = 0 and parent in ('Appraisal', 'Ticket', 'Project')") + + appr = get_obj('DocType', 'Appraisal', with_children=1) + ch = addchild(appr.doc, 'permissions', 'DocPerm', 0) + ch.permlevel = 0 + ch.role = 'Employee' + ch.read = 1 + ch.write = 1 + ch.save() diff --git a/erpnext/patches/april_2012/update_permlevel_in_address.py b/erpnext/patches/april_2012/update_permlevel_in_address.py new file mode 100644 index 00000000000..f8deb2c4c3a --- /dev/null +++ b/erpnext/patches/april_2012/update_permlevel_in_address.py @@ -0,0 +1,3 @@ +def execute(): + import webnotes + webnotes.conn.sql("update `tabDocPerm` set permlevel = 0 where parent = 'Address'") diff --git a/erpnext/patches/april_2012/update_role_in_address.py b/erpnext/patches/april_2012/update_role_in_address.py new file mode 100644 index 00000000000..6917da422be --- /dev/null +++ b/erpnext/patches/april_2012/update_role_in_address.py @@ -0,0 +1,21 @@ +def execute(): + import webnotes + from webnotes.model.doc import addchild + from webnotes.model.code import get_obj + + webnotes.conn.sql("delete from `tabDocPerm` where role = 'All' and parent = 'Address'") + + role1 = ['Sales User', 'Purchase User', 'Accounts User', 'Maintenance User'] + role2 = ['Sales Manager', 'Sales Master Manager', 'Purchase Manager', 'Purchase Master Manager', 'Accounts Manager', 'Maintenance Manager'] + + addr = get_obj('DocType', 'Address', with_children=1) + for d in role1+role2: + ch = addchild(addr.doc, 'permissions', 'DocPerm', 0) + ch.role = d + ch.read = 1 + ch.write = 1 + ch.create = 1 + if d in role2: + ch.cancel = 1 + + ch.save() diff --git a/erpnext/patches/patch_list.py b/erpnext/patches/patch_list.py index 7d8a0951bb7..e0f9ea33a7c 100644 --- a/erpnext/patches/patch_list.py +++ b/erpnext/patches/patch_list.py @@ -282,4 +282,30 @@ patch_list = [ 'patch_file': 'change_cacheitem_schema', 'description': 'Modified datatype of `value` column from text to longtext' }, + { + 'patch_module': 'patches.april_2012', + 'patch_file': 'remove_default_from_rv_detail', + 'description': '' + }, + { + 'patch_module': 'patches.april_2012', + 'patch_file': 'update_role_in_address', + 'description': 'updated roles in address' + }, + { + 'patch_module': 'patches.april_2012', + 'patch_file': 'update_permlevel_in_address', + 'description': 'updated permlevel in address' + }, + { + 'patch_module': 'patches.april_2012', + 'patch_file': 'update_appraisal_permission', + 'description': 'updated permission in appraisal' + }, + { + 'patch_module': 'patches.april_2012', + 'patch_file': 'serial_no_fixes', + 'description': 'fixes for sle creation while import' + }, + ] diff --git a/erpnext/setup/doctype/notification_control/notification_control.js b/erpnext/setup/doctype/notification_control/notification_control.js index 32919b6f9cd..551269789e6 100644 --- a/erpnext/setup/doctype/notification_control/notification_control.js +++ b/erpnext/setup/doctype/notification_control/notification_control.js @@ -14,19 +14,19 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -cur_frm.cscript.select_transaction = function(doc, dt, dn) { +cur_frm.cscript.select_transaction = function(doc, cdt, cdn) { if(doc.select_transaction) { var callback = function(r,rt) { - var doc = locals[dt][dn]; + var doc = locals[cdt][cdn]; doc.custom_message = r.message; refresh_field('custom_message'); } - $c_obj('Notification Control','get_message',doc.select_transaction, callback) + $c_obj(make_doclist(cdt, cdn),'get_message',doc.select_transaction, callback) } } cur_frm.cscript.notify = function(doc, args) { - $c_obj('Notification Control', 'get_formatted_message', { + $c_obj(make_doclist(doc.doctype, doc.name), 'get_formatted_message', { type: args['type'], doctype: args['doctype'], contact_name: args['contact_name'] || doc.contact_display diff --git a/erpnext/setup/doctype/notification_control/notification_control.py b/erpnext/setup/doctype/notification_control/notification_control.py index 650486ece7b..2a21e80615d 100644 --- a/erpnext/setup/doctype/notification_control/notification_control.py +++ b/erpnext/setup/doctype/notification_control/notification_control.py @@ -39,7 +39,7 @@ class DocType: # set custom text # --------------- - def set_message(self, arg=''): + def set_message(self, arg = ''): fn = self.doc.select_transaction.lower().replace(' ', '_') + '_message' webnotes.conn.set(self.doc, fn, self.doc.custom_message) msgprint("Custom Message for %s updated!" % self.doc.select_transaction) diff --git a/erpnext/startup/startup.css b/erpnext/startup/startup.css index 47f188be656..490b2f4ee95 100644 --- a/erpnext/startup/startup.css +++ b/erpnext/startup/startup.css @@ -13,7 +13,6 @@ span, div, td, input, textarea, button, select { } body { - background: url(../images/redbeech.jpg) repeat; color: #616161; } diff --git a/erpnext/startup/startup.js b/erpnext/startup/startup.js index c96a6a8a1b9..23a02cf1cb5 100644 --- a/erpnext/startup/startup.js +++ b/erpnext/startup/startup.js @@ -188,7 +188,7 @@ erpnext.startup.set_periodic_updates = function() { } erpnext.set_user_background = function(src) { - set_style(repl('body { background: url("files/%(src)s") repeat;}', {src:src})) + set_style(repl('#body_div { background: url("files/%(src)s") repeat;}', {src:src})) } // start diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py index a6fc1c4386a..f645e8fa42d 100644 --- a/erpnext/stock/doctype/bin/bin.py +++ b/erpnext/stock/doctype/bin/bin.py @@ -44,6 +44,7 @@ class DocType: def update_stock(self, actual_qty=0, reserved_qty=0, ordered_qty=0, indented_qty=0, planned_qty=0, dt=None, sle_id='', posting_time='', serial_no = '', is_cancelled = 'No',doc_type='',doc_name='',is_amended='No'): if not dt: dt = nowdate() + # update the stock values (for current quantities) self.doc.actual_qty = flt(self.doc.actual_qty) + flt(actual_qty) self.doc.ordered_qty = flt(self.doc.ordered_qty) + flt(ordered_qty) @@ -295,7 +296,7 @@ class DocType: order by timestamp(posting_date, posting_time) asc, name asc""", \ (self.doc.item_code, self.doc.warehouse, \ prev_sle.get('posting_date','1900-01-01'), prev_sle.get('posting_time', '12:00')), as_dict = 1) - for sle in sll: + for sle in sll: # block if stock level goes negative on any date if val_method != 'Moving Average' or flt(allow_negative_stock) == 0: self.validate_negative_stock(cqty, sle) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index 8761881b67a..e32439ce3b5 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -63,13 +63,8 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { if(doc.docstatus == 1){ - var ch = getchildren('Purchase Receipt Item',doc.name,'purchase_receipt_details'); - allow_billing = 0; - for(var i in ch){ - if(ch[i].qty > ch[i].billed_qty) allow_billing = 1; - } - cur_frm.add_custom_button('Make Purchase Invoice', cur_frm.cscript['Make Purchase Invoice']); - cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); + if (doc.per_billed < 100) cur_frm.add_custom_button('Make Purchase Invoice', cur_frm.cscript['Make Purchase Invoice']); + cur_frm.add_custom_button('Send SMS', cur_frm.cscript['Send SMS']); } } diff --git a/erpnext/stock/doctype/sales_bom/sales_bom.py b/erpnext/stock/doctype/sales_bom/sales_bom.py index ae3378e0ba9..f2921646dd5 100644 --- a/erpnext/stock/doctype/sales_bom/sales_bom.py +++ b/erpnext/stock/doctype/sales_bom/sales_bom.py @@ -67,7 +67,7 @@ class DocType: msgprint("Sales Bom Item " + d.item_code +" cannot be child item.") raise Exception # Check if is_main_item is modified once saved - if not self.doc.fields.get('__islocal') and d.is_main_item == "Yes" and cstr(d.item_code) != cstr(self.doc.name)[:-3] : + if not self.doc.fields.get('__islocal') and d.is_main_item == "Yes" and cstr(d.item_code) != cstr(self.doc.new_item_code)[:-3] : msgprint("Modifying the main item is not allowed.") raise Exception if len(is_main_item) > 1: @@ -165,19 +165,18 @@ class DocType: return # get all Sales BOM that have the first item - sbl = sql("select distinct parent from `tabSales BOM Item` where item_code=%s", il[0].item_code) + sbl = sql("select distinct parent from `tabSales BOM Item` where item_code=%s and parent != %s and docstatus != 2", (il[0].item_code, self.doc.name)) # check all siblings sub_items = [[d.item_code, flt(d.qty)] for d in il] for s in sbl: - if not cstr(s[0]) == cstr(self.doc.name) : - t = sql("select item_code, qty from `tabSales BOM Item` where parent=%s", s[0]) - t = [[d[0], flt(d[1])] for d in t] + t = sql("select item_code, qty from `tabSales BOM Item` where parent=%s and docstatus != 2", s[0]) + t = [[d[0], flt(d[1])] for d in t] - if self.has_same_items(sub_items, t): - msgprint("%s has the same Sales BOM details" % s[0]) - raise Exception + if self.has_same_items(sub_items, t): + msgprint("%s has the same Sales BOM details" % s[0]) + raise Exception if finder: msgprint("There is no Sales BOM present with the following Combination.") diff --git a/erpnext/stock/doctype/sales_bom/sales_bom.txt b/erpnext/stock/doctype/sales_bom/sales_bom.txt index 476a3194b1c..dfc2a6547db 100644 --- a/erpnext/stock/doctype/sales_bom/sales_bom.txt +++ b/erpnext/stock/doctype/sales_bom/sales_bom.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-04-23 16:00:21', + 'creation': '2012-04-26 13:04:56', 'docstatus': 0, - 'modified': '2012-04-24 15:07:42', + 'modified': '2012-04-27 11:00:18', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -15,7 +15,6 @@ '_last_update': u'1322549701', 'allow_trash': 1, 'colour': u'White:FFF', - 'default_print_format': u'Standard', 'doctype': 'DocType', 'document_type': u'Master', 'is_submittable': 1, @@ -124,6 +123,24 @@ 'write': 0 }, + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'basic_section', + 'fieldtype': u'Section Break', + 'label': u'Basic Section', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'col1', + 'fieldtype': u'Column Break', + 'permlevel': 0, + 'width': u'50%' + }, + # DocField { 'doctype': u'DocField', @@ -173,6 +190,15 @@ 'width': u'300px' }, + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'col2', + 'fieldtype': u'Column Break', + 'permlevel': 0, + 'width': u'50%' + }, + # DocField { 'doctype': u'DocField', @@ -186,6 +212,18 @@ 'reqd': 1 }, + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'stock_uom', + 'fieldtype': u'Link', + 'label': u'Stock UOM', + 'oldfieldname': u'stock_uom', + 'oldfieldtype': u'Link', + 'options': u'UOM', + 'permlevel': 0 + }, + # DocField { 'colour': u'White:FFF', @@ -214,42 +252,6 @@ 'trigger': u'Client' }, - # DocField - { - 'colour': u'White:FFF', - 'doctype': u'DocField', - 'fieldname': u'find_sales_bom', - 'fieldtype': u'Button', - 'label': u'Find Sales BOM', - 'oldfieldtype': u'Button', - 'permlevel': 0, - 'trigger': u'Client' - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'sales_bom_items', - 'fieldtype': u'Table', - 'label': u'Sales BOM Items', - 'oldfieldname': u'sales_bom_items', - 'oldfieldtype': u'Table', - 'options': u'Sales BOM Item', - 'permlevel': 0 - }, - - # DocField - { - 'doctype': u'DocField', - 'fieldname': u'stock_uom', - 'fieldtype': u'Link', - 'label': u'Stock UOM', - 'oldfieldname': u'stock_uom', - 'oldfieldtype': u'Link', - 'options': u'UOM', - 'permlevel': 0 - }, - # DocField { 'depends_on': u'eval:doc.amended_from', @@ -270,11 +272,44 @@ 'fieldtype': u'Link', 'label': u'Amended From', 'no_copy': 1, - 'options': u'Sales Invoice', + 'options': u'Sales BOM', 'permlevel': 1, 'print_hide': 1 }, + # DocField + { + 'colour': u'White:FFF', + 'doctype': u'DocField', + 'fieldname': u'find_sales_bom', + 'fieldtype': u'Button', + 'label': u'Find Sales BOM', + 'oldfieldtype': u'Button', + 'permlevel': 0, + 'trigger': u'Client' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'item_section', + 'fieldtype': u'Section Break', + 'label': u'Items', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'sales_bom_items', + 'fieldtype': u'Table', + 'label': u'Sales BOM Items', + 'oldfieldname': u'sales_bom_items', + 'oldfieldtype': u'Table', + 'options': u'Sales BOM Item', + 'permlevel': 0 + }, + # DocField { 'doctype': u'DocField', diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 2384171f6a9..88f1bf21a6b 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -71,10 +71,13 @@ class DocType(TransactionBase): self.validate_warehouse() self.validate_item() + 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): + self.make_stock_ledger_entry(1) + webnotes.conn.set(self.doc, 'sle_exists', 1) + - # ------------------------ - # make stock ledger entry - # ------------------------ def make_stock_ledger_entry(self, qty): from webnotes.model.code import get_obj values = [{ @@ -91,21 +94,13 @@ class DocType(TransactionBase): 'incoming_rate' : self.doc.purchase_rate, 'company' : self.doc.company, 'fiscal_year' : self.doc.fiscal_year, - 'is_cancelled' : 'No', # is_cancelled is always 'No' because while deleted it can not find creation entry if it not created directly, voucher no != serial no. + 'is_cancelled' : 'No', # is_cancelled is always 'No' because while deleted it can not find creation entry if it not created directly, voucher no != serial no 'batch_no' : '', 'serial_no' : self.doc.name }] get_obj('Stock Ledger', 'Stock Ledger').update_stock(values) - # ---------- - # on update - # ---------- - def on_update(self): - if self.doc.localname and self.doc.warehouse and self.doc.status == 'In Store' and not 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) - - # --------- # on trash # --------- diff --git a/erpnext/stock/doctype/serial_no/serial_no.txt b/erpnext/stock/doctype/serial_no/serial_no.txt index aa0ea667c81..8e32243307b 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.txt +++ b/erpnext/stock/doctype/serial_no/serial_no.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-03-27 14:36:37', + 'creation': '2012-04-23 16:00:23', 'docstatus': 0, - 'modified': '2012-03-27 14:36:37', + 'modified': '2012-04-26 13:01:57', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -13,6 +13,7 @@ # These values are common for all DocType { '_last_update': u'1325570647', + 'allow_attach': 1, 'allow_trash': 1, 'autoname': u'field:serial_no', 'colour': u'White:FFF', @@ -27,7 +28,7 @@ 'show_in_menu': 0, 'subject': u'Item Code: %(item_code)s, Warehouse: %(warehouse)s', 'tag_fields': u'status', - 'version': 191 + 'version': 1 }, # These values are common for all DocField @@ -55,6 +56,54 @@ 'name': u'Serial No' }, + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 1, + 'role': u'Material Manager', + 'submit': 0, + 'write': 0 + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'Material Manager', + 'submit': 0, + 'write': 0 + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 1, + 'role': u'Material User', + 'submit': 0, + 'write': 0 + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'Material User', + 'submit': 0, + 'write': 0 + }, + # DocPerm { 'cancel': 1, @@ -89,54 +138,6 @@ 'role': u'Sales Master Manager' }, - # DocPerm - { - 'amend': 0, - 'cancel': 0, - 'create': 0, - 'doctype': u'DocPerm', - 'permlevel': 1, - 'role': u'Material Manager', - 'submit': 0, - 'write': 0 - }, - - # DocPerm - { - 'amend': 0, - 'cancel': 0, - 'create': 0, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Material Manager', - 'submit': 0, - 'write': 0 - }, - - # DocPerm - { - 'amend': 0, - 'cancel': 0, - 'create': 0, - 'doctype': u'DocPerm', - 'permlevel': 1, - 'role': u'Material User', - 'submit': 0, - 'write': 0 - }, - - # DocPerm - { - 'amend': 0, - 'cancel': 0, - 'create': 0, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Material User', - 'submit': 0, - 'write': 0 - }, - # DocField { 'doctype': u'DocField', @@ -700,5 +701,30 @@ 'oldfieldname': u'trash_reason', 'oldfieldtype': u'Small Text', 'permlevel': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'file_list', + 'fieldtype': u'Text', + 'hidden': 1, + 'label': u'File List', + 'no_copy': 1, + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'sle_exists', + 'fieldtype': u'Check', + 'hidden': 1, + 'label': u'SLE Exists', + 'no_copy': 1, + 'permlevel': 1, + 'print_hide': 1, + 'report_hide': 1 } ] \ No newline at end of file diff --git a/erpnext/stock/doctype/stock_ledger/stock_ledger.py b/erpnext/stock/doctype/stock_ledger/stock_ledger.py index 577d2ef6e90..1d3aabe57fd 100644 --- a/erpnext/stock/doctype/stock_ledger/stock_ledger.py +++ b/erpnext/stock/doctype/stock_ledger/stock_ledger.py @@ -128,6 +128,7 @@ class DocType: s.modified = nowdate() s.modified_by = session['user'] s.serial_no = serial_no + s.sle_exists = 1 s.fiscal_year = obj.doc.fiscal_year s.company = obj.doc.company s.save(new_rec) @@ -211,7 +212,7 @@ class DocType: import datetime for d in getlist(obj.doclist, fname): if d.serial_no: - serial_nos = self.get_sr_no_list(d.serial_no, d.qty) + serial_nos = self.get_sr_no_list(d.serial_no) for a in serial_nos: serial_no = a.strip() if is_incoming: diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index bb23226ee8c..cf3bd2fa392 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -35,11 +35,14 @@ class DocType: 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]) - + self.doc.fields.update({'batch_bal': batch_bal}) + if (batch_bal + self.doc.actual_qty) < 0: msgprint("""Not enough quantity (requested: %(actual_qty)s, current: %(batch_bal)s in Batch %(batch_no)s for Item %(item_code)s at Warehouse%(warehouse)s - as on %(posting_date)s %(posting_time)s""" % self.doc.fields.update({'batch_bal': batch_bal}), raise_exception = 1) + as on %(posting_date)s %(posting_time)s""" % self.doc.fields, raise_exception = 1) + + self.doc.fields.pop('batch_bal') # mandatory @@ -89,9 +92,17 @@ class DocType: if getdate(self.doc.posting_date) <= getdate(stock_frozen_upto) and not stock_auth_role in webnotes.user.get_roles(): msgprint("You are not authorized to do / modify back dated stock entries before %s" % getdate(stock_frozen_upto).strftime('%d-%m-%Y'), raise_exception=1) + def validate_posting_time(self): + """ Validate posting time format""" + if self.doc.posting_time and len(cstr(self.doc.posting_time)) == 8 and cstr(self.doc.posting_time)[-2:] != '00': + msgprint("Wrong format of posting time, can not complete the transaction. If you think \ + you entered posting time correctly, please contact ERPNext support team.") + raise Exception + def validate(self): self.validate_mandatory() + self.validate_posting_time() self.validate_item() self.actual_amt_check() self.check_stock_frozen_date() diff --git a/erpnext/stock/search_criteria/stock_report/stock_report.js b/erpnext/stock/search_criteria/stock_report/stock_report.js index 5451eb10e9b..d08d1e75e7e 100644 --- a/erpnext/stock/search_criteria/stock_report/stock_report.js +++ b/erpnext/stock/search_criteria/stock_report/stock_report.js @@ -19,7 +19,7 @@ report.customize_filters = function() { this.mytabs.items['Select Columns'].hide() this.mytabs.items['More Filters'].hide() this.hide_all_filters(); - this.add_filter({fieldname:'based_on', label:'Based On', fieldtype:'Select', options:'Warehouse'+NEWLINE+'Item Code',report_default:'Warehouse',ignore : 1,parent:'Stock Ledger Entry'}); + this.add_filter({fieldname:'based_on', label:'Based On', fieldtype:'Select', options:'Warehouse'+NEWLINE+'Item Code',ignore : 1,parent:'Stock Ledger Entry'}); this.filter_fields_dict['Stock Ledger Entry'+FILTER_SEP +'To Posting Date'].df.filter_hide = 0; this.filter_fields_dict['Stock Ledger Entry'+FILTER_SEP +'Item Code'].df.filter_hide = 0; this.filter_fields_dict['Stock Ledger Entry'+FILTER_SEP +'Warehouse'].df.filter_hide = 0; @@ -57,8 +57,8 @@ report.get_query = function(){ ware_type_cond = repl(' AND `tabWarehouse`.warehouse_type IN (%(war)s)', {war: war.substr(0,war.length-1)}) } - if(based_on.length == 1){ - if(based_on == 'Item Code'){ + if(based_on.length == 1 && based_on[0]){ + if(based_on[0] == 'Item Code'){ cols = '`tabItem`.name AS "Item Code", `tabItem`.item_name AS "Item Name", `tabItem`.description AS "Description", `tabItem`.stock_uom AS "Stock UOM"'; cond = '(IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.is_stock_item = "Yes"'; if(item_code) cond += repl(' AND `tabItem`.name = %(item)s', {item:'"'+item_code+'"'}); @@ -66,7 +66,7 @@ report.get_query = function(){ tables = '`tabItem`'; group_by = '`tabStock Ledger Entry`.item_code'; } - else if(based_on == 'Warehouse'){ + else if(based_on[0] == 'Warehouse'){ cols = '`tabWarehouse`.name AS "Warehouse", `tabWarehouse`.warehouse_type AS "Warehouse Type"'; cond = '`tabWarehouse`.docstatus < 2' if(warehouse) cond += repl(' AND `tabWarehouse`.name = %(warehouse)s', {warehouse:'"'+warehouse+'"'}); @@ -74,8 +74,7 @@ report.get_query = function(){ tables = '`tabWarehouse`'; group_by = '`tabStock Ledger Entry`.warehouse'; } - } - else if(based_on.length == 2){ + } else { cols = '`tabItem`.name AS "Item Code", `tabItem`.item_name AS "Item Name", `tabItem`.description AS "Description", `tabItem`.stock_uom AS "Stock UOM", `tabWarehouse`.name AS "Warehouse", `tabWarehouse`.warehouse_type AS "Warehouse Type"'; cond = '(IFNULL(`tabItem`.`end_of_life`,"") = "" OR `tabItem`.`end_of_life` = "0000-00-00" OR `tabItem`.`end_of_life` > NOW()) AND `tabItem`.is_stock_item = "Yes" AND `tabWarehouse`.docstatus < 2'; if(item_code) cond += repl(" AND `tabItem`.name = %(item)s", {item:"'"+item_code+"'"}); @@ -87,4 +86,4 @@ report.get_query = function(){ q = repl("SELECT %(cols)s FROM %(tables)s, `tabStock Ledger Entry` WHERE %(cond)s %(date_cond)s GROUP BY %(group_by)s", {cols:cols, tables:tables, cond:cond, date_cond:date_cond, group_by:group_by}); return q; -} \ No newline at end of file +} diff --git a/erpnext/stock/search_criteria/stock_report/stock_report.py b/erpnext/stock/search_criteria/stock_report/stock_report.py index 84866e93ee8..b87f684d24a 100644 --- a/erpnext/stock/search_criteria/stock_report/stock_report.py +++ b/erpnext/stock/search_criteria/stock_report/stock_report.py @@ -14,19 +14,16 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -if not filter_values.get('based_on'): - msgprint("Please Select Based On") - raise Exception cols, columns = [], [] # Add columns # ------------ based_on = filter_values.get('based_on').split(NEWLINE) -if len(based_on) == 1: +if len(based_on) == 1 and based_on[0]: if based_on[0] == 'Item Code': cols = ["Item Code", "Item Name", "Description", "Stock UOM"] elif based_on[0] == 'Warehouse': cols = ["Warehouse", "Warehouse Type"] -elif len(based_on) == 2: +else: cols = ["Item Code", "Item Name", "Description", "Stock UOM", "Warehouse", "Warehouse Type"] for d in cols: @@ -65,7 +62,7 @@ out=[] cl_bal,tot_stock = 0,0 for r in res: - if len(based_on) == 1: + if len(based_on) == 1 and based_on[0]: if based_on[0] == 'Item Code': closing_balance, stock_value = get_values(msgprint, flt, posting_date, item_code = r[col_idx['Item Code']]) elif based_on[0] == 'Warehouse': closing_balance, stock_value = get_values(msgprint, flt, posting_date, warehouse = r[col_idx['Warehouse']]) r.append(closing_balance) diff --git a/erpnext/website/css/website.css b/erpnext/website/css/website.css index ad8702ab474..fa27d4a9f8a 100644 --- a/erpnext/website/css/website.css +++ b/erpnext/website/css/website.css @@ -1,9 +1,10 @@ -div#body_div, header .container, .content, #opened-page-selector, footer { +header .container, .content { width: 900px; } div#body_div { - margin-top: 90px; + padding-top: 90px; + min-height: 400px; } p, li { @@ -62,19 +63,23 @@ pre { background-color: #444; } + footer { - color: #777; + background-color: #eee; + box-shadow: inset 0 10px 10px rgba(0,0,0,0.3), inset 0 3px 3px rgba(0,0,0,0.3); + border-top: 1px solid #555; + padding-top: 10px; + text-align: center; } .web-footer { color: inherit; - text-align: center; - margin: 10px; + padding: 10px; line-height: 1.7; } .web-footer div, .web-footer a { - font-size: 14px; + font-size: 12px; } .web-footer-menu { @@ -93,10 +98,20 @@ footer { border-right: 1px solid #999; } +.web-footer-menu ul li:first-child { + padding-left: 0px; +} + .web-footer-menu ul li:last-child { border-right: 0px solid #777 !important; } +.web-footer-powered { + color: #888; + float: right; + margin-top: -12px; +} + /* slide view */ .next-slide { diff --git a/erpnext/website/doctype/blog/blog.py b/erpnext/website/doctype/blog/blog.py index 1f1b98b4102..c78a9cc3b90 100644 --- a/erpnext/website/doctype/blog/blog.py +++ b/erpnext/website/doctype/blog/blog.py @@ -32,9 +32,11 @@ class DocType(): self.doc.name = website.utils.page_name(self.doc.title) def validate(self): - """write/update 'Page' with the blog""" + """write/update 'Page' with the blog""" + if self.doc.page_name: + webnotes.conn.sql("""delete from tabPage where name=%s""", self.doc.page_name) + p = website.utils.add_page(self.doc.title) - self.doc.name = p.name from jinja2 import Template import markdown2 @@ -54,11 +56,11 @@ class DocType(): p.save() website.utils.add_guest_access_to_page(p.name) + self.doc.page_name = p.name # cleanup for f in ['content_html', 'full_name', 'updated']: if f in self.doc.fields: - del self.doc.fields[f] - + del self.doc.fields[f] \ No newline at end of file diff --git a/erpnext/website/doctype/blog/blog.txt b/erpnext/website/doctype/blog/blog.txt index f9ff6fd47f2..ad44d13d964 100644 --- a/erpnext/website/doctype/blog/blog.txt +++ b/erpnext/website/doctype/blog/blog.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-03-27 14:36:47', + 'creation': '2012-04-02 16:02:43', 'docstatus': 0, - 'modified': '2012-03-27 14:36:47', + 'modified': '2012-04-26 16:58:27', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -21,7 +21,7 @@ 'name': '__common__', 'section_style': u'Simple', 'show_in_menu': 0, - 'version': 3 + 'version': 5 }, # These values are common for all DocField @@ -35,15 +35,12 @@ # These values are common for all DocPerm { - 'create': 1, 'doctype': u'DocPerm', 'name': '__common__', 'parent': u'Blog', 'parentfield': u'permissions', 'parenttype': u'DocType', - 'permlevel': 0, - 'read': 1, - 'write': 1 + 'read': 1 }, # DocType, Blog @@ -54,14 +51,27 @@ # DocPerm { + 'create': 1, 'doctype': u'DocPerm', - 'role': u'Website Manager' + 'permlevel': 0, + 'role': u'Website Manager', + 'write': 1 + }, + + # DocPerm + { + 'create': 1, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'Blogger', + 'write': 1 }, # DocPerm { 'doctype': u'DocPerm', - 'role': u'Blogger' + 'permlevel': 1, + 'role': u'All' }, # DocField @@ -70,7 +80,8 @@ 'fieldname': u'title', 'fieldtype': u'Data', 'label': u'Title', - 'permlevel': 0 + 'permlevel': 0, + 'reqd': 1 }, # DocField @@ -88,7 +99,8 @@ 'fieldname': u'content', 'fieldtype': u'Code', 'label': u'Content', - 'permlevel': 0 + 'permlevel': 0, + 'reqd': 0 }, # DocField @@ -96,10 +108,19 @@ 'doctype': u'DocField', 'fieldname': u'content_html', 'fieldtype': u'Text', - 'label': u'Preview', + 'label': u'Content HTML', 'permlevel': 1 }, + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'page_name', + 'fieldtype': u'Data', + 'label': u'Page Name', + 'permlevel': 0 + }, + # DocField { 'doctype': u'DocField', diff --git a/erpnext/website/doctype/blog/blog_page.js b/erpnext/website/doctype/blog/blog_page.js index aa3f4c57b16..dddc6e04f86 100644 --- a/erpnext/website/doctype/blog/blog_page.js +++ b/erpnext/website/doctype/blog/blog_page.js @@ -18,32 +18,28 @@ pscript['onload_{{ doc.name }}'] = function(wrapper) { // sidebar - var side = $(wrapper).find('.web-side-section') - .append('

Recent Posts

').get(0); - wrapper.recent_list = new wn.ui.Listing({ - parent: side, + parent: $(wrapper).find('.recent-posts'), + no_toolbar: true, query: 'select name, title, left(content, 100) as content from tabBlog\ - where ifnull(published,1)=1', + where ifnull(published,0)=1 and name!="{{ doc.name }}" order by modified desc', hide_refresh: true, render_row: function(parent, data) { - if(data.content.length==100) data.content += '...'; + console.log(data); + if(data.content && data.content.length==100) data.content += '...'; parent.innerHTML = repl('%(title)s\
%(content)s

', data); }, - page_length: 5 + page_length: 5, }); wrapper.recent_list.run(); - - - // comments - $(wrapper).find('.web-main-section').append('

Comments

'); - + wrapper.comment_list = new wn.ui.Listing({ - parent: $(wrapper).find('.web-main-section').get(0), + parent: $(wrapper).find('.blog-comments').get(0), + no_toolbar: true, query: 'select comment, comment_by_fullname, modified\ from `tabComment` where comment_doctype="Page"\ - and comment_docname="{{ doc.name }}"', + and comment_docname="{{ doc.name }}" order by modified desc', no_result_message: 'Be the first one to comment', render_row: function(parent, data) { data.comment_date = prettyDate(data.modified); @@ -57,7 +53,7 @@ pscript['onload_{{ doc.name }}'] = function(wrapper) { wrapper.comment_list.run(); // add comment - $(wrapper).find('.web-main-section').append('
'); $(wrapper).find('button.add-comment').click(function(){ d = new wn.widgets.Dialog({ diff --git a/erpnext/website/doctype/blog/template.html b/erpnext/website/doctype/blog/template.html index 467f30169fd..688ffac3103 100644 --- a/erpnext/website/doctype/blog/template.html +++ b/erpnext/website/doctype/blog/template.html @@ -1,14 +1,18 @@
-

Blog

-

{{ doc.title }}

+

{{ doc.title }}

By {{ doc.full_name }} on {{ doc.updated }}

{{ doc.content_html }} +

Comments

+
+

All Blogs

+

Recent Posts

+

Subscribe

diff --git a/erpnext/website/doctype/style_settings/custom_template.css b/erpnext/website/doctype/style_settings/custom_template.css index 8c987f87a5d..4866ac7be5c 100644 --- a/erpnext/website/doctype/style_settings/custom_template.css +++ b/erpnext/website/doctype/style_settings/custom_template.css @@ -1,4 +1,4 @@ -body { +#body_div { {% if doc.background_image %} background: url("files/{{ doc.background_image }}") repeat; {% elif doc.background_color %} diff --git a/erpnext/website/doctype/web_page/template.html b/erpnext/website/doctype/web_page/template.html index 471c95c94a8..b66aded5f37 100644 --- a/erpnext/website/doctype/web_page/template.html +++ b/erpnext/website/doctype/web_page/template.html @@ -28,6 +28,3 @@

-
- Last Modified: {{ doc.updated }} Feedback -
diff --git a/erpnext/website/doctype/web_page/web_page.js b/erpnext/website/doctype/web_page/web_page.js index 0b7b78da59d..17e7f15a488 100644 --- a/erpnext/website/doctype/web_page/web_page.js +++ b/erpnext/website/doctype/web_page/web_page.js @@ -24,10 +24,10 @@ $.extend(cur_frm.cscript, { refresh: function(doc) { cur_frm.cscript.layout(doc); }, - insert_style: function() { + insert_style: function(doc) { cur_frm.cscript.layout(doc); }, - insert_code: function() { + insert_code: function(doc) { cur_frm.cscript.layout(doc); } }) \ No newline at end of file diff --git a/erpnext/website/js/topbar.js b/erpnext/website/js/topbar.js index aec0f02aa8e..8caf8dcf1ca 100644 --- a/erpnext/website/js/topbar.js +++ b/erpnext/website/js/topbar.js @@ -91,8 +91,7 @@ erpnext.Footer = Class.extend({ init: function() { $('footer').html(repl('', wn.boot.website_settings)); diff --git a/erpnext/website/page/blog/blog.html b/erpnext/website/page/blog/blog.html index ffb81280a48..8d7cd00345c 100644 --- a/erpnext/website/page/blog/blog.html +++ b/erpnext/website/page/blog/blog.html @@ -3,6 +3,7 @@

Blog


+