Compare commits
131 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe977289eb | ||
|
|
45b5b6d11f | ||
|
|
c58b330673 | ||
|
|
5d976ca3ac | ||
|
|
f2f17959ab | ||
|
|
6448076143 | ||
|
|
3f657bcf51 | ||
|
|
53f7ba26f6 | ||
|
|
937103f840 | ||
|
|
1969f9e1ac | ||
|
|
60fcce66f7 | ||
|
|
47fcc0310d | ||
|
|
7e676f3aae | ||
|
|
30aac9bbcf | ||
|
|
c2a5858143 | ||
|
|
879b3a0cbc | ||
|
|
ef0a0e8209 | ||
|
|
f7f20f624a | ||
|
|
115dcc09d4 | ||
|
|
990d7c4862 | ||
|
|
166024a23c | ||
|
|
3c4bb0c7c9 | ||
|
|
258191ab40 | ||
|
|
d66396abe3 | ||
|
|
7c1976950d | ||
|
|
158200b209 | ||
|
|
a570cd66f7 | ||
|
|
d7f3d63a8e | ||
|
|
2e67426936 | ||
|
|
16f88ba3cd | ||
|
|
e31a41854b | ||
|
|
7349c191ab | ||
|
|
dc540dda4d | ||
|
|
5c494f79f3 | ||
|
|
191935bbf5 | ||
|
|
8c78a1abb7 | ||
|
|
8821541f33 | ||
|
|
5cec7ec84a | ||
|
|
9d5566634c | ||
|
|
9536f112b5 | ||
|
|
44a40b860e | ||
|
|
b3d26c08f6 | ||
|
|
98d4622ed8 | ||
|
|
24b26db327 | ||
|
|
fa9fabaa49 | ||
|
|
49e8e783e3 | ||
|
|
c4ee74857d | ||
|
|
fc13b87fd5 | ||
|
|
d9ba544e09 | ||
|
|
af21479665 | ||
|
|
eec59ae7c4 | ||
|
|
efa9a7ed5b | ||
|
|
557abdebe0 | ||
|
|
8589b1db22 | ||
|
|
82a21beba0 | ||
|
|
256c4da0a5 | ||
|
|
7395dc9969 | ||
|
|
d39bc09e62 | ||
|
|
c7676797e1 | ||
|
|
423932fab2 | ||
|
|
efda5b0d36 | ||
|
|
13a9e27320 | ||
|
|
b0433d96a3 | ||
|
|
f3aba2e536 | ||
|
|
1594f102fd | ||
|
|
b2f2df4c64 | ||
|
|
9f6c48d82e | ||
|
|
f0307dc75e | ||
|
|
872e4d1f3d | ||
|
|
b164e606f9 | ||
|
|
806343395a | ||
|
|
afe93d633c | ||
|
|
cd20717c3d | ||
|
|
529709e08b | ||
|
|
e82eee512b | ||
|
|
ee0c623760 | ||
|
|
dbb4955483 | ||
|
|
ed87335513 | ||
|
|
8a4111fe0e | ||
|
|
4bfa8d560b | ||
|
|
96db41d996 | ||
|
|
9a74330d6f | ||
|
|
1951baca57 | ||
|
|
da08124df2 | ||
|
|
2aecc5a717 | ||
|
|
a37ffe162b | ||
|
|
bc99c9d6e0 | ||
|
|
f32314dd0b | ||
|
|
7e73f35916 | ||
|
|
e1e63a91d6 | ||
|
|
9a05aad8ea | ||
|
|
f6b77479d7 | ||
|
|
3c279163fc | ||
|
|
6933617538 | ||
|
|
2648661757 | ||
|
|
e31a97f355 | ||
|
|
6bdb73c392 | ||
|
|
deda7e2c75 | ||
|
|
5cdb8cea13 | ||
|
|
90a8c9e636 | ||
|
|
c0c951b6a9 | ||
|
|
39eb7faeb9 | ||
|
|
4829ad3eb8 | ||
|
|
a682d45846 | ||
|
|
76dd468f0e | ||
|
|
a6df26839d | ||
|
|
c5d4fc38aa | ||
|
|
02f7e83bd1 | ||
|
|
f55d9414cd | ||
|
|
5644ed37a4 | ||
|
|
ee6200576a | ||
|
|
eeb8ba18cd | ||
|
|
3a19370892 | ||
|
|
6dc1ba6f7f | ||
|
|
d91af2853e | ||
|
|
d23ae108ae | ||
|
|
72f8ae2d5a | ||
|
|
1e347910d5 | ||
|
|
25cfb700bb | ||
|
|
8d2d4e82fd | ||
|
|
c43d58ac79 | ||
|
|
0b3c10601c | ||
|
|
14bf711d04 | ||
|
|
35a9d585b4 | ||
|
|
38e56eeb45 | ||
|
|
3dd1043d5e | ||
|
|
55387aa931 | ||
|
|
03463ef73b | ||
|
|
371663169c | ||
|
|
f3ded044e0 | ||
|
|
68b0d54b4b |
@@ -6,6 +6,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _
|
||||
from webnotes.utils import cint
|
||||
|
||||
class DocType:
|
||||
def __init__(self, d, dl):
|
||||
@@ -14,7 +15,12 @@ class DocType:
|
||||
def on_update(self):
|
||||
webnotes.conn.set_default("auto_accounting_for_stock", self.doc.auto_accounting_for_stock)
|
||||
|
||||
if self.doc.auto_accounting_for_stock:
|
||||
if cint(self.doc.auto_accounting_for_stock):
|
||||
# set default perpetual account in company
|
||||
for company in webnotes.conn.sql("select name from tabCompany"):
|
||||
webnotes.bean("Company", company[0]).save()
|
||||
|
||||
# Create account head for warehouses
|
||||
warehouse_list = webnotes.conn.sql("select name, company from tabWarehouse", as_dict=1)
|
||||
warehouse_with_no_company = [d.name for d in warehouse_list if not d.company]
|
||||
if warehouse_with_no_company:
|
||||
|
||||
@@ -146,11 +146,12 @@ def update_outstanding_amt(account, against_voucher_type, against_voucher, on_ca
|
||||
webnotes.conn.sql("update `tab%s` set outstanding_amount=%s where name='%s'" %
|
||||
(against_voucher_type, bal, against_voucher))
|
||||
|
||||
def validate_frozen_account(account, adv_adj):
|
||||
def validate_frozen_account(account, adv_adj=None):
|
||||
frozen_account = webnotes.conn.get_value("Account", account, "freeze_account")
|
||||
if frozen_account == 'Yes' and not adv_adj:
|
||||
frozen_accounts_modifier = webnotes.conn.get_value( 'Accounts Settings', None,
|
||||
'frozen_accounts_modifier')
|
||||
|
||||
if not frozen_accounts_modifier:
|
||||
webnotes.throw(account + _(" is a frozen account. \
|
||||
Either make the account active or assign role in Accounts Settings \
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-24 12:15:51",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-11-02 16:58:38",
|
||||
"modified": "2014-01-15 16:23:58",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@@ -154,7 +154,7 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:sys_defaults.auto_accounting_for_stock",
|
||||
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "expense_account",
|
||||
"fieldtype": "Link",
|
||||
|
||||
@@ -32,6 +32,9 @@ class DocType(BuyingController):
|
||||
}]
|
||||
|
||||
def validate(self):
|
||||
if not self.doc.is_opening:
|
||||
self.doc.is_opening = 'No'
|
||||
|
||||
super(DocType, self).validate()
|
||||
|
||||
self.po_required()
|
||||
@@ -45,15 +48,8 @@ class DocType(BuyingController):
|
||||
self.check_for_stopped_status()
|
||||
self.validate_with_previous_doc()
|
||||
self.validate_uom_is_integer("uom", "qty")
|
||||
|
||||
if not self.doc.is_opening:
|
||||
self.doc.is_opening = 'No'
|
||||
|
||||
self.set_aging_date()
|
||||
|
||||
#set against account for credit to
|
||||
self.set_against_expense_account()
|
||||
|
||||
self.validate_write_off_account()
|
||||
self.update_raw_material_cost()
|
||||
self.update_valuation_rate("entries")
|
||||
@@ -215,7 +211,8 @@ class DocType(BuyingController):
|
||||
against_accounts = []
|
||||
stock_items = self.get_stock_items()
|
||||
for item in self.doclist.get({"parentfield": "entries"}):
|
||||
if auto_accounting_for_stock and item.item_code in stock_items:
|
||||
if auto_accounting_for_stock and item.item_code in stock_items \
|
||||
and self.doc.is_opening == 'No':
|
||||
# in case of auto inventory accounting, against expense account is always
|
||||
# Stock Received But Not Billed for a stock item
|
||||
item.expense_head = stock_not_billed_account
|
||||
@@ -302,6 +299,7 @@ class DocType(BuyingController):
|
||||
self.make_gl_entries()
|
||||
self.update_against_document_in_jv()
|
||||
self.update_prevdoc_status()
|
||||
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
|
||||
|
||||
def make_gl_entries(self):
|
||||
auto_accounting_for_stock = \
|
||||
@@ -358,7 +356,8 @@ class DocType(BuyingController):
|
||||
# expense will be booked in sales invoice
|
||||
stock_item_and_auto_accounting_for_stock = True
|
||||
|
||||
valuation_amt = item.amount + item.item_tax_amount + item.rm_supp_cost
|
||||
valuation_amt = flt(item.amount + item.item_tax_amount + item.rm_supp_cost,
|
||||
self.precision("amount", item))
|
||||
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
@@ -420,7 +419,7 @@ class DocType(BuyingController):
|
||||
remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_voucher")
|
||||
|
||||
self.update_prevdoc_status()
|
||||
|
||||
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
|
||||
self.make_cancel_gl_entries()
|
||||
|
||||
def on_update(self):
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
{
|
||||
"creation": "2013-01-10 16:34:08",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-07-22 15:22:25",
|
||||
"modified": "2014-01-28 12:28:56",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "wasim@webnotestech.com"
|
||||
},
|
||||
{
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:title",
|
||||
"description": "Standard tax template that can be applied to all Purchase Transactions. This template can contain list of tax heads and also other expense heads like \"Shipping\", \"Insurance\", \"Handling\" etc.\n\n#### Note\n\nThe tax rate you define here will be the standard tax rate for all **Items**. If there are **Items** that have different rates, they must be added in the **Item Tax** table in the **Item** master.\n\n#### Description of Columns\n\n1. Calculation Type: \n - This can be on **Net Total** (that is the sum of basic amount).\n - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.\n - **Actual** (as mentioned).\n2. Account Head: The Account ledger under which this tax will be booked\n3. Cost Center: If the tax / charge is an income (like shipping) or expense it needs to be booked against a Cost Center.\n4. Description: Description of the tax (that will be printed in invoices / quotes).\n5. Rate: Tax rate.\n6. Amount: Tax amount.\n7. Total: Cumulative total to this point.\n8. Enter Row: If based on \"Previous Row Total\" you can select the row number which will be taken as a base for this calculation (default is the previous row).\n9. Consider Tax or Charge for: In this section you can specify if the tax / charge is only for valuation (not a part of total) or only for total (does not add value to the item) or for both.\n10. Add or Deduct: Whether you want to add or deduct the tax.",
|
||||
"doctype": "DocType",
|
||||
|
||||
@@ -19,8 +19,10 @@ erpnext.POS = Class.extend({
|
||||
<table class="table table-condensed table-hover" id="cart" style="table-layout: fixed;">\
|
||||
<thead>\
|
||||
<tr>\
|
||||
<th style="width: 50%">Item</th>\
|
||||
<th style="width: 25%; text-align: right;">Qty</th>\
|
||||
<th style="width: 40%">Item</th>\
|
||||
<th style="width: 9%"></th>\
|
||||
<th style="width: 17%; text-align: right;">Qty</th>\
|
||||
<th style="width: 9%"></th>\
|
||||
<th style="width: 25%; text-align: right;">Rate</th>\
|
||||
</tr>\
|
||||
</thead>\
|
||||
@@ -60,10 +62,16 @@ erpnext.POS = Class.extend({
|
||||
</div>\
|
||||
</div>\
|
||||
<br><br>\
|
||||
<button class="btn btn-success btn-lg make-payment">\
|
||||
<i class="icon-money"></i> Make Payment</button>\
|
||||
<button class="btn btn-default btn-lg delete-items pull-right" style="display: none;">\
|
||||
<i class="icon-trash"></i> Del</button>\
|
||||
<div class="row">\
|
||||
<div class="col-sm-9">\
|
||||
<button class="btn btn-success btn-lg make-payment">\
|
||||
<i class="icon-money"></i> Make Payment</button>\
|
||||
</div>\
|
||||
<div class="col-sm-3">\
|
||||
<button class="btn btn-default btn-lg remove-items" style="display: none;">\
|
||||
<i class="icon-trash"></i> Del</button>\
|
||||
</div>\
|
||||
</div>\
|
||||
<br><br>\
|
||||
</div>\
|
||||
<div class="col-sm-6">\
|
||||
@@ -82,7 +90,7 @@ erpnext.POS = Class.extend({
|
||||
me.refresh();
|
||||
});
|
||||
|
||||
this.call_function("delete-items", function() {me.remove_selected_item();});
|
||||
this.call_function("remove-items", function() {me.remove_selected_items();});
|
||||
this.call_function("make-payment", function() {me.make_payment();});
|
||||
},
|
||||
check_transaction_type: function() {
|
||||
@@ -101,6 +109,7 @@ erpnext.POS = Class.extend({
|
||||
this.party = party;
|
||||
this.price_list = (party == "Customer" ?
|
||||
this.frm.doc.selling_price_list : this.frm.doc.buying_price_list);
|
||||
this.price_list_field = (party == "Customer" ? "selling_price_list" : "buying_price_list");
|
||||
this.sales_or_purchase = (party == "Customer" ? "Sales" : "Purchase");
|
||||
this.net_total = "net_total_" + export_or_import;
|
||||
this.grand_total = "grand_total_" + export_or_import;
|
||||
@@ -261,22 +270,17 @@ erpnext.POS = Class.extend({
|
||||
this.frm.cscript.fname, this.frm.doctype), function(i, d) {
|
||||
if (d.item_code == item_code) {
|
||||
caught = true;
|
||||
if (serial_no) {
|
||||
d.serial_no += '\n' + serial_no;
|
||||
me.frm.script_manager.trigger("serial_no", d.doctype, d.name);
|
||||
}
|
||||
else {
|
||||
d.qty += 1;
|
||||
me.frm.script_manager.trigger("qty", d.doctype, d.name);
|
||||
}
|
||||
if (serial_no)
|
||||
wn.model.set_value(d.doctype, d.name, "serial_no", d.serial_no + '\n' + serial_no);
|
||||
else
|
||||
wn.model.set_value(d.doctype, d.name, "qty", d.qty + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// if item not found then add new item
|
||||
if (!caught) {
|
||||
if (!caught)
|
||||
this.add_new_item_to_grid(item_code, serial_no);
|
||||
}
|
||||
|
||||
this.refresh();
|
||||
this.refresh_search_box();
|
||||
@@ -311,15 +315,16 @@ erpnext.POS = Class.extend({
|
||||
wn.model.clear_doc(d.doctype, d.name);
|
||||
me.refresh_grid();
|
||||
} else {
|
||||
d.qty = qty;
|
||||
me.frm.script_manager.trigger("qty", d.doctype, d.name);
|
||||
wn.model.set_value(d.doctype, d.name, "qty", qty);
|
||||
}
|
||||
}
|
||||
});
|
||||
me.refresh();
|
||||
this.refresh();
|
||||
},
|
||||
refresh: function() {
|
||||
var me = this;
|
||||
|
||||
this.refresh_item_list();
|
||||
this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]);
|
||||
this.barcode.set_input("");
|
||||
|
||||
@@ -333,7 +338,7 @@ erpnext.POS = Class.extend({
|
||||
}
|
||||
|
||||
this.disable_text_box_and_button();
|
||||
this.make_payment_button();
|
||||
this.hide_payment_button();
|
||||
|
||||
// If quotation to is not Customer then remove party
|
||||
if (this.frm.doctype == "Quotation") {
|
||||
@@ -342,6 +347,14 @@ erpnext.POS = Class.extend({
|
||||
this.make_party();
|
||||
}
|
||||
},
|
||||
refresh_item_list: function() {
|
||||
var me = this;
|
||||
// refresh item list on change of price list
|
||||
if (this.frm.doc[this.price_list_field] != this.price_list) {
|
||||
this.price_list = this.frm.doc[this.price_list_field];
|
||||
this.make_item_list();
|
||||
}
|
||||
},
|
||||
show_items_in_item_cart: function() {
|
||||
var me = this;
|
||||
var $items = this.wrapper.find("#cart tbody").empty();
|
||||
@@ -351,8 +364,18 @@ erpnext.POS = Class.extend({
|
||||
|
||||
$(repl('<tr id="%(item_code)s" data-selected="false">\
|
||||
<td>%(item_code)s%(item_name)s</td>\
|
||||
<td><input type="text" value="%(qty)s" \
|
||||
<td style="vertical-align:middle;" align="right">\
|
||||
<div class="decrease-qty" style="cursor:pointer;">\
|
||||
<i class="icon-minus-sign icon-large text-danger"></i>\
|
||||
</div>\
|
||||
</td>\
|
||||
<td style="vertical-align:middle;"><input type="text" value="%(qty)s" \
|
||||
class="form-control qty" style="text-align: right;"></td>\
|
||||
<td style="vertical-align:middle;cursor:pointer;">\
|
||||
<div class="increase-qty" style="cursor:pointer;">\
|
||||
<i class="icon-plus-sign icon-large text-success"></i>\
|
||||
</div>\
|
||||
</td>\
|
||||
<td style="text-align: right;"><b>%(amount)s</b><br>%(rate)s</td>\
|
||||
</tr>',
|
||||
{
|
||||
@@ -364,27 +387,31 @@ erpnext.POS = Class.extend({
|
||||
}
|
||||
)).appendTo($items);
|
||||
});
|
||||
|
||||
this.wrapper.find("input.qty").on("focus", function() {
|
||||
$(this).select();
|
||||
});
|
||||
},
|
||||
show_taxes: function() {
|
||||
var me = this;
|
||||
var taxes = wn.model.get_children(this.sales_or_purchase + " Taxes and Charges",
|
||||
this.frm.doc.name, this.frm.cscript.other_fname, this.frm.doctype);
|
||||
$(this.wrapper).find(".tax-table")
|
||||
.toggle((taxes && taxes.length &&
|
||||
flt(me.frm.doc.other_charges_total_export ||
|
||||
me.frm.doc.other_charges_added_import) != 0.0) ? true : false)
|
||||
.toggle((taxes && taxes.length) ? true : false)
|
||||
.find("tbody").empty();
|
||||
|
||||
$.each(taxes, function(i, d) {
|
||||
$(repl('<tr>\
|
||||
<td>%(description)s %(rate)s</td>\
|
||||
<td style="text-align: right;">%(tax_amount)s</td>\
|
||||
<tr>', {
|
||||
description: d.description,
|
||||
rate: ((d.charge_type == "Actual") ? '' : ("(" + d.rate + "%)")),
|
||||
tax_amount: format_currency(flt(d.tax_amount)/flt(me.frm.doc.conversion_rate),
|
||||
me.frm.doc.currency)
|
||||
})).appendTo(".tax-table tbody");
|
||||
if (d.tax_amount) {
|
||||
$(repl('<tr>\
|
||||
<td>%(description)s %(rate)s</td>\
|
||||
<td style="text-align: right;">%(tax_amount)s</td>\
|
||||
<tr>', {
|
||||
description: d.description,
|
||||
rate: ((d.charge_type == "Actual") ? '' : ("(" + d.rate + "%)")),
|
||||
tax_amount: format_currency(flt(d.tax_amount)/flt(me.frm.doc.conversion_rate),
|
||||
me.frm.doc.currency)
|
||||
})).appendTo(".tax-table tbody");
|
||||
}
|
||||
});
|
||||
},
|
||||
set_totals: function() {
|
||||
@@ -399,10 +426,16 @@ erpnext.POS = Class.extend({
|
||||
|
||||
// append quantity to the respective item after change from input box
|
||||
$(this.wrapper).find("input.qty").on("change", function() {
|
||||
var item_code = $(this).closest("tr")[0].id;
|
||||
var item_code = $(this).closest("tr").attr("id");
|
||||
me.update_qty(item_code, $(this).val());
|
||||
});
|
||||
|
||||
// increase/decrease qty on plus/minus button
|
||||
$(this.wrapper).find(".increase-qty, .decrease-qty").on("click", function() {
|
||||
var tr = $(this).closest("tr");
|
||||
me.increase_decrease_qty(tr, $(this).attr("class"));
|
||||
});
|
||||
|
||||
// on td click toggle the highlighting of row
|
||||
$(this.wrapper).find("#cart tbody tr td").on("click", function() {
|
||||
var row = $(this).closest("tr");
|
||||
@@ -420,6 +453,15 @@ erpnext.POS = Class.extend({
|
||||
me.refresh_delete_btn();
|
||||
this.barcode.$input.focus();
|
||||
},
|
||||
increase_decrease_qty: function(tr, operation) {
|
||||
var item_code = tr.attr("id");
|
||||
var item_qty = cint(tr.find("input.qty").val());
|
||||
|
||||
if (operation == "increase-qty")
|
||||
this.update_qty(item_code, item_qty + 1);
|
||||
else if (operation == "decrease-qty" && item_qty != 1)
|
||||
this.update_qty(item_code, item_qty - 1);
|
||||
},
|
||||
disable_text_box_and_button: function() {
|
||||
var me = this;
|
||||
// if form is submitted & cancelled then disable all input box & buttons
|
||||
@@ -427,7 +469,7 @@ erpnext.POS = Class.extend({
|
||||
$(this.wrapper).find('input, button').each(function () {
|
||||
$(this).prop('disabled', true);
|
||||
});
|
||||
$(this.wrapper).find(".delete-items").hide();
|
||||
$(this.wrapper).find(".remove-items").hide();
|
||||
$(this.wrapper).find(".make-payment").hide();
|
||||
}
|
||||
else {
|
||||
@@ -437,14 +479,14 @@ erpnext.POS = Class.extend({
|
||||
$(this.wrapper).find(".make-payment").show();
|
||||
}
|
||||
},
|
||||
make_payment_button: function() {
|
||||
hide_payment_button: function() {
|
||||
var me = this;
|
||||
// Show Make Payment button only in Sales Invoice
|
||||
if (this.frm.doctype != "Sales Invoice")
|
||||
$(this.wrapper).find(".make-payment").hide();
|
||||
},
|
||||
refresh_delete_btn: function() {
|
||||
$(this.wrapper).find(".delete-items").toggle($(".item-cart .warning").length ? true : false);
|
||||
$(this.wrapper).find(".remove-items").toggle($(".item-cart .warning").length ? true : false);
|
||||
},
|
||||
add_item_thru_barcode: function() {
|
||||
var me = this;
|
||||
@@ -466,7 +508,7 @@ erpnext.POS = Class.extend({
|
||||
}
|
||||
});
|
||||
},
|
||||
remove_selected_item: function() {
|
||||
remove_selected_items: function() {
|
||||
var me = this;
|
||||
var selected_items = [];
|
||||
var no_of_items = $(this.wrapper).find("#cart tbody tr").length;
|
||||
@@ -487,9 +529,11 @@ erpnext.POS = Class.extend({
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.refresh_grid();
|
||||
},
|
||||
refresh_grid: function() {
|
||||
this.frm.dirty();
|
||||
this.frm.fields_dict[this.frm.cscript.fname].grid.refresh();
|
||||
this.frm.script_manager.trigger("calculate_taxes_and_totals");
|
||||
this.refresh();
|
||||
|
||||
@@ -88,6 +88,7 @@ class DocType(SellingController):
|
||||
|
||||
self.update_status_updater_args()
|
||||
self.update_prevdoc_status()
|
||||
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
||||
|
||||
# this sequence because outstanding may get -ve
|
||||
self.make_gl_entries()
|
||||
@@ -114,6 +115,7 @@ class DocType(SellingController):
|
||||
|
||||
self.update_status_updater_args()
|
||||
self.update_prevdoc_status()
|
||||
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
||||
|
||||
self.make_cancel_gl_entries()
|
||||
|
||||
@@ -318,12 +320,9 @@ class DocType(SellingController):
|
||||
item = webnotes.conn.sql("select name,is_asset_item,is_sales_item from `tabItem` where name = '%s' and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now())"% d.item_code)
|
||||
acc = webnotes.conn.sql("select account_type from `tabAccount` where name = '%s' and docstatus != 2" % d.income_account)
|
||||
if not acc:
|
||||
msgprint("Account: "+d.income_account+" does not exist in the system")
|
||||
raise Exception
|
||||
msgprint("Account: "+d.income_account+" does not exist in the system", raise_exception=True)
|
||||
elif item and item[0][1] == 'Yes' and not acc[0][0] == 'Fixed Asset Account':
|
||||
msgprint("Please select income head with account type 'Fixed Asset Account' as Item %s is an asset item" % d.item_code)
|
||||
raise Exception
|
||||
|
||||
msgprint("Please select income head with account type 'Fixed Asset Account' as Item %s is an asset item" % d.item_code, raise_exception=True)
|
||||
|
||||
def validate_with_previous_doc(self):
|
||||
super(DocType, self).validate_with_previous_doc(self.tname, {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-24 19:29:05",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-11-18 15:16:50",
|
||||
"modified": "2014-01-16 15:36:16",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@@ -1091,7 +1091,7 @@
|
||||
"fieldtype": "Select",
|
||||
"label": "Recurring Type",
|
||||
"no_copy": 1,
|
||||
"options": "Monthly\nQuarterly\nHalf-yearly\nYearly",
|
||||
"options": "\nMonthly\nQuarterly\nHalf-yearly\nYearly",
|
||||
"print_hide": 1,
|
||||
"read_only": 0
|
||||
},
|
||||
|
||||
@@ -654,7 +654,8 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
|
||||
def _test_recurring_invoice(self, base_si, first_and_last_day):
|
||||
from webnotes.utils import add_months, get_last_day
|
||||
from accounts.doctype.sales_invoice.sales_invoice import manage_recurring_invoices
|
||||
from accounts.doctype.sales_invoice.sales_invoice \
|
||||
import manage_recurring_invoices, get_next_date
|
||||
|
||||
no_of_months = ({"Monthly": 1, "Quarterly": 3, "Yearly": 12})[base_si.doc.recurring_type]
|
||||
|
||||
@@ -662,7 +663,8 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
self.assertEquals(i+1, webnotes.conn.sql("""select count(*) from `tabSales Invoice`
|
||||
where recurring_id=%s and docstatus=1""", base_si.doc.recurring_id)[0][0])
|
||||
|
||||
next_date = add_months(base_si.doc.posting_date, no_of_months)
|
||||
next_date = get_next_date(base_si.doc.posting_date, no_of_months,
|
||||
base_si.doc.repeat_on_day_of_month)
|
||||
|
||||
manage_recurring_invoices(next_date=next_date, commit=False)
|
||||
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
{
|
||||
"creation": "2013-01-10 16:34:09",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-10-31 19:25:09",
|
||||
"modified": "2014-01-28 12:28:27",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:title",
|
||||
"description": "Standard tax template that can be applied to all Sales Transactions. This template can contain list of tax heads and also other expense / income heads like \"Shipping\", \"Insurance\", \"Handling\" etc.\n\n#### Note\n\nThe tax rate you define here will be the standard tax rate for all **Items**. If there are **Items** that have different rates, they must be added in the **Item Tax** table in the **Item** master.\n\n#### Description of Columns\n\n1. Calculation Type: \n - This can be on **Net Total** (that is the sum of basic amount).\n - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.\n - **Actual** (as mentioned).\n2. Account Head: The Account ledger under which this tax will be booked\n3. Cost Center: If the tax / charge is an income (like shipping) or expense it needs to be booked against a Cost Center.\n4. Description: Description of the tax (that will be printed in invoices / quotes).\n5. Rate: Tax rate.\n6. Amount: Tax amount.\n7. Total: Cumulative total to this point.\n8. Enter Row: If based on \"Previous Row Total\" you can select the row number which will be taken as a base for this calculation (default is the previous row).\n9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.",
|
||||
"doctype": "DocType",
|
||||
|
||||
@@ -37,12 +37,15 @@ class AccountsReceivableReport(object):
|
||||
return columns
|
||||
|
||||
def get_data(self, customer_naming_by):
|
||||
from accounts.utils import get_currency_precision
|
||||
currency_precision = get_currency_precision() or 2
|
||||
|
||||
data = []
|
||||
future_vouchers = self.get_entries_after(self.filters.report_date)
|
||||
for gle in self.get_entries_till(self.filters.report_date):
|
||||
if self.is_receivable(gle, future_vouchers):
|
||||
outstanding_amount = self.get_outstanding_amount(gle, self.filters.report_date)
|
||||
if abs(outstanding_amount) > 0.0:
|
||||
if abs(outstanding_amount) > 0.1/10**currency_precision:
|
||||
due_date = self.get_due_date(gle)
|
||||
invoiced_amount = gle.debit if (gle.debit > 0) else 0
|
||||
payment_received = invoiced_amount - outstanding_amount
|
||||
@@ -129,7 +132,7 @@ class AccountsReceivableReport(object):
|
||||
if not hasattr(self, "gl_entries"):
|
||||
conditions, values = self.prepare_conditions()
|
||||
self.gl_entries = webnotes.conn.sql("""select * from `tabGL Entry`
|
||||
where docstatus < 2 {} order by posting_date, account""".format(conditions),
|
||||
where docstatus < 2 {0} order by posting_date, account""".format(conditions),
|
||||
values, as_dict=True)
|
||||
|
||||
return self.gl_entries
|
||||
@@ -150,8 +153,8 @@ class AccountsReceivableReport(object):
|
||||
if not account_map:
|
||||
webnotes.throw(_("No Customer Accounts found."))
|
||||
else:
|
||||
accounts_list = ['"{}"'.format(ac) for ac in account_map]
|
||||
conditions.append("account in ({})".format(", ".join(accounts_list)))
|
||||
accounts_list = ['"{0}"'.format(ac) for ac in account_map]
|
||||
conditions.append("account in ({0})".format(", ".join(accounts_list)))
|
||||
|
||||
return " and ".join(conditions), values
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ wn.query_reports["Bank Reconciliation Statement"] = {
|
||||
"label": wn._("Bank Account"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Account",
|
||||
"reqd": 1,
|
||||
"get_query": function() {
|
||||
return {
|
||||
"query": "accounts.utils.get_account_list",
|
||||
@@ -22,7 +23,8 @@ wn.query_reports["Bank Reconciliation Statement"] = {
|
||||
"fieldname":"report_date",
|
||||
"label": wn._("Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": get_today()
|
||||
"default": get_today(),
|
||||
"reqd": 1
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -3,13 +3,14 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _, msgprint
|
||||
from webnotes.utils import flt
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
|
||||
columns = get_columns()
|
||||
|
||||
debit_or_credit = webnotes.conn.get_value("Account", filters["account"], "debit_or_credit")
|
||||
|
||||
columns = get_columns()
|
||||
data = get_entries(filters)
|
||||
|
||||
from accounts.utils import get_balance_on
|
||||
@@ -20,47 +21,39 @@ def execute(filters=None):
|
||||
total_debit += flt(d[4])
|
||||
total_credit += flt(d[5])
|
||||
|
||||
if webnotes.conn.get_value("Account", filters["account"], "debit_or_credit") == 'Debit':
|
||||
if debit_or_credit == 'Debit':
|
||||
bank_bal = flt(balance_as_per_company) - flt(total_debit) + flt(total_credit)
|
||||
else:
|
||||
bank_bal = flt(balance_as_per_company) + flt(total_debit) - flt(total_credit)
|
||||
|
||||
data += [
|
||||
["", "", "", "Balance as per company books", balance_as_per_company, ""],
|
||||
get_balance_row("Balance as per company books", balance_as_per_company, debit_or_credit),
|
||||
["", "", "", "Amounts not reflected in bank", total_debit, total_credit],
|
||||
["", "", "", "Balance as per bank", bank_bal, ""]
|
||||
get_balance_row("Balance as per bank", bank_bal, debit_or_credit)
|
||||
]
|
||||
|
||||
return columns, data
|
||||
|
||||
return columns, data
|
||||
|
||||
def get_columns():
|
||||
return ["Journal Voucher:Link/Journal Voucher:140", "Posting Date:Date:100",
|
||||
"Clearance Date:Date:110", "Against Account:Link/Account:200",
|
||||
"Debit:Currency:120", "Credit:Currency:120"
|
||||
]
|
||||
|
||||
def get_conditions(filters):
|
||||
conditions = ""
|
||||
if not filters.get("account"):
|
||||
msgprint(_("Please select Bank Account"), raise_exception=1)
|
||||
else:
|
||||
conditions += " and jvd.account = %(account)s"
|
||||
|
||||
if not filters.get("report_date"):
|
||||
msgprint(_("Please select Date on which you want to run the report"), raise_exception=1)
|
||||
else:
|
||||
conditions += """ and jv.posting_date <= %(report_date)s
|
||||
and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s"""
|
||||
|
||||
return conditions
|
||||
|
||||
def get_entries(filters):
|
||||
conditions = get_conditions(filters)
|
||||
entries = webnotes.conn.sql("""select jv.name, jv.posting_date, jv.clearance_date,
|
||||
jvd.against_account, jvd.debit, jvd.credit
|
||||
from `tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv
|
||||
where jvd.parent = jv.name and jv.docstatus=1 and ifnull(jv.cheque_no, '')!= '' %s
|
||||
order by jv.name DESC""" % conditions, filters, as_list=1)
|
||||
entries = webnotes.conn.sql("""select
|
||||
jv.name, jv.posting_date, jv.clearance_date, jvd.against_account, jvd.debit, jvd.credit
|
||||
from
|
||||
`tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv
|
||||
where jvd.parent = jv.name and jv.docstatus=1 and ifnull(jv.cheque_no, '')!= ''
|
||||
and jvd.account = %(account)s and jv.posting_date <= %(report_date)s
|
||||
and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s
|
||||
order by jv.name DESC""", filters, as_list=1)
|
||||
|
||||
return entries
|
||||
return entries
|
||||
|
||||
def get_balance_row(label, amount, debit_or_credit):
|
||||
if debit_or_credit == "Debit":
|
||||
return ["", "", "", label, amount, 0]
|
||||
else:
|
||||
return ["", "", "", label, 0, amount]
|
||||
@@ -34,7 +34,7 @@ def validate_filters(filters, account_details):
|
||||
def get_columns():
|
||||
return ["Posting Date:Date:100", "Account:Link/Account:200", "Debit:Float:100",
|
||||
"Credit:Float:100", "Voucher Type::120", "Voucher No::160", "Link::20",
|
||||
"Against Account::120", "Cost Center:Link/Cost Center:100", "Remarks::200"]
|
||||
"Against Account::120", "Cost Center:Link/Cost Center:100", "Remarks::400"]
|
||||
|
||||
def get_result(filters, account_details):
|
||||
gl_entries = get_gl_entries(filters)
|
||||
@@ -51,7 +51,7 @@ def get_gl_entries(filters):
|
||||
|
||||
gl_entries = webnotes.conn.sql("""select posting_date, account,
|
||||
sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit,
|
||||
voucher_type, voucher_no, cost_center, remarks, is_advance, against
|
||||
voucher_type, voucher_no, cost_center, remarks, is_opening, against
|
||||
from `tabGL Entry`
|
||||
where company=%(company)s {conditions}
|
||||
{group_by_condition}
|
||||
@@ -138,7 +138,7 @@ def get_accountwise_gle(filters, gl_entries, gle_map):
|
||||
for gle in gl_entries:
|
||||
amount = flt(gle.debit) - flt(gle.credit)
|
||||
if filters.get("account") and (gle.posting_date < filters.from_date
|
||||
or cstr(gle.is_advance) == "Yes"):
|
||||
or cstr(gle.is_opening) == "Yes"):
|
||||
gle_map[gle.account].opening += amount
|
||||
opening += amount
|
||||
elif gle.posting_date <= filters.to_date:
|
||||
|
||||
@@ -378,4 +378,13 @@ def get_account_for(account_for_doctype, account_for):
|
||||
account_for_field = "account_type"
|
||||
|
||||
return webnotes.conn.get_value("Account", {account_for_field: account_for_doctype,
|
||||
"master_name": account_for})
|
||||
"master_name": account_for})
|
||||
|
||||
def get_currency_precision(currency=None):
|
||||
if not currency:
|
||||
currency = webnotes.conn.get_value("Company",
|
||||
webnotes.conn.get_default("company"), "default_currency")
|
||||
currency_format = webnotes.conn.get_value("Currency", currency, "number_format")
|
||||
|
||||
from webnotes.utils import get_number_format_info
|
||||
return get_number_format_info(currency_format)[2]
|
||||
@@ -302,11 +302,11 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
|
||||
calculate_totals: function() {
|
||||
var tax_count = this.frm.tax_doclist.length;
|
||||
this.frm.doc.grand_total = flt(
|
||||
tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
|
||||
this.frm.doc.grand_total = flt(tax_count ?
|
||||
this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
|
||||
precision("grand_total"));
|
||||
this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total / this.frm.doc.conversion_rate,
|
||||
precision("grand_total_import"));
|
||||
this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total /
|
||||
this.frm.doc.conversion_rate, precision("grand_total_import"));
|
||||
|
||||
this.frm.doc.total_tax = flt(this.frm.doc.grand_total - this.frm.doc.net_total,
|
||||
precision("total_tax"));
|
||||
@@ -321,20 +321,26 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
||||
}
|
||||
|
||||
// other charges added/deducted
|
||||
this.frm.doc.other_charges_added = 0.0
|
||||
this.frm.doc.other_charges_deducted = 0.0
|
||||
if(tax_count) {
|
||||
this.frm.doc.other_charges_added = wn.utils.sum($.map(this.frm.tax_doclist,
|
||||
function(tax) { return (tax.add_deduct_tax == "Add" && in_list(["Valuation and Total", "Total"], tax.category)) ? tax.tax_amount : 0.0; }));
|
||||
function(tax) { return (tax.add_deduct_tax == "Add"
|
||||
&& in_list(["Valuation and Total", "Total"], tax.category)) ?
|
||||
tax.tax_amount : 0.0; }));
|
||||
|
||||
this.frm.doc.other_charges_deducted = wn.utils.sum($.map(this.frm.tax_doclist,
|
||||
function(tax) { return (tax.add_deduct_tax == "Deduct" && in_list(["Valuation and Total", "Total"], tax.category)) ? tax.tax_amount : 0.0; }));
|
||||
function(tax) { return (tax.add_deduct_tax == "Deduct"
|
||||
&& in_list(["Valuation and Total", "Total"], tax.category)) ?
|
||||
tax.tax_amount : 0.0; }));
|
||||
|
||||
wn.model.round_floats_in(this.frm.doc, ["other_charges_added", "other_charges_deducted"]);
|
||||
|
||||
this.frm.doc.other_charges_added_import = flt(this.frm.doc.other_charges_added / this.frm.doc.conversion_rate,
|
||||
precision("other_charges_added_import"));
|
||||
this.frm.doc.other_charges_deducted_import = flt(this.frm.doc.other_charges_deducted / this.frm.doc.conversion_rate,
|
||||
precision("other_charges_deducted_import"));
|
||||
wn.model.round_floats_in(this.frm.doc,
|
||||
["other_charges_added", "other_charges_deducted"]);
|
||||
}
|
||||
this.frm.doc.other_charges_added_import = flt(this.frm.doc.other_charges_added /
|
||||
this.frm.doc.conversion_rate, precision("other_charges_added_import"));
|
||||
this.frm.doc.other_charges_deducted_import = flt(this.frm.doc.other_charges_deducted /
|
||||
this.frm.doc.conversion_rate, precision("other_charges_deducted_import"));
|
||||
},
|
||||
|
||||
_cleanup: function() {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
wn.require('app/setup/doctype/contact_control/contact_control.js');
|
||||
|
||||
cur_frm.cscript.refresh = function(doc,dt,dn) {
|
||||
cur_frm.cscript.refresh = function(doc, dt, dn) {
|
||||
cur_frm.cscript.make_dashboard(doc);
|
||||
erpnext.hide_naming_series();
|
||||
|
||||
@@ -93,7 +93,7 @@ cur_frm.cscript.make_contact = function() {
|
||||
cur_frm.contact_list.run();
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['default_price_list'].get_query = function(doc,cdt,cdn) {
|
||||
cur_frm.fields_dict['default_price_list'].get_query = function(doc, cdt, cdn) {
|
||||
return{
|
||||
filters:{'buying': 1}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-13 16:10:02",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-05-13 16:21:07",
|
||||
"modified": "2014-01-24 18:19:11",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@@ -11,7 +11,7 @@
|
||||
"doctype": "Report",
|
||||
"is_standard": "Yes",
|
||||
"name": "__common__",
|
||||
"query": "select \n mr.name as \"Material Request:Link/Material Request:120\",\n\tmr.transaction_date as \"Date:Date:100\",\n\tmr_item.item_code as \"Item Code:Link/Item:120\",\n\tmr_item.qty as \"Qty:Float:100\",\n\tmr_item.ordered_qty as \"Ordered Qty:Float:100\", \n\t(mr_item.qty - ifnull(mr_item.ordered_qty, 0)) as \"Qty to Order:Float:100\",\n\tmr_item.item_name as \"Item Name::150\",\n\tmr_item.description as \"Description::200\"\nfrom\n\t`tabMaterial Request` mr, `tabMaterial Request Item` mr_item\nwhere\n\tmr_item.parent = mr.name\n\tand mr.material_request_type = \"Purchase\"\n\tand mr.docstatus = 1\n\tand mr.status != \"Stopped\"\n\tand ifnull(mr_item.ordered_qty, 0) < ifnull(mr_item.qty, 0)\norder by mr.transaction_date asc",
|
||||
"query": "select \n mr.name as \"Material Request:Link/Material Request:120\",\n\tmr.transaction_date as \"Date:Date:100\",\n\tmr_item.item_code as \"Item Code:Link/Item:120\",\n\tsum(ifnull(mr_item.qty, 0)) as \"Qty:Float:100\",\n\tsum(ifnull(mr_item.ordered_qty, 0)) as \"Ordered Qty:Float:100\", \n\t(sum(mr_item.qty) - sum(ifnull(mr_item.ordered_qty, 0))) as \"Qty to Order:Float:100\",\n\tmr_item.item_name as \"Item Name::150\",\n\tmr_item.description as \"Description::200\"\nfrom\n\t`tabMaterial Request` mr, `tabMaterial Request Item` mr_item\nwhere\n\tmr_item.parent = mr.name\n\tand mr.material_request_type = \"Purchase\"\n\tand mr.docstatus = 1\n\tand mr.status != \"Stopped\"\ngroup by mr.name, mr_item.item_code\nhaving\n\tsum(ifnull(mr_item.ordered_qty, 0)) < sum(ifnull(mr_item.qty, 0))\norder by mr.transaction_date asc",
|
||||
"ref_doctype": "Purchase Order",
|
||||
"report_name": "Requested Items To Be Ordered",
|
||||
"report_type": "Query Report"
|
||||
|
||||
@@ -89,8 +89,10 @@ def _get_price_list_rate(args, item_bean, meta):
|
||||
|
||||
# try fetching from price list
|
||||
if args.buying_price_list and args.price_list_currency:
|
||||
price_list_rate = webnotes.conn.sql("""select ref_rate from `tabItem Price`
|
||||
where price_list=%s and item_code=%s and buying=1""",
|
||||
price_list_rate = webnotes.conn.sql("""select ip.ref_rate from
|
||||
`tabItem Price` ip, `tabPrice List` pl
|
||||
where ip.price_list=pl.name and ip.price_list=%s and
|
||||
ip.item_code=%s and ip.buying=1 and pl.enabled=1""",
|
||||
(args.buying_price_list, args.item_code), as_dict=1)
|
||||
|
||||
if price_list_rate:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"app_name": "ERPNext",
|
||||
"app_version": "3.5.1",
|
||||
"app_version": "3.8.1",
|
||||
"base_template": "app/portal/templates/base.html",
|
||||
"modules": {
|
||||
"Accounts": {
|
||||
@@ -74,5 +74,5 @@
|
||||
"type": "module"
|
||||
}
|
||||
},
|
||||
"requires_framework_version": "==3.5.0"
|
||||
"requires_framework_version": "==3.9.0"
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _, msgprint, throw
|
||||
from webnotes import _, throw
|
||||
from webnotes.utils import flt, cint, today, cstr
|
||||
from webnotes.model.code import get_obj
|
||||
from setup.utils import get_company_currency
|
||||
@@ -44,14 +44,13 @@ class AccountsController(TransactionBase):
|
||||
def validate_for_freezed_account(self):
|
||||
for fieldname in ["customer", "supplier"]:
|
||||
if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname):
|
||||
accounts = webnotes.conn.get_values("Account", {"master_type": fieldname.title(),
|
||||
"master_name": self.doc.fields[fieldname], "company": self.doc.company},
|
||||
"freeze_account", as_dict=1)
|
||||
|
||||
accounts = webnotes.conn.get_values("Account",
|
||||
{"master_type": fieldname.title(), "master_name": self.doc.fields[fieldname],
|
||||
"company": self.doc.company}, "name")
|
||||
if accounts:
|
||||
if not filter(lambda x: cstr(x.freeze_account) in ["", "No"], accounts):
|
||||
throw(_("Account for this ") + fieldname + _(" has been freezed. ") +
|
||||
self.doc.doctype + _(" can not be made."))
|
||||
from accounts.doctype.gl_entry.gl_entry import validate_frozen_account
|
||||
for account in accounts:
|
||||
validate_frozen_account(account[0])
|
||||
|
||||
def set_price_list_currency(self, buying_or_selling):
|
||||
if self.meta.get_field("currency"):
|
||||
@@ -224,20 +223,22 @@ class AccountsController(TransactionBase):
|
||||
_on_previous_row_error("1 - %d" % (tax.row_id,))
|
||||
|
||||
def calculate_taxes(self):
|
||||
for item in self.item_doclist:
|
||||
# maintain actual tax rate based on idx
|
||||
actual_tax_dict = dict([[tax.idx, tax.rate] for tax in self.tax_doclist
|
||||
if tax.charge_type == "Actual"])
|
||||
|
||||
for n, item in enumerate(self.item_doclist):
|
||||
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
|
||||
|
||||
for i, tax in enumerate(self.tax_doclist):
|
||||
# tax_amount represents the amount of tax for the current step
|
||||
current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map)
|
||||
|
||||
# case when net total is 0 but there is an actual type charge
|
||||
# in this case add the actual amount to tax.tax_amount
|
||||
# and tax.grand_total_for_current_item for the first such iteration
|
||||
if tax.charge_type=="Actual" and \
|
||||
not (current_tax_amount or self.doc.net_total or tax.tax_amount):
|
||||
zero_net_total_adjustment = flt(tax.rate, self.precision("tax_amount", tax))
|
||||
current_tax_amount += zero_net_total_adjustment
|
||||
|
||||
# Adjust divisional loss to the last item
|
||||
if tax.charge_type == "Actual":
|
||||
actual_tax_dict[tax.idx] -= current_tax_amount
|
||||
if n == len(self.item_doclist) - 1:
|
||||
current_tax_amount += actual_tax_dict[tax.idx]
|
||||
|
||||
# store tax_amount for current item as it will be used for
|
||||
# charge type = 'On Previous Row Amount'
|
||||
@@ -249,7 +250,8 @@ class AccountsController(TransactionBase):
|
||||
if tax.category:
|
||||
# if just for valuation, do not add the tax amount in total
|
||||
# hence, setting it as 0 for further steps
|
||||
current_tax_amount = 0.0 if (tax.category == "Valuation") else current_tax_amount
|
||||
current_tax_amount = 0.0 if (tax.category == "Valuation") \
|
||||
else current_tax_amount
|
||||
|
||||
current_tax_amount *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
|
||||
|
||||
@@ -268,6 +270,11 @@ class AccountsController(TransactionBase):
|
||||
# in tax.total, accumulate grand total of each item
|
||||
tax.total += tax.grand_total_for_current_item
|
||||
|
||||
# set precision in the last item iteration
|
||||
if n == len(self.item_doclist) - 1:
|
||||
tax.total = flt(tax.total, self.precision("total", tax))
|
||||
tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax))
|
||||
|
||||
def get_current_tax_amount(self, item, tax, item_tax_map):
|
||||
tax_rate = self._get_tax_rate(tax, item_tax_map)
|
||||
current_tax_amount = 0.0
|
||||
|
||||
@@ -124,8 +124,8 @@ class BuyingController(StockController):
|
||||
self.round_floats_in(self.doc, ["net_total", "net_total_import"])
|
||||
|
||||
def calculate_totals(self):
|
||||
self.doc.grand_total = flt(self.tax_doclist and \
|
||||
self.tax_doclist[-1].total or self.doc.net_total, self.precision("grand_total"))
|
||||
self.doc.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist
|
||||
else self.doc.net_total, self.precision("grand_total"))
|
||||
self.doc.grand_total_import = flt(self.doc.grand_total / self.doc.conversion_rate,
|
||||
self.precision("grand_total_import"))
|
||||
|
||||
@@ -137,6 +137,24 @@ class BuyingController(StockController):
|
||||
|
||||
if self.meta.get_field("rounded_total_import"):
|
||||
self.doc.rounded_total_import = _round(self.doc.grand_total_import)
|
||||
|
||||
if self.meta.get_field("other_charges_added"):
|
||||
self.doc.other_charges_added = flt(sum([flt(d.tax_amount) for d in self.tax_doclist
|
||||
if d.add_deduct_tax=="Add" and d.category in ["Valuation and Total", "Total"]]),
|
||||
self.precision("other_charges_added"))
|
||||
|
||||
if self.meta.get_field("other_charges_deducted"):
|
||||
self.doc.other_charges_deducted = flt(sum([flt(d.tax_amount) for d in self.tax_doclist
|
||||
if d.add_deduct_tax=="Deduct" and d.category in ["Valuation and Total", "Total"]]),
|
||||
self.precision("other_charges_deducted"))
|
||||
|
||||
if self.meta.get_field("other_charges_added_import"):
|
||||
self.doc.other_charges_added_import = flt(self.doc.other_charges_added /
|
||||
self.doc.conversion_rate, self.precision("other_charges_added_import"))
|
||||
|
||||
if self.meta.get_field("other_charges_deducted_import"):
|
||||
self.doc.other_charges_deducted_import = flt(self.doc.other_charges_deducted /
|
||||
self.doc.conversion_rate, self.precision("other_charges_deducted_import"))
|
||||
|
||||
def calculate_outstanding_amount(self):
|
||||
if self.doc.doctype == "Purchase Invoice" and self.doc.docstatus < 2:
|
||||
@@ -175,23 +193,31 @@ class BuyingController(StockController):
|
||||
stock_items = self.get_stock_items()
|
||||
|
||||
stock_items_qty, stock_items_amount = 0, 0
|
||||
last_stock_item_idx = 1
|
||||
for d in self.doclist.get({"parentfield": parentfield}):
|
||||
if d.item_code and d.item_code in stock_items:
|
||||
stock_items_qty += flt(d.qty)
|
||||
stock_items_amount += flt(d.amount)
|
||||
last_stock_item_idx = d.idx
|
||||
|
||||
total_valuation_amount = sum([flt(d.tax_amount) for d in
|
||||
self.doclist.get({"parentfield": "purchase_tax_details"})
|
||||
if d.category in ["Valuation", "Valuation and Total"]])
|
||||
|
||||
|
||||
for item in self.doclist.get({"parentfield": parentfield}):
|
||||
|
||||
valuation_amount_adjustment = total_valuation_amount
|
||||
for i, item in enumerate(self.doclist.get({"parentfield": parentfield})):
|
||||
if item.item_code and item.qty and item.item_code in stock_items:
|
||||
item_proportion = flt(item.amount) / stock_items_amount if stock_items_amount \
|
||||
else flt(item.qty) / stock_items_qty
|
||||
|
||||
item.item_tax_amount = flt(item_proportion * total_valuation_amount,
|
||||
self.precision("item_tax_amount", item))
|
||||
if i == (last_stock_item_idx - 1):
|
||||
item.item_tax_amount = flt(valuation_amount_adjustment,
|
||||
self.precision("item_tax_amount", item))
|
||||
else:
|
||||
item.item_tax_amount = flt(item_proportion * total_valuation_amount,
|
||||
self.precision("item_tax_amount", item))
|
||||
valuation_amount_adjustment -= item.item_tax_amount
|
||||
|
||||
self.round_floats_in(item)
|
||||
|
||||
|
||||
@@ -191,7 +191,8 @@ class SellingController(StockController):
|
||||
|
||||
self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total,
|
||||
self.precision("other_charges_total"))
|
||||
self.doc.other_charges_total_export = flt(self.doc.grand_total_export - self.doc.net_total_export,
|
||||
self.doc.other_charges_total_export = flt(
|
||||
self.doc.grand_total_export - self.doc.net_total_export,
|
||||
self.precision("other_charges_total_export"))
|
||||
|
||||
self.doc.rounded_total = _round(self.doc.grand_total)
|
||||
|
||||
@@ -232,6 +232,43 @@ class StatusUpdater(DocListController):
|
||||
'Fully %(keyword)s', 'Partly %(keyword)s'))
|
||||
where name='%(name)s'""" % args)
|
||||
|
||||
|
||||
def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
|
||||
ref_fieldname = ref_dt.lower().replace(" ", "_")
|
||||
zero_amount_refdoc = []
|
||||
all_zero_amount_refdoc = webnotes.conn.sql_list("""select name from `tab%s`
|
||||
where docstatus=1 and net_total = 0""" % ref_dt)
|
||||
|
||||
for item in self.doclist.get({"parentfield": "entries"}):
|
||||
if item.fields.get(ref_fieldname) \
|
||||
and item.fields.get(ref_fieldname) in all_zero_amount_refdoc \
|
||||
and item.fields.get(ref_fieldname) not in zero_amount_refdoc:
|
||||
zero_amount_refdoc.append(item.fields[ref_fieldname])
|
||||
|
||||
if zero_amount_refdoc:
|
||||
self.update_biling_status(zero_amount_refdoc, ref_dt, ref_fieldname)
|
||||
|
||||
def update_biling_status(self, zero_amount_refdoc, ref_dt, ref_fieldname):
|
||||
for ref_dn in zero_amount_refdoc:
|
||||
ref_doc_qty = flt(webnotes.conn.sql("""select sum(ifnull(qty, 0)) from `tab%s Item`
|
||||
where parent=%s""" % (ref_dt, '%s'), (ref_dn))[0][0])
|
||||
|
||||
billed_qty = flt(webnotes.conn.sql("""select sum(ifnull(qty, 0))
|
||||
from `tab%s Item` where %s=%s and docstatus=1""" %
|
||||
(self.doc.doctype, ref_fieldname, '%s'), (ref_dn))[0][0])
|
||||
|
||||
per_billed = ((ref_doc_qty if billed_qty > ref_doc_qty else billed_qty)\
|
||||
/ ref_doc_qty)*100
|
||||
webnotes.conn.set_value(ref_dt, ref_dn, "per_billed", per_billed)
|
||||
|
||||
from webnotes.model.meta import has_field
|
||||
if has_field(ref_dt, "billing_status"):
|
||||
if per_billed < 0.001: billing_status = "Not Billed"
|
||||
elif per_billed >= 99.99: billing_status = "Fully Billed"
|
||||
else: billing_status = "Partly Billed"
|
||||
|
||||
webnotes.conn.set_value(ref_dt, ref_dn, "billing_status", billing_status)
|
||||
|
||||
def get_tolerance_for(item_code, item_tolerance={}, global_tolerance=None):
|
||||
"""
|
||||
Returns the tolerance for the item, if not set, returns global tolerance
|
||||
|
||||
@@ -43,7 +43,7 @@ cur_frm.cscript.make_jv = function(doc, dt, dn) {
|
||||
jv = locals['Journal Voucher'][jv];
|
||||
jv.voucher_type = 'Bank Voucher';
|
||||
jv.user_remark = wn._('Payment of salary for the month: ') + doc.month +
|
||||
wn._('and fiscal year: ') + doc.fiscal_year;
|
||||
wn._(' and fiscal year: ') + doc.fiscal_year;
|
||||
jv.fiscal_year = doc.fiscal_year;
|
||||
jv.company = doc.company;
|
||||
jv.posting_date = dateutil.obj_to_str(new Date());
|
||||
|
||||
@@ -7,7 +7,7 @@ wn.query_reports["Monthly Salary Register"] = {
|
||||
"fieldname":"month",
|
||||
"label": wn._("Month"),
|
||||
"fieldtype": "Select",
|
||||
"options": "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec",
|
||||
"options": "\nJan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec",
|
||||
"default": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov",
|
||||
"Dec"][wn.datetime.str_to_obj(wn.datetime.get_today()).getMonth()],
|
||||
},
|
||||
|
||||
@@ -50,17 +50,17 @@ def get_columns(salary_slips):
|
||||
where ifnull(d_modified_amount, 0) != 0 and parent in (%s)""" %
|
||||
(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]))
|
||||
|
||||
columns = columns + [(e + ":Link/Earning Type:120") for e in earning_types] + \
|
||||
columns = columns + [(e + ":Currency:120") for e in earning_types] + \
|
||||
["Arrear Amount:Currency:120", "Leave Encashment Amount:Currency:150",
|
||||
"Gross Pay:Currency:120"] + [(d + ":Link/Deduction Type:120") for d in ded_types] + \
|
||||
"Gross Pay:Currency:120"] + [(d + ":Currency:120") for d in ded_types] + \
|
||||
["Total Deduction:Currency:120", "Net Pay:Currency:120"]
|
||||
|
||||
return columns, earning_types, ded_types
|
||||
|
||||
def get_salary_slips(filters):
|
||||
conditions, filters = get_conditions(filters)
|
||||
salary_slips = webnotes.conn.sql("""select * from `tabSalary Slip` where docstatus = 1 %s""" %
|
||||
conditions, filters, as_dict=1)
|
||||
salary_slips = webnotes.conn.sql("""select * from `tabSalary Slip` where docstatus = 1 %s
|
||||
order by employee, month""" % conditions, filters, as_dict=1)
|
||||
|
||||
if not salary_slips:
|
||||
msgprint(_("No salary slip found for month: ") + cstr(filters.get("month")) +
|
||||
@@ -102,6 +102,6 @@ def get_ss_ded_map(salary_slips):
|
||||
ss_ded_map = {}
|
||||
for d in ss_deductions:
|
||||
ss_ded_map.setdefault(d.parent, webnotes._dict()).setdefault(d.d_type, [])
|
||||
ss_ded_map[d.parent][d.e_type] = flt(d.d_modified_amount)
|
||||
ss_ded_map[d.parent][d.d_type] = flt(d.d_modified_amount)
|
||||
|
||||
return ss_ded_map
|
||||
@@ -20,7 +20,7 @@ requirements = [
|
||||
"jinja2",
|
||||
"markdown2",
|
||||
"markupsafe",
|
||||
"mysql-python==1.2.4",
|
||||
"mysql-python",
|
||||
"pygeoip",
|
||||
"python-dateutil",
|
||||
"python-memcached",
|
||||
|
||||
@@ -35,6 +35,7 @@ class TestProductionOrder(unittest.TestCase):
|
||||
|
||||
stock_entry.doc.fg_completed_qty = 4
|
||||
stock_entry.doc.posting_date = "2013-05-12"
|
||||
stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
|
||||
stock_entry.run_method("get_items")
|
||||
stock_entry.submit()
|
||||
|
||||
@@ -52,6 +53,7 @@ class TestProductionOrder(unittest.TestCase):
|
||||
stock_entry = make_stock_entry(pro_order, "Manufacture/Repack")
|
||||
stock_entry = webnotes.bean(stock_entry)
|
||||
stock_entry.doc.posting_date = "2013-05-12"
|
||||
stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
|
||||
stock_entry.doc.fg_completed_qty = 15
|
||||
stock_entry.run_method("get_items")
|
||||
stock_entry.insert()
|
||||
|
||||
@@ -243,10 +243,10 @@ class DocType:
|
||||
"item_code": [qty_required, description, stock_uom, min_order_qty]
|
||||
}
|
||||
"""
|
||||
bom_wise_item_details = {}
|
||||
item_list = []
|
||||
|
||||
for bom, so_wise_qty in bom_dict.items():
|
||||
bom_wise_item_details = {}
|
||||
if self.doc.use_multi_level_bom:
|
||||
# get all raw materials with sub assembly childs
|
||||
for d in webnotes.conn.sql("""select fb.item_code,
|
||||
|
||||
9
patches/1401/enable_all_price_list.py
Normal file
9
patches/1401/enable_all_price_list.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2014, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
def execute():
|
||||
webnotes.reload_doc("stock", "doctype", "price_list")
|
||||
webnotes.conn.sql("""update `tabPrice List` set enabled=1""")
|
||||
13
patches/1401/fix_planned_qty.py
Normal file
13
patches/1401/fix_planned_qty.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import webnotes
|
||||
|
||||
def execute():
|
||||
webnotes.conn.auto_commit_on_many_writes = 1
|
||||
from utilities.repost_stock import repost_stock
|
||||
for d in webnotes.conn.sql("""select distinct production_item, fg_warehouse
|
||||
from `tabProduction Order` where docstatus>0""", as_dict=1):
|
||||
repost_stock(d.production_item, d.fg_warehouse)
|
||||
|
||||
webnotes.conn.auto_commit_on_many_writes = 0
|
||||
19
patches/1401/fix_serial_no_status_and_warehouse.py
Normal file
19
patches/1401/fix_serial_no_status_and_warehouse.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
|
||||
def execute():
|
||||
serial_nos = webnotes.conn.sql("""select name from `tabSerial No` where docstatus=0
|
||||
and status in ('Available', 'Sales Returned') and ifnull(warehouse, '') = ''""")
|
||||
for sr in serial_nos:
|
||||
try:
|
||||
last_sle = webnotes.bean("Serial No", sr[0]).make_controller().get_last_sle()
|
||||
if last_sle.actual_qty > 0:
|
||||
webnotes.conn.set_value("Serial No", sr[0], "warehouse", last_sle.warehouse)
|
||||
|
||||
webnotes.conn.commit()
|
||||
except:
|
||||
pass
|
||||
@@ -0,0 +1,25 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import webnotes
|
||||
|
||||
def execute():
|
||||
webnotes.reload_doc("core", "doctype", "custom_field")
|
||||
|
||||
cf_doclist = webnotes.get_doctype("Custom Field")
|
||||
|
||||
delete_list = []
|
||||
for d in webnotes.conn.sql("""select cf.name as cf_name, ps.property,
|
||||
ps.value, ps.name as ps_name
|
||||
from `tabProperty Setter` ps, `tabCustom Field` cf
|
||||
where ps.doctype_or_field = 'DocField' and ps.property != 'previous_field'
|
||||
and ps.doc_type=cf.dt and ps.field_name=cf.fieldname""", as_dict=1):
|
||||
if cf_doclist.get_field(d.property):
|
||||
webnotes.conn.sql("""update `tabCustom Field`
|
||||
set `%s`=%s where name=%s""" % (d.property, '%s', '%s'), (d.value, d.cf_name))
|
||||
|
||||
delete_list.append(d.ps_name)
|
||||
|
||||
if delete_list:
|
||||
webnotes.conn.sql("""delete from `tabProperty Setter` where name in (%s)""" %
|
||||
', '.join(['%s']*len(delete_list)), tuple(delete_list))
|
||||
29
patches/1401/update_billing_status_for_zero_value_order.py
Normal file
29
patches/1401/update_billing_status_for_zero_value_order.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import webnotes
|
||||
from webnotes.utils import flt
|
||||
|
||||
def execute():
|
||||
for order_type in ["Sales", "Purchase"]:
|
||||
for d in webnotes.conn.sql("""select par.name, sum(ifnull(child.qty, 0)) as total_qty
|
||||
from `tab%s Order` par, `tab%s Order Item` child
|
||||
where par.name = child.parent and par.docstatus = 1
|
||||
and ifnull(par.net_total, 0) = 0 group by par.name""" %
|
||||
(order_type, order_type), as_dict=1):
|
||||
|
||||
billed_qty = flt(webnotes.conn.sql("""select sum(ifnull(qty, 0))
|
||||
from `tab%s Invoice Item` where %s=%s and docstatus=1""" %
|
||||
(order_type, "sales_order" if order_type=="Sales" else "purchase_order", '%s'),
|
||||
(d.name))[0][0])
|
||||
|
||||
per_billed = ((d.total_qty if billed_qty > d.total_qty else billed_qty)\
|
||||
/ d.total_qty)*100
|
||||
webnotes.conn.set_value(order_type+ " Order", d.name, "per_billed", per_billed)
|
||||
|
||||
if order_type == "Sales":
|
||||
if per_billed < 0.001: billing_status = "Not Billed"
|
||||
elif per_billed >= 99.99: billing_status = "Fully Billed"
|
||||
else: billing_status = "Partly Billed"
|
||||
|
||||
webnotes.conn.set_value("Sales Order", d.name, "billing_status", billing_status)
|
||||
@@ -263,5 +263,10 @@ patch_list = [
|
||||
"patches.1311.p08_email_digest_recipients",
|
||||
"execute:webnotes.delete_doc('DocType', 'Warehouse Type')",
|
||||
"patches.1312.p02_update_item_details_in_item_price",
|
||||
"patches.1401.p01_move_related_property_setters_to_custom_field",
|
||||
"patches.1401.p01_make_buying_selling_as_check_box_in_price_list",
|
||||
"patches.1401.update_billing_status_for_zero_value_order",
|
||||
"patches.1401.enable_all_price_list",
|
||||
"patches.1401.fix_serial_no_status_and_warehouse",
|
||||
"patches.1401.fix_planned_qty",
|
||||
]
|
||||
@@ -10,9 +10,9 @@
|
||||
<li class="active"><i class="icon-file icon-fixed-width"></i> {{ doc.name }}</li>
|
||||
</ul>
|
||||
<h3><i class="icon-file icon-fixed-width"></i> {{ doc.name }}</h3>
|
||||
{% if doc.name == "Not Allowed" -%}
|
||||
{% if session_user == "Guest" -%}
|
||||
<script>ask_to_login();</script>
|
||||
{% else %}
|
||||
{% elif doc.name != "Not Allowed"%}
|
||||
<hr>
|
||||
<div>
|
||||
<div class="row">
|
||||
|
||||
@@ -41,21 +41,23 @@ def get_currency_context():
|
||||
}
|
||||
|
||||
def get_transaction_context(doctype, name):
|
||||
context = {"session_user": webnotes.session.user}
|
||||
|
||||
customer = webnotes.conn.get_value("Contact", {"email_id": webnotes.session.user},
|
||||
"customer")
|
||||
|
||||
bean = webnotes.bean(doctype, name)
|
||||
if bean.doc.customer != customer:
|
||||
return {
|
||||
"doc": {"name": "Not Allowed"}
|
||||
}
|
||||
context.update({"doc": {"name": "Not Allowed"}})
|
||||
else:
|
||||
return {
|
||||
context.update({
|
||||
"doc": bean.doc,
|
||||
"doclist": bean.doclist,
|
||||
"webnotes": webnotes,
|
||||
"utils": webnotes.utils
|
||||
}
|
||||
})
|
||||
|
||||
return context
|
||||
|
||||
@webnotes.whitelist(allow_guest=True)
|
||||
def send_message(subject="Website Query", message="", sender="", status="Open"):
|
||||
|
||||
@@ -24,16 +24,17 @@ $(document).bind('toolbar_setup', function() {
|
||||
wn.provide('wn.ui.misc');
|
||||
wn.ui.misc.about = function() {
|
||||
if(!wn.ui.misc.about_dialog) {
|
||||
var d = new wn.ui.Dialog({title: wn._('About ERPNext')})
|
||||
var d = new wn.ui.Dialog({title: wn._('About')})
|
||||
|
||||
$(d.body).html(repl("<div>\
|
||||
<p>"+wn._("ERPNext is an open-source web based ERP made by Web Notes Technologies Pvt Ltd.\
|
||||
to provide an integrated tool to manage most processes in a small organization.\
|
||||
For more information about Web Notes, or to buy hosting servies, go to ")+
|
||||
"<a href='https://erpnext.com'>https://erpnext.com</a>.</p>\
|
||||
<p>"+wn._("To report an issue, go to ")+"<a href='https://github.com/webnotes/erpnext/issues'>GitHub Issues</a></p>\
|
||||
<hr>\
|
||||
<h2>ERPNext</h2> \
|
||||
<p><strong>v" + wn.boot.app_version + "</strong></p>\
|
||||
<p>"+wn._("An open source ERP made for the web.</p>") +
|
||||
"<p>"+wn._("To report an issue, go to ")+"<a href='https://github.com/webnotes/erpnext/issues'>GitHub Issues</a></p> \
|
||||
<p><a href='http://erpnext.org' target='_blank'>http://erpnext.org</a>.</p>\
|
||||
<p><a href='http://www.gnu.org/copyleft/gpl.html'>License: GNU General Public License Version 3</a></p>\
|
||||
<hr>\
|
||||
<p>© 2014 Web Notes Technologies Pvt. Ltd and contributers </p> \
|
||||
</div>", wn.app));
|
||||
|
||||
wn.ui.misc.about_dialog = d;
|
||||
|
||||
@@ -7,35 +7,35 @@ $.extend(erpnext.queries, {
|
||||
profile: function() {
|
||||
return { query: "core.doctype.profile.profile.profile_query" };
|
||||
},
|
||||
|
||||
|
||||
lead: function() {
|
||||
return { query: "controllers.queries.lead_query" };
|
||||
},
|
||||
|
||||
|
||||
customer: function() {
|
||||
return { query: "controllers.queries.customer_query" };
|
||||
},
|
||||
|
||||
|
||||
supplier: function() {
|
||||
return { query: "controllers.queries.supplier_query" };
|
||||
},
|
||||
|
||||
|
||||
account: function() {
|
||||
return { query: "controllers.queries.account_query" };
|
||||
},
|
||||
|
||||
|
||||
item: function() {
|
||||
return { query: "controllers.queries.item_query" };
|
||||
},
|
||||
|
||||
|
||||
bom: function() {
|
||||
return { query: "controllers.queries.bom" };
|
||||
},
|
||||
|
||||
|
||||
task: function() {
|
||||
return { query: "projects.utils.query_task" };
|
||||
},
|
||||
|
||||
|
||||
customer_filter: function(doc) {
|
||||
if(!doc.customer) {
|
||||
wn.throw(wn._("Please specify a") + " " +
|
||||
@@ -44,7 +44,7 @@ $.extend(erpnext.queries, {
|
||||
|
||||
return { filters: { customer: doc.customer } };
|
||||
},
|
||||
|
||||
|
||||
supplier_filter: function(doc) {
|
||||
if(!doc.supplier) {
|
||||
wn.throw(wn._("Please specify a") + " " +
|
||||
@@ -53,9 +53,17 @@ $.extend(erpnext.queries, {
|
||||
|
||||
return { filters: { supplier: doc.supplier } };
|
||||
},
|
||||
|
||||
|
||||
lead_filter: function(doc) {
|
||||
if(!doc.lead) {
|
||||
wn.throw(wn._("Please specify a") + " " +
|
||||
wn._(wn.meta.get_label(doc.doctype, "lead", doc.name)));
|
||||
}
|
||||
|
||||
return { filters: { lead: doc.lead } };
|
||||
},
|
||||
|
||||
not_a_group_filter: function() {
|
||||
return { filters: { is_group: "No" } };
|
||||
},
|
||||
|
||||
});
|
||||
@@ -21,6 +21,6 @@ erpnext.toolbar.setup = function() {
|
||||
<i class="icon-fixed-width icon-comments"></i> '+wn._('Live Chat')+'</a></li>');
|
||||
}
|
||||
|
||||
$("#toolbar-tools").append('<li><a href="#latest-updates">\
|
||||
$("#toolbar-tools").append('<li><a href="https://github.com/webnotes/erpnext/releases" target="_blank">\
|
||||
<i class="icon-fixed-width icon-rss"></i> Latest Updates</li>');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,6 +540,14 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
|
||||
calculate_taxes: function() {
|
||||
var me = this;
|
||||
var actual_tax_dict = {};
|
||||
|
||||
// maintain actual tax rate based on idx
|
||||
$.each(this.frm.tax_doclist, function(i, tax) {
|
||||
if (tax.charge_type == "Actual") {
|
||||
actual_tax_dict[tax.idx] = flt(tax.rate);
|
||||
}
|
||||
});
|
||||
|
||||
$.each(this.frm.item_doclist, function(n, item) {
|
||||
var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
|
||||
@@ -549,15 +557,15 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
var current_tax_amount = me.get_current_tax_amount(item, tax, item_tax_map);
|
||||
|
||||
me.set_item_tax_amount && me.set_item_tax_amount(item, tax, current_tax_amount);
|
||||
|
||||
// case when net total is 0 but there is an actual type charge
|
||||
// in this case add the actual amount to tax.tax_amount
|
||||
// and tax.grand_total_for_current_item for the first such iteration
|
||||
if(tax.charge_type == "Actual" &&
|
||||
!(current_tax_amount || me.frm.doc.net_total || tax.tax_amount)) {
|
||||
var zero_net_total_adjustment = flt(tax.rate, precision("tax_amount", tax));
|
||||
current_tax_amount += zero_net_total_adjustment;
|
||||
|
||||
// Adjust divisional loss to the last item
|
||||
if (tax.charge_type == "Actual") {
|
||||
actual_tax_dict[tax.idx] -= current_tax_amount;
|
||||
if (n == me.frm.item_doclist.length - 1) {
|
||||
current_tax_amount += actual_tax_dict[tax.idx]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// store tax_amount for current item as it will be used for
|
||||
// charge type = 'On Previous Row Amount'
|
||||
@@ -589,6 +597,11 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
|
||||
|
||||
// in tax.total, accumulate grand total for each item
|
||||
tax.total += tax.grand_total_for_current_item;
|
||||
|
||||
if (n == me.frm.item_doclist.length - 1) {
|
||||
tax.total = flt(tax.total, precision("total", tax));
|
||||
tax.tax_amount = flt(tax.tax_amount, precision("tax_amount", tax));
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,13 +1,2 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
|
||||
//--------- ONLOAD -------------
|
||||
cur_frm.cscript.onload = function(doc, cdt, cdn) {
|
||||
|
||||
}
|
||||
|
||||
cur_frm.cscript.refresh = function(doc, cdt, cdn) {
|
||||
|
||||
}
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
@@ -2,11 +2,12 @@
|
||||
{
|
||||
"creation": "2013-01-10 16:34:18",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-07-05 14:29:57",
|
||||
"modified": "2014-01-16 12:52:19",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:campaign_name",
|
||||
"description": "Keep Track of Sales Campaigns. Keep track of Leads, Quotations, Sales Order etc from Campaigns to gauge Return on Investment. ",
|
||||
"doctype": "DocType",
|
||||
|
||||
@@ -18,7 +18,7 @@ cur_frm.cscript.load_defaults = function(doc, dt, dn) {
|
||||
cur_frm.add_fetch('lead_name', 'company_name', 'customer_name');
|
||||
cur_frm.add_fetch('default_sales_partner','commission_rate','default_commission_rate');
|
||||
|
||||
cur_frm.cscript.refresh = function(doc,dt,dn) {
|
||||
cur_frm.cscript.refresh = function(doc, dt, dn) {
|
||||
cur_frm.cscript.setup_dashboard(doc);
|
||||
erpnext.hide_naming_series();
|
||||
|
||||
@@ -107,20 +107,20 @@ cur_frm.cscript.make_contact = function() {
|
||||
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['customer_group'].get_query = function(doc,dt,dn) {
|
||||
cur_frm.fields_dict['customer_group'].get_query = function(doc, dt, dn) {
|
||||
return{
|
||||
filters:{'is_group': 'No'}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cur_frm.fields_dict.lead_name.get_query = function(doc,cdt,cdn) {
|
||||
cur_frm.fields_dict.lead_name.get_query = function(doc, cdt, cdn) {
|
||||
return{
|
||||
query:"controllers.queries.lead_query"
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['default_price_list'].get_query = function(doc,cdt,cdn) {
|
||||
cur_frm.fields_dict['default_price_list'].get_query = function(doc, cdt, cdn) {
|
||||
return{
|
||||
filters:{'selling': 1}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,13 @@ erpnext.selling.Opportunity = wn.ui.form.Controller.extend({
|
||||
if(!this.frm.doc.enquiry_from)
|
||||
hide_field(['customer', 'customer_address', 'contact_person', 'customer_name','lead', 'address_display', 'contact_display', 'contact_mobile', 'contact_email', 'territory', 'customer_group']);
|
||||
if(!this.frm.doc.status)
|
||||
set_multiple(cdt,cdn,{status:'Draft'});
|
||||
set_multiple(cdt, cdn, { status:'Draft' });
|
||||
if(!this.frm.doc.date)
|
||||
this.frm.doc.transaction_date = date.obj_to_str(new Date());
|
||||
if(!this.frm.doc.company && wn.defaults.get_default("company"))
|
||||
set_multiple(cdt,cdn,{company:wn.defaults.get_default("company")});
|
||||
if(!this.frm.doc.fiscal_year && sys_defaults.fiscal_year)
|
||||
set_multiple(cdt,cdn,{fiscal_year:sys_defaults.fiscal_year});
|
||||
set_multiple(cdt, cdn, { company:wn.defaults.get_default("company") });
|
||||
if(!this.frm.doc.fiscal_year && sys_defaults.fiscal_year)
|
||||
set_multiple(cdt, cdn, { fiscal_year:sys_defaults.fiscal_year });
|
||||
|
||||
if(this.frm.doc.enquiry_from) {
|
||||
if(this.frm.doc.enquiry_from == 'Customer') {
|
||||
@@ -99,15 +99,15 @@ erpnext.selling.Opportunity = wn.ui.form.Controller.extend({
|
||||
|
||||
$.extend(cur_frm.cscript, new erpnext.selling.Opportunity({frm: cur_frm}));
|
||||
|
||||
cur_frm.cscript.refresh = function(doc, cdt, cdn){
|
||||
cur_frm.cscript.refresh = function(doc, cdt, cdn) {
|
||||
erpnext.hide_naming_series();
|
||||
cur_frm.clear_custom_buttons();
|
||||
|
||||
if(doc.docstatus === 1 && doc.status!=="Lost") {
|
||||
cur_frm.add_custom_button(wn._('Create Quotation'), cur_frm.cscript.create_quotation);
|
||||
if(doc.status!=="Quotation") {
|
||||
if(doc.status!=="Quotation")
|
||||
cur_frm.add_custom_button(wn._('Opportunity Lost'), cur_frm.cscript['Declare Opportunity Lost']);
|
||||
}
|
||||
|
||||
cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript.send_sms, "icon-mobile-phone");
|
||||
}
|
||||
|
||||
@@ -116,31 +116,29 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn){
|
||||
}
|
||||
|
||||
cur_frm.cscript.onload_post_render = function(doc, cdt, cdn) {
|
||||
if(doc.enquiry_from == 'Lead' && doc.lead) {
|
||||
cur_frm.cscript.lead(doc,cdt,cdn);
|
||||
}
|
||||
if(doc.enquiry_from == 'Lead' && doc.lead)
|
||||
cur_frm.cscript.lead(doc, cdt, cdn);
|
||||
}
|
||||
|
||||
cur_frm.cscript.item_code = function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
if (d.item_code) {
|
||||
return get_server_fields('get_item_details',d.item_code, 'enquiry_details',doc, cdt,cdn,1);
|
||||
}
|
||||
if (d.item_code)
|
||||
return get_server_fields('get_item_details', d.item_code, 'enquiry_details', doc, cdt, cdn, 1);
|
||||
}
|
||||
|
||||
// hide - unhide fields on basis of enquiry_from lead or customer
|
||||
cur_frm.cscript.enquiry_from = function(doc,cdt,cdn){
|
||||
cur_frm.cscript.lead_cust_show(doc,cdt,cdn);
|
||||
cur_frm.cscript.enquiry_from = function(doc, cdt, cdn) {
|
||||
cur_frm.cscript.lead_cust_show(doc, cdt, cdn);
|
||||
}
|
||||
|
||||
// hide - unhide fields based on lead or customer
|
||||
cur_frm.cscript.lead_cust_show = function(doc,cdt,cdn){
|
||||
if(doc.enquiry_from == 'Lead'){
|
||||
cur_frm.cscript.lead_cust_show = function(doc, cdt, cdn) {
|
||||
if(doc.enquiry_from == 'Lead') {
|
||||
unhide_field(['lead']);
|
||||
hide_field(['customer','customer_address','contact_person','customer_name','address_display','contact_display','contact_mobile','contact_email','territory','customer_group']);
|
||||
doc.lead = doc.customer = doc.customer_address = doc.contact_person = doc.address_display = doc.contact_display = doc.contact_mobile = doc.contact_email = doc.territory = doc.customer_group = "";
|
||||
}
|
||||
else if(doc.enquiry_from == 'Customer'){
|
||||
else if(doc.enquiry_from == 'Customer') {
|
||||
unhide_field(['customer']);
|
||||
hide_field(['lead', 'address_display', 'contact_display', 'contact_mobile',
|
||||
'contact_email', 'territory', 'customer_group']);
|
||||
@@ -164,15 +162,13 @@ cur_frm.cscript.lead = function(doc, cdt, cdn) {
|
||||
wn.model.map_current_doc({
|
||||
method: "selling.doctype.lead.lead.make_opportunity",
|
||||
source_name: cur_frm.doc.lead
|
||||
})
|
||||
});
|
||||
|
||||
unhide_field(['customer_name', 'address_display','contact_mobile', 'customer_address',
|
||||
'contact_email', 'territory']);
|
||||
'contact_email', 'territory']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
cur_frm.cscript['Declare Opportunity Lost'] = function(){
|
||||
cur_frm.cscript['Declare Opportunity Lost'] = function() {
|
||||
var dialog = new wn.ui.Dialog({
|
||||
title: wn._("Set as Lost"),
|
||||
fields: [
|
||||
@@ -200,5 +196,4 @@ cur_frm.cscript['Declare Opportunity Lost'] = function(){
|
||||
})
|
||||
});
|
||||
dialog.show();
|
||||
|
||||
}
|
||||
@@ -15,12 +15,21 @@ wn.require('app/accounts/doctype/sales_invoice/pos.js');
|
||||
|
||||
erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
|
||||
onload: function(doc, dt, dn) {
|
||||
var me = this;
|
||||
this._super(doc, dt, dn);
|
||||
if(doc.customer && !doc.quotation_to)
|
||||
doc.quotation_to = "Customer";
|
||||
else if(doc.lead && !doc.quotation_to)
|
||||
doc.quotation_to = "Lead";
|
||||
|
||||
|
||||
// to overwrite the customer_filter trigger from queries.js
|
||||
if (doc.lead) {
|
||||
$.each(["customer_address", "shipping_address_name"],
|
||||
function(i, opts) {
|
||||
me.frm.set_query(opts, erpnext.queries["lead_filter"]);
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
refresh: function(doc, dt, dn) {
|
||||
this._super(doc, dt, dn);
|
||||
@@ -68,6 +77,12 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
|
||||
quotation_to: function() {
|
||||
this.frm.toggle_reqd("lead", this.frm.doc.quotation_to == "Lead");
|
||||
this.frm.toggle_reqd("customer", this.frm.doc.quotation_to == "Customer");
|
||||
if (this.frm.doc.quotation_to == "Lead") {
|
||||
this.frm.set_value("customer", null);
|
||||
this.frm.set_value("contact_person", null);
|
||||
}
|
||||
else if (this.frm.doc.quotation_to == "Customer")
|
||||
this.frm.set_value("lead", null);
|
||||
},
|
||||
|
||||
tc_name: function() {
|
||||
@@ -89,7 +104,7 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
|
||||
|
||||
cur_frm.script_manager.make(erpnext.selling.QuotationController);
|
||||
|
||||
cur_frm.fields_dict.lead.get_query = function(doc,cdt,cdn) {
|
||||
cur_frm.fields_dict.lead.get_query = function(doc, cdt, cdn) {
|
||||
return{ query:"controllers.queries.lead_query" } }
|
||||
|
||||
cur_frm.cscript.lead = function(doc, cdt, cdn) {
|
||||
@@ -152,7 +167,6 @@ cur_frm.cscript['Declare Order Lost'] = function(){
|
||||
}
|
||||
|
||||
cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
|
||||
if(cint(wn.boot.notification_settings.quotation)) {
|
||||
if(cint(wn.boot.notification_settings.quotation))
|
||||
cur_frm.email_doc(wn.boot.notification_settings.quotation_message);
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,10 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.utils import cstr
|
||||
from webnotes.model.bean import getlist
|
||||
from webnotes.model.code import get_obj
|
||||
from webnotes import _, msgprint
|
||||
|
||||
|
||||
|
||||
from controllers.selling_controller import SellingController
|
||||
|
||||
class DocType(SellingController):
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-24 19:29:08",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-12-14 17:25:46",
|
||||
"modified": "2014-01-29 19:42:32",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@@ -665,6 +665,7 @@
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.customer",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "contact_person",
|
||||
"fieldtype": "Link",
|
||||
|
||||
@@ -10,11 +10,12 @@ no_cache = True
|
||||
def get_context():
|
||||
from portal.utils import get_transaction_context
|
||||
context = get_transaction_context("Sales Order", webnotes.form_dict.name)
|
||||
modify_status(context.get("doc"))
|
||||
context.update({
|
||||
"parent_link": "orders",
|
||||
"parent_title": "My Orders"
|
||||
})
|
||||
if context.get("doc").get("name") != "Not Allowed":
|
||||
modify_status(context.get("doc"))
|
||||
context.update({
|
||||
"parent_link": "orders",
|
||||
"parent_title": "My Orders"
|
||||
})
|
||||
return context
|
||||
|
||||
def modify_status(doc):
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import msgprint, _, throw
|
||||
from webnotes.utils import flt, cint, comma_and
|
||||
from webnotes import _, throw
|
||||
from webnotes.utils import flt, cint
|
||||
import json
|
||||
|
||||
def get_customer_list(doctype, txt, searchfield, start, page_len, filters):
|
||||
@@ -121,10 +121,16 @@ def _validate_item_details(args, item):
|
||||
def _get_basic_details(args, item_bean, warehouse_fieldname):
|
||||
item = item_bean.doc
|
||||
|
||||
from webnotes.defaults import get_user_default_as_list
|
||||
user_default_warehouse_list = get_user_default_as_list('warehouse')
|
||||
user_default_warehouse = user_default_warehouse_list[0] \
|
||||
if len(user_default_warehouse_list)==1 else ""
|
||||
|
||||
out = webnotes._dict({
|
||||
"item_code": item.name,
|
||||
"description": item.description_html or item.description,
|
||||
warehouse_fieldname: item.default_warehouse or args.get(warehouse_fieldname),
|
||||
warehouse_fieldname: user_default_warehouse or item.default_warehouse \
|
||||
or args.get(warehouse_fieldname),
|
||||
"income_account": item.default_income_account or args.income_account \
|
||||
or webnotes.conn.get_value("Company", args.company, "default_income_account"),
|
||||
"expense_account": item.purchase_account or args.expense_account \
|
||||
@@ -144,8 +150,10 @@ def _get_basic_details(args, item_bean, warehouse_fieldname):
|
||||
return out
|
||||
|
||||
def _get_price_list_rate(args, item_bean, meta):
|
||||
ref_rate = webnotes.conn.sql("""select ref_rate from `tabItem Price`
|
||||
where price_list=%s and item_code=%s and selling=1""",
|
||||
ref_rate = webnotes.conn.sql("""select ip.ref_rate from
|
||||
`tabItem Price` ip, `tabPrice List` pl
|
||||
where ip.price_list=pl.name and ip.price_list=%s and
|
||||
ip.item_code=%s and ip.selling=1 and pl.enabled=1""",
|
||||
(args.selling_price_list, args.item_code), as_dict=1)
|
||||
|
||||
if not ref_rate:
|
||||
|
||||
@@ -282,7 +282,7 @@ def apply_cart_settings(party=None, quotation=None):
|
||||
party = get_lead_or_customer()
|
||||
if not quotation:
|
||||
quotation = _get_cart_quotation(party)
|
||||
|
||||
|
||||
cart_settings = webnotes.get_obj("Shopping Cart Settings")
|
||||
|
||||
billing_territory = get_address_territory(quotation.doc.customer_address) or \
|
||||
@@ -310,7 +310,8 @@ def set_price_list_and_rate(quotation, cart_settings, billing_territory):
|
||||
quotation.run_method("set_price_list_and_item_details")
|
||||
|
||||
# set it in cookies for using in product page
|
||||
webnotes.local._response.set_cookie("selling_price_list", quotation.doc.selling_price_list)
|
||||
if quotation.doc.selling_price_list:
|
||||
webnotes.local._response.set_cookie("selling_price_list", quotation.doc.selling_price_list)
|
||||
|
||||
def set_taxes(quotation, cart_settings, billing_territory):
|
||||
"""set taxes based on billing territory"""
|
||||
|
||||
@@ -27,8 +27,9 @@ def get_product_info(item_code):
|
||||
else:
|
||||
in_stock = -1
|
||||
|
||||
price = price_list and webnotes.conn.sql("""select ref_rate, currency from
|
||||
`tabItem Price` where item_code=%s and price_list=%s""",
|
||||
price = price_list and webnotes.conn.sql("""select ip.ref_rate, ip.currency from
|
||||
`tabItem Price` ip, `tabPrice List` pl where ip.price_list=pl.name and
|
||||
ip.item_code=%s and ip.price_list=%s and pl.enabled=1""",
|
||||
(item_code, price_list), as_dict=1) or []
|
||||
|
||||
price = price and price[0] or None
|
||||
|
||||
@@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _, msgprint
|
||||
|
||||
from webnotes.utils import cstr
|
||||
from webnotes.utils import cstr, cint
|
||||
import webnotes.defaults
|
||||
|
||||
|
||||
@@ -237,21 +237,24 @@ class DocType:
|
||||
account.insert()
|
||||
|
||||
def set_default_accounts(self):
|
||||
accounts = {
|
||||
"default_income_account": "Sales",
|
||||
"default_expense_account": "Cost of Goods Sold",
|
||||
def _set_default_accounts(accounts):
|
||||
for a in accounts:
|
||||
account_name = accounts[a] + " - " + self.doc.abbr
|
||||
if not self.doc.fields.get(a) and webnotes.conn.exists("Account", account_name):
|
||||
webnotes.conn.set(self.doc, a, account_name)
|
||||
|
||||
_set_default_accounts({
|
||||
"receivables_group": "Accounts Receivable",
|
||||
"payables_group": "Accounts Payable",
|
||||
"default_cash_account": "Cash",
|
||||
"stock_received_but_not_billed": "Stock Received But Not Billed",
|
||||
"stock_adjustment_account": "Stock Adjustment",
|
||||
"expenses_included_in_valuation": "Expenses Included In Valuation"
|
||||
}
|
||||
"default_cash_account": "Cash"
|
||||
})
|
||||
|
||||
for a in accounts:
|
||||
account_name = accounts[a] + " - " + self.doc.abbr
|
||||
if not self.doc.fields.get(a) and webnotes.conn.exists("Account", account_name):
|
||||
webnotes.conn.set(self.doc, a, account_name)
|
||||
if cint(webnotes.conn.get_value("Accounts Settings", None, "auto_accounting_for_stock")):
|
||||
_set_default_accounts({
|
||||
"stock_received_but_not_billed": "Stock Received But Not Billed",
|
||||
"stock_adjustment_account": "Stock Adjustment",
|
||||
"expenses_included_in_valuation": "Expenses Included In Valuation"
|
||||
})
|
||||
|
||||
def create_default_cost_center(self):
|
||||
cc_list = [
|
||||
|
||||
@@ -98,6 +98,7 @@ def create_price_lists(args):
|
||||
{
|
||||
"doctype": "Price List",
|
||||
"price_list_name": "Standard " + pl_type,
|
||||
"enabled": 1,
|
||||
"buying": 1 if pl_type == "Buying" else 0,
|
||||
"selling": 1 if pl_type == "Selling" else 0,
|
||||
"currency": args["currency"]
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _, msgprint
|
||||
from webnotes import _, msgprint, throw
|
||||
import json
|
||||
|
||||
def get_company_currency(company):
|
||||
@@ -11,8 +11,8 @@ def get_company_currency(company):
|
||||
if not currency:
|
||||
currency = webnotes.conn.get_default("currency")
|
||||
if not currency:
|
||||
msgprint(_('Please specify Default Currency in Company Master \
|
||||
and Global Defaults'), raise_exception=True)
|
||||
throw(_('Please specify Default Currency in Company Master \
|
||||
and Global Defaults'))
|
||||
|
||||
return currency
|
||||
|
||||
@@ -32,5 +32,14 @@ def get_ancestors_of(doctype, name):
|
||||
|
||||
@webnotes.whitelist()
|
||||
def get_price_list_currency(price_list):
|
||||
return {"price_list_currency": webnotes.conn.get_value("Price List", price_list,
|
||||
"currency")}
|
||||
price_list_currency = webnotes.conn.get_value("Price List", {"name": price_list,
|
||||
"enabled": 1}, "currency")
|
||||
|
||||
if not price_list_currency:
|
||||
throw("{message}: {price_list} {disabled}".format(**{
|
||||
"message": _("Price List"),
|
||||
"price_list": price_list,
|
||||
"disabled": _("is disabled.")
|
||||
}))
|
||||
else:
|
||||
return {"price_list_currency": price_list_currency}
|
||||
@@ -70,6 +70,6 @@ def on_build():
|
||||
|
||||
def comment_added(doc):
|
||||
"""add comment to feed"""
|
||||
home.make_feed('Comment', doc.comment_doctype, doc.comment_docname, doc.comment_by,
|
||||
'<i>"' + doc.comment + '"</i>', '#6B24B3')
|
||||
home.make_feed('Comment', doc.comment_doctype, doc.comment_docname,
|
||||
doc.comment_by or doc.owner, '<i>"' + doc.comment + '"</i>', '#6B24B3')
|
||||
|
||||
|
||||
@@ -29,10 +29,7 @@ cur_frm.cscript.make_dashboard = function() {
|
||||
|
||||
cur_frm.cscript.edit_prices_button = function() {
|
||||
cur_frm.add_custom_button("Add / Edit Prices", function() {
|
||||
wn.route_options = {
|
||||
"item_code": cur_frm.doc.name
|
||||
};
|
||||
wn.set_route("Report", "Item Price");
|
||||
wn.set_route("Report", "Item Price", {"item_code": cur_frm.doc.name});
|
||||
}, "icon-money");
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ test_records = [
|
||||
"stock_uom": "_Test UOM",
|
||||
"default_income_account": "Sales - _TC",
|
||||
"default_warehouse": "_Test Warehouse - _TC",
|
||||
"purchase_account": "_Test Account Cost for Goods Sold - _TC"
|
||||
}, {
|
||||
"doctype": "Item Reorder",
|
||||
"parentfield": "item_reorder",
|
||||
@@ -64,6 +65,7 @@ test_records = [
|
||||
"stock_uom": "_Test UOM",
|
||||
"default_income_account": "Sales - _TC",
|
||||
"default_warehouse": "_Test Warehouse - _TC",
|
||||
"purchase_account": "_Test Account Cost for Goods Sold - _TC"
|
||||
}],
|
||||
[{
|
||||
"doctype": "Item",
|
||||
@@ -73,6 +75,7 @@ test_records = [
|
||||
"item_group": "_Test Item Group Desktops",
|
||||
"default_warehouse": "_Test Warehouse - _TC",
|
||||
"default_income_account": "Sales - _TC",
|
||||
"purchase_account": "_Test Account Cost for Goods Sold - _TC",
|
||||
"is_stock_item": "Yes",
|
||||
"is_asset_item": "No",
|
||||
"has_batch_no": "No",
|
||||
@@ -99,6 +102,7 @@ test_records = [
|
||||
"item_group": "_Test Item Group Desktops",
|
||||
"default_warehouse": "_Test Warehouse - _TC",
|
||||
"default_income_account": "Sales - _TC",
|
||||
"purchase_account": "_Test Account Cost for Goods Sold - _TC",
|
||||
"is_stock_item": "Yes",
|
||||
"is_asset_item": "No",
|
||||
"has_batch_no": "No",
|
||||
@@ -119,6 +123,7 @@ test_records = [
|
||||
"description": "_Test Sales BOM Item",
|
||||
"item_group": "_Test Item Group Desktops",
|
||||
"default_income_account": "Sales - _TC",
|
||||
"purchase_account": "_Test Account Cost for Goods Sold - _TC",
|
||||
"is_stock_item": "No",
|
||||
"is_asset_item": "No",
|
||||
"has_batch_no": "No",
|
||||
@@ -140,6 +145,7 @@ test_records = [
|
||||
"is_stock_item": "Yes",
|
||||
"default_warehouse": "_Test Warehouse - _TC",
|
||||
"default_income_account": "Sales - _TC",
|
||||
"purchase_account": "_Test Account Cost for Goods Sold - _TC",
|
||||
"is_asset_item": "No",
|
||||
"has_batch_no": "No",
|
||||
"has_serial_no": "No",
|
||||
@@ -216,6 +222,7 @@ test_records = [
|
||||
"item_group": "_Test Item Group Desktops",
|
||||
"default_warehouse": "_Test Warehouse - _TC",
|
||||
"default_income_account": "Sales - _TC",
|
||||
"purchase_account": "_Test Account Cost for Goods Sold - _TC",
|
||||
"is_stock_item": "Yes",
|
||||
"is_asset_item": "No",
|
||||
"has_batch_no": "No",
|
||||
@@ -238,6 +245,7 @@ test_records = [
|
||||
"is_stock_item": "Yes",
|
||||
"default_warehouse": "_Test Warehouse - _TC",
|
||||
"default_income_account": "Sales - _TC",
|
||||
"purchase_account": "_Test Account Cost for Goods Sold - _TC",
|
||||
"is_asset_item": "No",
|
||||
"has_batch_no": "No",
|
||||
"has_serial_no": "No",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _
|
||||
from webnotes import throw, _
|
||||
|
||||
class ItemPriceDuplicateItem(webnotes.ValidationError): pass
|
||||
|
||||
@@ -12,26 +12,36 @@ class DocType:
|
||||
self.doc, self.doclist = d, dl
|
||||
|
||||
def validate(self):
|
||||
self.validate_price_list()
|
||||
self.check_duplicate_item()
|
||||
self.update_price_list_details()
|
||||
self.update_item_details()
|
||||
|
||||
def update_price_list_details(self):
|
||||
self.doc.buying, self.doc.selling, self.doc.currency = webnotes.conn.get_value("Price List",
|
||||
self.doc.price_list, ["buying", "selling", "currency"])
|
||||
|
||||
def update_item_details(self):
|
||||
self.doc.item_name, self.doc.item_description = webnotes.conn.get_value("Item",
|
||||
self.doc.item_code, ["item_name", "description"])
|
||||
def validate_price_list(self):
|
||||
enabled = webnotes.conn.get_value("Price List", self.doc.price_list, "enabled")
|
||||
if not enabled:
|
||||
throw("{message}: {price_list} {disabled}".format(**{
|
||||
"message": _("Price List"),
|
||||
"price_list": self.doc.price_list,
|
||||
"disabled": _("is disabled.")
|
||||
}))
|
||||
|
||||
def check_duplicate_item(self):
|
||||
if webnotes.conn.sql("""select name from `tabItem Price`
|
||||
where item_code=%s and price_list=%s and name!=%s""",
|
||||
(self.doc.item_code, self.doc.price_list, self.doc.name)):
|
||||
webnotes.throw("{duplicate_item}: {item_code}, {already}: {price_list}".format(**{
|
||||
throw("{duplicate_item}: {item_code}, {already}: {price_list}".format(**{
|
||||
"duplicate_item": _("Duplicate Item"),
|
||||
"item_code": self.doc.item_code,
|
||||
"already": _("already available in Price List"),
|
||||
"price_list": self.doc.price_list
|
||||
}), ItemPriceDuplicateItem)
|
||||
|
||||
def update_price_list_details(self):
|
||||
self.doc.buying, self.doc.selling, self.doc.currency = webnotes.conn.get_value("Price List",
|
||||
{"name": self.doc.price_list, "enabled": 1}, ["buying", "selling", "currency"])
|
||||
|
||||
def update_item_details(self):
|
||||
self.doc.item_name, self.doc.item_description = webnotes.conn.get_value("Item",
|
||||
self.doc.item_code, ["item_name", "description"])
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-01-25 11:35:09",
|
||||
"docstatus": 0,
|
||||
"modified": "2014-01-06 18:28:23",
|
||||
"modified": "2014-01-27 11:11:08",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@@ -11,6 +11,7 @@
|
||||
"allow_copy": 0,
|
||||
"allow_email": 1,
|
||||
"allow_print": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:price_list_name",
|
||||
"description": "Price List Master",
|
||||
"doctype": "DocType",
|
||||
@@ -42,6 +43,18 @@
|
||||
"doctype": "DocType",
|
||||
"name": "Price List"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "enabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enabled"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "sb_1",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "price_list_name",
|
||||
|
||||
@@ -11,6 +11,7 @@ test_records = [
|
||||
{
|
||||
"doctype": "Price List",
|
||||
"price_list_name": "_Test Price List",
|
||||
"enabled": 1,
|
||||
"currency": "INR",
|
||||
"selling": 1
|
||||
},
|
||||
@@ -24,6 +25,7 @@ test_records = [
|
||||
{
|
||||
"doctype": "Price List",
|
||||
"price_list_name": "_Test Price List 2",
|
||||
"enabled": 1,
|
||||
"currency": "INR",
|
||||
"selling": 1
|
||||
},
|
||||
@@ -37,6 +39,7 @@ test_records = [
|
||||
{
|
||||
"doctype": "Price List",
|
||||
"price_list_name": "_Test Price List India",
|
||||
"enabled": 1,
|
||||
"currency": "INR",
|
||||
"selling": 1
|
||||
},
|
||||
@@ -50,6 +53,7 @@ test_records = [
|
||||
{
|
||||
"doctype": "Price List",
|
||||
"price_list_name": "_Test Price List Rest of the World",
|
||||
"enabled": 1,
|
||||
"currency": "USD",
|
||||
"selling": 1
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-24 19:29:10",
|
||||
"docstatus": 0,
|
||||
"modified": "2014-01-03 18:28:20",
|
||||
"modified": "2014-01-15 16:00:44",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@@ -336,7 +336,7 @@
|
||||
},
|
||||
{
|
||||
"default": ":Company",
|
||||
"depends_on": "eval:sys_defaults.auto_accounting_for_stock",
|
||||
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "cost_center",
|
||||
"fieldtype": "Link",
|
||||
|
||||
@@ -94,6 +94,8 @@ class DocType(StockController):
|
||||
self.doc.status = "Delivered"
|
||||
else:
|
||||
self.doc.status = "Not Available"
|
||||
else:
|
||||
self.doc.status = "Not Available"
|
||||
|
||||
def set_purchase_details(self, purchase_sle):
|
||||
if purchase_sle:
|
||||
@@ -185,10 +187,9 @@ class DocType(StockController):
|
||||
def on_stock_ledger_entry(self):
|
||||
if self.via_stock_ledger and not self.doc.fields.get("__islocal"):
|
||||
last_sle = self.get_last_sle()
|
||||
if last_sle:
|
||||
self.set_status(last_sle.get("last_sle"))
|
||||
self.set_purchase_details(last_sle.get("purchase_sle"))
|
||||
self.set_sales_details(last_sle.get("delivery_sle"))
|
||||
self.set_status(last_sle.get("last_sle"))
|
||||
self.set_purchase_details(last_sle.get("purchase_sle"))
|
||||
self.set_sales_details(last_sle.get("delivery_sle"))
|
||||
|
||||
def on_communication(self):
|
||||
return
|
||||
|
||||
@@ -346,7 +346,8 @@ class DocType(StockController):
|
||||
pro_bean = webnotes.bean("Production Order", self.doc.production_order)
|
||||
_validate_production_order(pro_bean)
|
||||
self.update_produced_qty(pro_bean)
|
||||
self.update_planned_qty(pro_bean)
|
||||
if self.doc.purpose == "Manufacture/Repack":
|
||||
self.update_planned_qty(pro_bean)
|
||||
|
||||
def update_produced_qty(self, pro_bean):
|
||||
if self.doc.purpose == "Manufacture/Repack":
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-03-29 18:22:12",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-11-08 16:15:44",
|
||||
"modified": "2014-01-15 16:08:45",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@@ -165,7 +165,7 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:sys_defaults.auto_accounting_for_stock",
|
||||
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "expense_account",
|
||||
"fieldtype": "Link",
|
||||
@@ -175,7 +175,7 @@
|
||||
},
|
||||
{
|
||||
"default": ":Company",
|
||||
"depends_on": "eval:sys_defaults.auto_accounting_for_stock",
|
||||
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "cost_center",
|
||||
"fieldtype": "Link",
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import msgprint
|
||||
from webnotes.utils import flt, getdate
|
||||
from webnotes.utils import flt, getdate, add_days
|
||||
from webnotes.model.controller import DocListController
|
||||
from datetime import date
|
||||
|
||||
class StockFreezeError(webnotes.ValidationError): pass
|
||||
|
||||
class DocType(DocListController):
|
||||
def __init__(self, doc, doclist=[]):
|
||||
@@ -19,30 +23,30 @@ class DocType(DocListController):
|
||||
validate_warehouse_user(self.doc.warehouse)
|
||||
validate_warehouse_company(self.doc.warehouse, self.doc.company)
|
||||
self.scrub_posting_time()
|
||||
|
||||
|
||||
from accounts.utils import validate_fiscal_year
|
||||
validate_fiscal_year(self.doc.posting_date, self.doc.fiscal_year, self.meta.get_label("posting_date"))
|
||||
|
||||
|
||||
def on_submit(self):
|
||||
self.check_stock_frozen_date()
|
||||
self.actual_amt_check()
|
||||
|
||||
|
||||
from stock.doctype.serial_no.serial_no import process_serial_no
|
||||
process_serial_no(self.doc)
|
||||
|
||||
|
||||
#check for item quantity available in stock
|
||||
def actual_amt_check(self):
|
||||
if self.doc.batch_no:
|
||||
batch_bal_after_transaction = flt(webnotes.conn.sql("""select sum(actual_qty)
|
||||
from `tabStock Ledger Entry`
|
||||
where warehouse=%s and item_code=%s and batch_no=%s""",
|
||||
batch_bal_after_transaction = 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])
|
||||
|
||||
|
||||
if batch_bal_after_transaction < 0:
|
||||
self.doc.fields.update({
|
||||
'batch_bal': batch_bal_after_transaction - self.doc.actual_qty
|
||||
})
|
||||
|
||||
|
||||
webnotes.throw("""Not enough quantity (requested: %(actual_qty)s, \
|
||||
current: %(batch_bal)s in Batch <b>%(batch_no)s</b> for Item \
|
||||
<b>%(item_code)s</b> at Warehouse <b>%(warehouse)s</b> \
|
||||
@@ -60,41 +64,49 @@ class DocType(DocListController):
|
||||
msgprint("Warehouse: '%s' does not exist in the system. Please check." % self.doc.fields.get(k), raise_exception = 1)
|
||||
|
||||
def validate_item(self):
|
||||
item_det = webnotes.conn.sql("""select name, has_batch_no, docstatus,
|
||||
is_stock_item, has_serial_no, serial_no_series
|
||||
from tabItem where name=%s""",
|
||||
item_det = webnotes.conn.sql("""select name, has_batch_no, docstatus,
|
||||
is_stock_item, has_serial_no, serial_no_series
|
||||
from tabItem where name=%s""",
|
||||
self.doc.item_code, as_dict=True)[0]
|
||||
|
||||
if item_det.is_stock_item != 'Yes':
|
||||
webnotes.throw("""Item: "%s" is not a Stock Item.""" % self.doc.item_code)
|
||||
|
||||
|
||||
# check if batch number is required
|
||||
if item_det.has_batch_no =='Yes' and self.doc.voucher_type != 'Stock Reconciliation':
|
||||
if not self.doc.batch_no:
|
||||
webnotes.throw("Batch number is mandatory for Item '%s'" % self.doc.item_code)
|
||||
|
||||
|
||||
# check if batch belongs to item
|
||||
if not webnotes.conn.sql("""select name from `tabBatch`
|
||||
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)):
|
||||
webnotes.throw("'%s' is not a valid Batch Number for Item '%s'" % (self.doc.batch_no, self.doc.item_code))
|
||||
|
||||
|
||||
if not self.doc.stock_uom:
|
||||
self.doc.stock_uom = item_det.stock_uom
|
||||
|
||||
|
||||
def check_stock_frozen_date(self):
|
||||
stock_frozen_upto = webnotes.conn.get_value('Stock Settings', None, 'stock_frozen_upto') or ''
|
||||
if stock_frozen_upto:
|
||||
stock_auth_role = webnotes.conn.get_value('Stock Settings', None,'stock_auth_role')
|
||||
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)
|
||||
msgprint("You are not authorized to do / modify back dated stock entries before %s" % getdate(stock_frozen_upto).strftime('%d-%m-%Y'), raise_exception=StockFreezeError)
|
||||
|
||||
stock_frozen_upto_days = int(webnotes.conn.get_value('Stock Settings', None, 'stock_frozen_upto_days') or 0)
|
||||
if stock_frozen_upto_days:
|
||||
stock_auth_role = webnotes.conn.get_value('Stock Settings', None,'stock_auth_role')
|
||||
older_than_x_days_ago = (add_days(getdate(self.doc.posting_date), stock_frozen_upto_days) <= date.today())
|
||||
if older_than_x_days_ago and not stock_auth_role in webnotes.user.get_roles():
|
||||
msgprint("You are not authorized to do / modify back dated stock entries older than %d days ago" %stock_frozen_upto_days, raise_exception=StockFreezeError)
|
||||
|
||||
|
||||
def scrub_posting_time(self):
|
||||
if not self.doc.posting_time or self.doc.posting_time == '00:0':
|
||||
self.doc.posting_time = '00:00'
|
||||
|
||||
def on_doctype_update():
|
||||
if not webnotes.conn.sql("""show index from `tabStock Ledger Entry`
|
||||
if not webnotes.conn.sql("""show index from `tabStock Ledger Entry`
|
||||
where Key_name="posting_sort_index" """):
|
||||
webnotes.conn.commit()
|
||||
webnotes.conn.sql("""alter table `tabStock Ledger Entry`
|
||||
webnotes.conn.sql("""alter table `tabStock Ledger Entry`
|
||||
add index posting_sort_index(posting_date, posting_time, name)""")
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-03-28 10:35:31",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-09-24 15:35:12",
|
||||
"modified": "2014-01-15 15:45:07",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@@ -102,7 +102,7 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:sys_defaults.auto_accounting_for_stock",
|
||||
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "expense_account",
|
||||
"fieldtype": "Link",
|
||||
@@ -110,6 +110,7 @@
|
||||
"options": "Account"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "cost_center",
|
||||
"fieldtype": "Link",
|
||||
|
||||
@@ -5,18 +5,23 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes import _
|
||||
|
||||
class DocType:
|
||||
def __init__(self, d, dl):
|
||||
self.doc, self.doclist = d, dl
|
||||
|
||||
|
||||
def validate(self):
|
||||
for key in ["item_naming_by", "item_group", "stock_uom",
|
||||
for key in ["item_naming_by", "item_group", "stock_uom",
|
||||
"allow_negative_stock"]:
|
||||
webnotes.conn.set_default(key, self.doc.fields.get(key, ""))
|
||||
|
||||
|
||||
from setup.doctype.naming_series.naming_series import set_by_naming_series
|
||||
set_by_naming_series("Item", "item_code",
|
||||
set_by_naming_series("Item", "item_code",
|
||||
self.doc.get("item_naming_by")=="Naming Series", hide_name_field=True)
|
||||
|
||||
|
||||
stock_frozen_limit = 356
|
||||
submitted_stock_frozen = self.doc.stock_frozen_upto_days
|
||||
if submitted_stock_frozen > stock_frozen_limit:
|
||||
self.doc.stock_frozen_upto_days = stock_frozen_limit
|
||||
webnotes.msgprint (_("`Freeze Stocks Older Than` should be smaller than %d days.") %stock_frozen_limit)
|
||||
|
||||
@@ -1,128 +1,134 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-06-24 16:37:54",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-11-02 19:41:56",
|
||||
"modified_by": "Administrator",
|
||||
"creation": "2013-06-24 16:37:54",
|
||||
"docstatus": 0,
|
||||
"modified": "2014-01-27 20:00:56",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "Settings",
|
||||
"doctype": "DocType",
|
||||
"icon": "icon-cog",
|
||||
"issingle": 1,
|
||||
"module": "Stock",
|
||||
"description": "Settings",
|
||||
"doctype": "DocType",
|
||||
"icon": "icon-cog",
|
||||
"issingle": 1,
|
||||
"module": "Stock",
|
||||
"name": "__common__"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"name": "__common__",
|
||||
"parent": "Stock Settings",
|
||||
"parentfield": "fields",
|
||||
"parenttype": "DocType",
|
||||
"doctype": "DocField",
|
||||
"name": "__common__",
|
||||
"parent": "Stock Settings",
|
||||
"parentfield": "fields",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0
|
||||
},
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"name": "__common__",
|
||||
"parent": "Stock Settings",
|
||||
"parentfield": "permissions",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0,
|
||||
"read": 1,
|
||||
"role": "Material Manager",
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"name": "__common__",
|
||||
"parent": "Stock Settings",
|
||||
"parentfield": "permissions",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0,
|
||||
"read": 1,
|
||||
"role": "Material Manager",
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"doctype": "DocType",
|
||||
"name": "Stock Settings"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "item_naming_by",
|
||||
"fieldtype": "Select",
|
||||
"label": "Item Naming By",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "item_naming_by",
|
||||
"fieldtype": "Select",
|
||||
"label": "Item Naming By",
|
||||
"options": "Item Code\nNaming Series"
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "<a href=\"#Sales Browser/Item Group\">Add / Edit</a>",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "item_group",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Item Group",
|
||||
"description": "<a href=\"#Sales Browser/Item Group\">Add / Edit</a>",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "item_group",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Item Group",
|
||||
"options": "Item Group"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Stock UOM",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "Default Stock UOM",
|
||||
"options": "UOM"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "column_break_4",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "allow_negative_stock",
|
||||
"fieldtype": "Check",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "allow_negative_stock",
|
||||
"fieldtype": "Check",
|
||||
"label": "Allow Negative Stock"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "valuation_method",
|
||||
"fieldtype": "Select",
|
||||
"label": "Default Valuation Method",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "valuation_method",
|
||||
"fieldtype": "Select",
|
||||
"label": "Default Valuation Method",
|
||||
"options": "FIFO\nMoving Average"
|
||||
},
|
||||
},
|
||||
{
|
||||
"description": "Percentage you are allowed to receive or deliver more against the quantity ordered. For example: If you have ordered 100 units. and your Allowance is 10% then you are allowed to receive 110 units.",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "tolerance",
|
||||
"fieldtype": "Float",
|
||||
"description": "Percentage you are allowed to receive or deliver more against the quantity ordered. For example: If you have ordered 100 units. and your Allowance is 10% then you are allowed to receive 110 units.",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "tolerance",
|
||||
"fieldtype": "Float",
|
||||
"label": "Allowance Percent"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "auto_material_request",
|
||||
"fieldtype": "Section Break",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "auto_material_request",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Auto Material Request"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "auto_indent",
|
||||
"fieldtype": "Check",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "auto_indent",
|
||||
"fieldtype": "Check",
|
||||
"label": "Raise Material Request when stock reaches re-order level"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "reorder_email_notify",
|
||||
"fieldtype": "Check",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "reorder_email_notify",
|
||||
"fieldtype": "Check",
|
||||
"label": "Notify by Email on creation of automatic Material Request"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "freeze_stock_entries",
|
||||
"fieldtype": "Section Break",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "freeze_stock_entries",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Freeze Stock Entries"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "stock_frozen_upto",
|
||||
"fieldtype": "Date",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "stock_frozen_upto",
|
||||
"fieldtype": "Date",
|
||||
"label": "Stock Frozen Upto"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "stock_auth_role",
|
||||
"fieldtype": "Link",
|
||||
"label": "Role Allowed to edit frozen stock",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "stock_frozen_upto_days",
|
||||
"fieldtype": "Int",
|
||||
"label": "Freeze Stocks Older Than [Days]"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "stock_auth_role",
|
||||
"fieldtype": "Link",
|
||||
"label": "Role Allowed to edit frozen stock",
|
||||
"options": "Role"
|
||||
},
|
||||
},
|
||||
{
|
||||
"doctype": "DocPerm"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.utils import cint, validate_email_add
|
||||
from webnotes import msgprint, _
|
||||
from webnotes import throw, msgprint, _
|
||||
|
||||
class DocType:
|
||||
def __init__(self, doc, doclist=[]):
|
||||
@@ -18,7 +18,7 @@ class DocType:
|
||||
|
||||
def validate(self):
|
||||
if self.doc.email_id and not validate_email_add(self.doc.email_id):
|
||||
msgprint("Please enter valid Email Id", raise_exception=1)
|
||||
throw(_("Please enter valid Email Id"))
|
||||
|
||||
self.update_parent_account()
|
||||
|
||||
@@ -76,8 +76,8 @@ class DocType:
|
||||
for d in bins:
|
||||
if d['actual_qty'] or d['reserved_qty'] or d['ordered_qty'] or \
|
||||
d['indented_qty'] or d['projected_qty'] or d['planned_qty']:
|
||||
msgprint("""Warehouse: %s can not be deleted as qty exists for item: %s"""
|
||||
% (self.doc.name, d['item_code']), raise_exception=1)
|
||||
throw("""Warehouse: %s can not be deleted as qty exists for item: %s"""
|
||||
% (self.doc.name, d['item_code']))
|
||||
else:
|
||||
webnotes.conn.sql("delete from `tabBin` where name = %s", d['name'])
|
||||
|
||||
@@ -88,27 +88,23 @@ class DocType:
|
||||
|
||||
if webnotes.conn.sql("""select name from `tabStock Ledger Entry`
|
||||
where warehouse = %s""", self.doc.name):
|
||||
msgprint("""Warehouse can not be deleted as stock ledger entry
|
||||
exists for this warehouse.""", raise_exception=1)
|
||||
throw(_("""Warehouse can not be deleted as stock ledger entry
|
||||
exists for this warehouse."""))
|
||||
|
||||
def before_rename(self, olddn, newdn, merge=False):
|
||||
# Add company abbr if not provided
|
||||
from setup.doctype.company.company import get_name_with_abbr
|
||||
new_warehouse = get_name_with_abbr(newdn, self.doc.company)
|
||||
|
||||
if merge:
|
||||
if not webnotes.conn.exists("Warehouse", newdn):
|
||||
webnotes.throw(_("Warehouse ") + newdn +_(" does not exists"))
|
||||
|
||||
if self.doc.company != webnotes.conn.get_value("Warehouse", new_warehouse, "company"):
|
||||
if self.doc.company != webnotes.conn.get_value("Warehouse", newdn, "company"):
|
||||
webnotes.throw(_("Both Warehouse must belong to same Company"))
|
||||
|
||||
webnotes.conn.sql("delete from `tabBin` where warehouse=%s", olddn)
|
||||
|
||||
from accounts.utils import rename_account_for
|
||||
rename_account_for("Warehouse", olddn, new_warehouse, merge)
|
||||
rename_account_for("Warehouse", olddn, newdn, merge)
|
||||
|
||||
return new_warehouse
|
||||
return newdn
|
||||
|
||||
def after_rename(self, olddn, newdn, merge=False):
|
||||
if merge:
|
||||
|
||||
@@ -15,8 +15,8 @@ def execute(filters=None):
|
||||
bom_rate = get_item_bom_rate()
|
||||
val_rate_map = get_valuation_rate()
|
||||
|
||||
precision = get_currency_precision or 2
|
||||
|
||||
from accounts.utils import get_currency_precision
|
||||
precision = get_currency_precision() or 2
|
||||
data = []
|
||||
for item in sorted(item_map):
|
||||
data.append([item, item_map[item]["item_name"],
|
||||
@@ -30,14 +30,6 @@ def execute(filters=None):
|
||||
])
|
||||
|
||||
return columns, data
|
||||
|
||||
def get_currency_precision():
|
||||
company_currency = webnotes.conn.get_value("Company",
|
||||
webnotes.conn.get_default("company"), "default_currency")
|
||||
currency_format = webnotes.conn.get_value("Currency", company_currency, "number_format")
|
||||
|
||||
from webnotes.utils import get_number_format_info
|
||||
return get_number_format_info(currency_format)[2]
|
||||
|
||||
def get_columns(filters):
|
||||
"""return columns based on filters"""
|
||||
@@ -65,9 +57,10 @@ def get_price_list():
|
||||
|
||||
rate = {}
|
||||
|
||||
price_list = webnotes.conn.sql("""select item_code, buying, selling,
|
||||
concat(price_list, " - ", currency, " ", ref_rate) as price
|
||||
from `tabItem Price`""", as_dict=1)
|
||||
price_list = webnotes.conn.sql("""select ip.item_code, ip.buying, ip.selling,
|
||||
concat(ip.price_list, " - ", ip.currency, " ", ip.ref_rate) as price
|
||||
from `tabItem Price` ip, `tabPrice List` pl
|
||||
where ip.price_list=pl.name and pl.enabled=1""", as_dict=1)
|
||||
|
||||
for j in price_list:
|
||||
if j.price:
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
{
|
||||
"creation": "2013-01-10 16:34:30",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-11-02 16:59:22",
|
||||
"modified": "2014-01-14 15:56:22",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "harshada@webnotestech.com"
|
||||
},
|
||||
{
|
||||
"allow_import": 1,
|
||||
"autoname": "naming_series:",
|
||||
"doctype": "DocType",
|
||||
"icon": "icon-bug",
|
||||
|
||||
@@ -20,4 +20,5 @@ Info:,,,,,"One of: No, Yes"
|
||||
Start entering data below this line,,,,
|
||||
,,2009,01-01-2009,31-12-2009,No
|
||||
,,2010,01-01-2010,31-12-2010,No
|
||||
,,2011,01-01-2011,31-12-2011,No
|
||||
,,2011,01-01-2011,31-12-2011,No
|
||||
,,2012,01-01-2012,31-12-2012,No
|
||||
|
Can't render this file because it has a wrong number of fields in line 16.
|
@@ -19,7 +19,7 @@ company_abbr = "WP"
|
||||
country = "United States"
|
||||
currency = "USD"
|
||||
time_zone = "America/New_York"
|
||||
start_date = '2013-01-01'
|
||||
start_date = '2014-01-01'
|
||||
bank_name = "Citibank"
|
||||
runs_for = None
|
||||
prob = {
|
||||
@@ -105,6 +105,10 @@ def run_accounts(current_date):
|
||||
for so in list(set([r[0] for r in query_report.run(report)["result"] if r[0]!="Total"]))[:how_many("Sales Invoice")]:
|
||||
si = webnotes.bean(make_sales_invoice(so))
|
||||
si.doc.posting_date = current_date
|
||||
for d in si.doclist.get({"parentfield": "entries"}):
|
||||
if not d.income_account:
|
||||
d.income_account = "Sales - {}".format(company_abbr)
|
||||
|
||||
si.insert()
|
||||
si.submit()
|
||||
webnotes.conn.commit()
|
||||
@@ -170,6 +174,9 @@ def run_stock(current_date):
|
||||
dn = webnotes.bean(make_delivery_note(so))
|
||||
dn.doc.posting_date = current_date
|
||||
dn.doc.fiscal_year = current_date.year
|
||||
for d in dn.doclist.get({"parentfield": "delivery_note_details"}):
|
||||
d.expense_account = "Cost of Goods Sold - {}".format(company_abbr)
|
||||
|
||||
dn.insert()
|
||||
try:
|
||||
dn.submit()
|
||||
@@ -236,7 +243,7 @@ def run_manufacturing(current_date):
|
||||
ppt = webnotes.bean("Production Planning Tool", "Production Planning Tool")
|
||||
ppt.doc.company = company
|
||||
ppt.doc.use_multi_level_bom = 1
|
||||
ppt.doc.purchase_request_for_warehouse = "Stores - WP"
|
||||
ppt.doc.purchase_request_for_warehouse = "Stores - {}".format(company_abbr)
|
||||
ppt.run_method("get_open_sales_orders")
|
||||
ppt.run_method("get_items_from_so")
|
||||
ppt.run_method("raise_production_order")
|
||||
@@ -380,8 +387,8 @@ def complete_setup():
|
||||
setup_account({
|
||||
"first_name": "Test",
|
||||
"last_name": "User",
|
||||
"fy_start_date": "2013-01-01",
|
||||
"fy_end_date": "2013-12-31",
|
||||
"fy_start_date": "2014-01-01",
|
||||
"fy_end_date": "2014-12-31",
|
||||
"industry": "Manufacturing",
|
||||
"company_name": company,
|
||||
"company_abbr": company_abbr,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes import msgprint
|
||||
from webnotes import msgprint, throw, _
|
||||
from webnotes.utils import cstr, cint
|
||||
|
||||
class DocType:
|
||||
@@ -16,11 +16,11 @@ class DocType:
|
||||
if not self.doc.address_title:
|
||||
self.doc.address_title = self.doc.customer \
|
||||
or self.doc.supplier or self.doc.sales_partner or self.doc.lead
|
||||
|
||||
|
||||
if self.doc.address_title:
|
||||
self.doc.name = cstr(self.doc.address_title).strip() + "-" + cstr(self.doc.address_type).strip()
|
||||
else:
|
||||
webnotes.msgprint("""Address Title is mandatory.""" + self.doc.customer, raise_exception=True)
|
||||
throw(_("Address Title is mandatory."))
|
||||
|
||||
def validate(self):
|
||||
self.validate_primary_address()
|
||||
|
||||
@@ -78,10 +78,12 @@ class TransactionBase(StatusUpdater):
|
||||
3. Clears existing Sales Team and fetches the one mentioned in Customer
|
||||
"""
|
||||
customer_defaults = self.get_customer_defaults()
|
||||
|
||||
customer_defaults["selling_price_list"] = customer_defaults.get("price_list") or \
|
||||
webnotes.conn.get_value("Customer Group", self.doc.customer_group, "default_price_list") or \
|
||||
self.doc.selling_price_list
|
||||
|
||||
customer_defaults["selling_price_list"] = \
|
||||
self.get_user_default_price_list("selling_price_list") or \
|
||||
customer_defaults.get("price_list") or \
|
||||
webnotes.conn.get_value("Customer Group", self.doc.customer_group,
|
||||
"default_price_list") or self.doc.selling_price_list
|
||||
|
||||
for fieldname, val in customer_defaults.items():
|
||||
if self.meta.get_field(fieldname):
|
||||
@@ -90,6 +92,12 @@ class TransactionBase(StatusUpdater):
|
||||
if self.meta.get_field("sales_team") and self.doc.customer:
|
||||
self.set_sales_team_for_customer()
|
||||
|
||||
def get_user_default_price_list(self, price_list):
|
||||
from webnotes.defaults import get_defaults_for
|
||||
user_default_price_list = get_defaults_for(webnotes.session.user).get(price_list)
|
||||
return cstr(user_default_price_list) \
|
||||
if not isinstance(user_default_price_list, list) else ""
|
||||
|
||||
def set_sales_team_for_customer(self):
|
||||
from webnotes.model import default_fields
|
||||
|
||||
@@ -120,8 +128,9 @@ class TransactionBase(StatusUpdater):
|
||||
out["supplier_name"] = supplier.supplier_name
|
||||
if supplier.default_currency:
|
||||
out["currency"] = supplier.default_currency
|
||||
if supplier.default_price_list:
|
||||
out["buying_price_list"] = supplier.default_price_list
|
||||
|
||||
out["buying_price_list"] = self.get_user_default_price_list("buying_price_list") or \
|
||||
supplier.default_price_list or self.doc.buying_price_list
|
||||
|
||||
return out
|
||||
|
||||
|
||||
Reference in New Issue
Block a user