Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2407d87b0d | ||
|
|
276053b35f | ||
|
|
dc4c2733f4 | ||
|
|
f6f2fc4079 | ||
|
|
68b5eaa82f | ||
|
|
238fd68803 | ||
|
|
22a4b82bd2 | ||
|
|
f456eb6254 | ||
|
|
408a8e804c | ||
|
|
e0b39b860f | ||
|
|
fde7febf0d | ||
|
|
eebf194468 | ||
|
|
6f701b3b6a | ||
|
|
8147f74e4e | ||
|
|
dc65dc3778 | ||
|
|
a7fb9216c9 | ||
|
|
81b98261ae | ||
|
|
c20072e940 | ||
|
|
e4c2ebfc57 | ||
|
|
587c061550 | ||
|
|
40a9f6f8e9 | ||
|
|
f0b0464cce | ||
|
|
4e803af0e6 | ||
|
|
4ccd8d3326 | ||
|
|
9768467d53 | ||
|
|
59de1e23bc |
@@ -1,5 +1,7 @@
|
||||
# ERPNext - Open source ERP for small and medium-size business [](https://travis-ci.org/frappe/erpnext)
|
||||
|
||||
[](https://gitter.im/frappe/erpnext?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
[https://erpnext.com](https://erpnext.com)
|
||||
|
||||
Includes: Accounting, Inventory, CRM, Sales, Purchase, Projects, HRMS. Requires MariaDB.
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = '4.19.0'
|
||||
__version__ = '4.20.2'
|
||||
|
||||
@@ -114,7 +114,7 @@ erpnext.POS = Class.extend({
|
||||
});
|
||||
|
||||
this.wrapper.find('input.discount-amount').on("change", function() {
|
||||
frappe.model.set_value(me.frm.doctype, me.frm.docname, "discount_amount", this.value);
|
||||
frappe.model.set_value(me.frm.doctype, me.frm.docname, "discount_amount", flt(this.value));
|
||||
});
|
||||
|
||||
this.call_function("remove-items", function() {me.remove_selected_items();});
|
||||
|
||||
@@ -4,7 +4,7 @@ app_publisher = "Web Notes Technologies Pvt. Ltd. and Contributors"
|
||||
app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
|
||||
app_icon = "icon-th"
|
||||
app_color = "#e74c3c"
|
||||
app_version = "4.19.0"
|
||||
app_version = "4.20.2"
|
||||
|
||||
error_report_email = "support@erpnext.com"
|
||||
|
||||
|
||||
@@ -92,3 +92,4 @@ execute:frappe.delete_doc("DocType", "Contact Control")
|
||||
erpnext.patches.v4_2.recalculate_bom_costs
|
||||
erpnext.patches.v4_2.discount_amount
|
||||
erpnext.patches.v4_2.update_landed_cost_voucher
|
||||
erpnext.patches.v4_2.set_item_has_batch
|
||||
|
||||
65
erpnext/patches/v4_2/set_item_has_batch.py
Normal file
65
erpnext/patches/v4_2/set_item_has_batch.py
Normal file
@@ -0,0 +1,65 @@
|
||||
# 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 frappe
|
||||
|
||||
def execute():
|
||||
frappe.db.sql("update tabItem set has_batch_no = 'No' where ifnull(has_batch_no, '') = ''")
|
||||
frappe.db.sql("update tabItem set has_serial_no = 'No' where ifnull(has_serial_no, '') = ''")
|
||||
|
||||
item_list = frappe.db.sql("""select name, has_batch_no, has_serial_no from tabItem
|
||||
where ifnull(is_stock_item, 'No') = 'Yes'""", as_dict=1)
|
||||
|
||||
sle_count = get_sle_count()
|
||||
sle_with_batch = get_sle_with_batch()
|
||||
sle_with_serial = get_sle_with_serial()
|
||||
|
||||
batch_items = get_items_with_batch()
|
||||
serialized_items = get_items_with_serial()
|
||||
|
||||
for d in item_list:
|
||||
if d.has_batch_no == 'Yes':
|
||||
if d.name not in batch_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_batch.get(d.name):
|
||||
frappe.db.set_value("Item", d.name, "has_batch_no", "No")
|
||||
else:
|
||||
if d.name in batch_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_batch.get(d.name)):
|
||||
frappe.db.set_value("Item", d.name, "has_batch_no", "Yes")
|
||||
|
||||
if d.has_serial_no == 'Yes':
|
||||
if d.name not in serialized_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_serial.get(d.name):
|
||||
frappe.db.set_value("Item", d.name, "has_serial_no", "No")
|
||||
else:
|
||||
if d.name in serialized_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_serial.get(d.name)):
|
||||
frappe.db.set_value("Item", d.name, "has_serial_no", "Yes")
|
||||
|
||||
|
||||
def get_sle_count():
|
||||
sle_count = {}
|
||||
for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry` group by item_code""", as_dict=1):
|
||||
sle_count.setdefault(d.item_code, d.cnt)
|
||||
|
||||
return sle_count
|
||||
|
||||
def get_sle_with_batch():
|
||||
sle_with_batch = {}
|
||||
for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry`
|
||||
where ifnull(batch_no, '') != '' group by item_code""", as_dict=1):
|
||||
sle_with_batch.setdefault(d.item_code, d.cnt)
|
||||
|
||||
return sle_with_batch
|
||||
|
||||
|
||||
def get_sle_with_serial():
|
||||
sle_with_serial = {}
|
||||
for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry`
|
||||
where ifnull(serial_no, '') != '' group by item_code""", as_dict=1):
|
||||
sle_with_serial.setdefault(d.item_code, d.cnt)
|
||||
|
||||
return sle_with_serial
|
||||
|
||||
def get_items_with_batch():
|
||||
return frappe.db.sql_list("select item from tabBatch")
|
||||
|
||||
def get_items_with_serial():
|
||||
return frappe.db.sql_list("select item_code from `tabSerial No`")
|
||||
@@ -51,12 +51,12 @@ class SalesOrder(SellingController):
|
||||
frappe.throw(_("Reserved warehouse required for stock item {0}").format(d.item_code))
|
||||
|
||||
if e in check_list:
|
||||
frappe.throw(_("Item {0} has been entered twice").format(d.item_code))
|
||||
frappe.msgprint(_("Item {0} has been entered twice").format(d.item_code))
|
||||
else:
|
||||
check_list.append(e)
|
||||
else:
|
||||
if f in chk_dupl_itm:
|
||||
frappe.throw(_("Item {0} has been entered twice").format(d.item_code))
|
||||
frappe.msgprint(_("Item {0} has been entered twice").format(d.item_code))
|
||||
else:
|
||||
chk_dupl_itm.append(f)
|
||||
|
||||
|
||||
@@ -8,19 +8,22 @@ frappe.query_reports["Customer Acquisition and Loyalty"] = {
|
||||
"label": __("Company"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Company",
|
||||
"default": frappe.defaults.get_user_default("company")
|
||||
"default": frappe.defaults.get_user_default("company"),
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"from_date",
|
||||
"label": __("From Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.defaults.get_user_default("year_start_date")
|
||||
"default": frappe.defaults.get_user_default("year_start_date"),
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"to_date",
|
||||
"label": __("To Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.defaults.get_user_default("year_end_date")
|
||||
"default": frappe.defaults.get_user_default("year_end_date"),
|
||||
"reqd": 1
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,4 +166,4 @@ def item_details(doctype, txt, searchfield, start, page_len, filters):
|
||||
and %s like "%s" %s
|
||||
limit %s, %s """ % ("%s", searchfield, "%s",
|
||||
get_match_cond(doctype), "%s", "%s"),
|
||||
(filters["delivery_note"], "%%%s%%" % txt, start, page_len))
|
||||
((filters or {}).get("delivery_note"), "%%%s%%" % txt, start, page_len))
|
||||
|
||||
@@ -231,8 +231,8 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
||||
if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse;
|
||||
},
|
||||
|
||||
source_mandatory: ["Material Issue", "Material Transfer", "Purchase Return"],
|
||||
target_mandatory: ["Material Receipt", "Material Transfer", "Sales Return"],
|
||||
source_mandatory: ["Material Issue", "Material Transfer", "Purchase Return", "Subcontract"],
|
||||
target_mandatory: ["Material Receipt", "Material Transfer", "Sales Return", "Subcontract"],
|
||||
|
||||
from_warehouse: function(doc) {
|
||||
var me = this;
|
||||
@@ -462,4 +462,4 @@ cur_frm.fields_dict.supplier.get_query = function(doc, cdt, cdn) {
|
||||
return { query: "erpnext.controllers.queries.supplier_query" }
|
||||
}
|
||||
cur_frm.add_fetch('production_order', 'total_fixed_cost', 'total_fixed_cost');
|
||||
cur_frm.add_fetch('bom_no', 'total_fixed_cost', 'total_fixed_cost');
|
||||
cur_frm.add_fetch('bom_no', 'total_fixed_cost', 'total_fixed_cost');
|
||||
|
||||
@@ -32,16 +32,15 @@ class StockLedgerEntry(Document):
|
||||
|
||||
#check for item quantity available in stock
|
||||
def actual_amt_check(self):
|
||||
if self.batch_no:
|
||||
if self.batch_no and not self.get("allow_negative_stock"):
|
||||
batch_bal_after_transaction = flt(frappe.db.sql("""select sum(actual_qty)
|
||||
from `tabStock Ledger Entry`
|
||||
where warehouse=%s and item_code=%s and batch_no=%s""",
|
||||
(self.warehouse, self.item_code, self.batch_no))[0][0])
|
||||
|
||||
if batch_bal_after_transaction < 0:
|
||||
frappe.throw(_("Negative balance {0} in Batch {1} for Item {2} at Warehouse {3} on {4} {5}")
|
||||
.format(batch_bal_after_transaction - self.actual_qty, self.batch_no, self.item_code, self.warehouse,
|
||||
formatdate(self.posting_date), self.posting_time))
|
||||
frappe.throw(_("Stock balance in Batch {0} will become negative {1} for Item {2} at Warehouse {3}")
|
||||
.format(self.batch_no, batch_bal_after_transaction, self.item_code, self.warehouse))
|
||||
|
||||
def validate_mandatory(self):
|
||||
mandatory = ['warehouse','posting_date','voucher_type','voucher_no','company']
|
||||
|
||||
@@ -28,7 +28,7 @@ def make_sl_entries(sl_entries, is_amended=None, allow_negative_stock=False):
|
||||
sle['actual_qty'] = -flt(sle['actual_qty'])
|
||||
|
||||
if sle.get("actual_qty") or sle.get("voucher_type")=="Stock Reconciliation":
|
||||
sle_id = make_entry(sle)
|
||||
sle_id = make_entry(sle, allow_negative_stock)
|
||||
|
||||
args = sle.copy()
|
||||
args.update({
|
||||
@@ -46,10 +46,11 @@ def set_as_cancel(voucher_type, voucher_no):
|
||||
where voucher_no=%s and voucher_type=%s""",
|
||||
(now(), frappe.session.user, voucher_type, voucher_no))
|
||||
|
||||
def make_entry(args):
|
||||
def make_entry(args, allow_negative_stock=False):
|
||||
args.update({"doctype": "Stock Ledger Entry"})
|
||||
sle = frappe.get_doc(args)
|
||||
sle.ignore_permissions = 1
|
||||
sle.allow_negative_stock=allow_negative_stock
|
||||
sle.insert()
|
||||
sle.submit()
|
||||
return sle.name
|
||||
|
||||
@@ -27,6 +27,7 @@ class MaintenanceVisit(TransactionBase):
|
||||
mntc_date = self.mntc_date
|
||||
service_person = d.service_person
|
||||
work_done = d.work_done
|
||||
status = "Open"
|
||||
if self.completion_status == 'Fully Completed':
|
||||
status = 'Closed'
|
||||
elif self.completion_status == 'Partially Completed':
|
||||
|
||||
@@ -9,9 +9,13 @@
|
||||
<tr>
|
||||
<th style="width: 3%">{{ _("Sr") }}</th>
|
||||
<th style="width: 57%">{{ _("Item") }}</th>
|
||||
<th style="width: 10%;" class="text-right">{{ _("Qty") }}</th>
|
||||
{% if not hide_rate -%}<th style="width: 15%;" class="text-right">{{ _("Rate") }}</th>{%- endif %}
|
||||
{% if not hide_amount -%}<th style="width: 15%;" class="text-right">{{ _("Amount") }}</th>{%- endif %}
|
||||
<th style="width: 10%;" class="text-right">{{ _(data[0].meta.get_label("qty")) }}</th>
|
||||
{% if not hide_rate -%}
|
||||
<th style="width: 15%;" class="text-right">{{ _(data[0].meta.get_label("rate")) }}</th>
|
||||
{%- endif %}
|
||||
{% if not hide_amount -%}
|
||||
<th style="width: 15%;" class="text-right">{{ _(data[0].meta.get_label("amount")) }}</th>
|
||||
{%- endif %}
|
||||
</tr>
|
||||
{%- for row in data -%}
|
||||
<tr>
|
||||
|
||||
Reference in New Issue
Block a user