refactor: rename doctype serial and batch ledger to serial and batch entry
This commit is contained in:
parent
16f26fb3d8
commit
5bb3173676
@ -510,10 +510,6 @@ class PurchaseInvoice(BuyingController):
|
|||||||
if self.is_old_subcontracting_flow:
|
if self.is_old_subcontracting_flow:
|
||||||
self.set_consumed_qty_in_subcontract_order()
|
self.set_consumed_qty_in_subcontract_order()
|
||||||
|
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
|
|
||||||
|
|
||||||
update_serial_nos_after_submit(self, "items")
|
|
||||||
|
|
||||||
# this sequence because outstanding may get -negative
|
# this sequence because outstanding may get -negative
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
|
|
||||||
|
|||||||
@ -38,11 +38,7 @@ from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timeshe
|
|||||||
from erpnext.setup.doctype.company.company import update_company_current_month_sales
|
from erpnext.setup.doctype.company.company import update_company_current_month_sales
|
||||||
from erpnext.stock.doctype.batch.batch import set_batch_nos
|
from erpnext.stock.doctype.batch.batch import set_batch_nos
|
||||||
from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so
|
from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import (
|
from erpnext.stock.doctype.serial_no.serial_no import get_delivery_note_serial_no, get_serial_nos
|
||||||
get_delivery_note_serial_no,
|
|
||||||
get_serial_nos,
|
|
||||||
update_serial_nos_after_submit,
|
|
||||||
)
|
|
||||||
|
|
||||||
form_grid_templates = {"items": "templates/form_grid/item_grid.html"}
|
form_grid_templates = {"items": "templates/form_grid/item_grid.html"}
|
||||||
|
|
||||||
@ -262,8 +258,6 @@ class SalesInvoice(SellingController):
|
|||||||
# because updating reserved qty in bin depends upon updated delivered qty in SO
|
# because updating reserved qty in bin depends upon updated delivered qty in SO
|
||||||
if self.update_stock == 1:
|
if self.update_stock == 1:
|
||||||
self.update_stock_ledger()
|
self.update_stock_ledger()
|
||||||
if self.is_return and self.update_stock:
|
|
||||||
update_serial_nos_after_submit(self, "items")
|
|
||||||
|
|
||||||
# this sequence because outstanding may get -ve
|
# this sequence because outstanding may get -ve
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
|
|||||||
@ -387,7 +387,7 @@ class StockController(AccountsController):
|
|||||||
bundle_doc.voucher_no = self.name
|
bundle_doc.voucher_no = self.name
|
||||||
bundle_doc.is_cancelled = 0
|
bundle_doc.is_cancelled = 0
|
||||||
|
|
||||||
for row in bundle_doc.ledgers:
|
for row in bundle_doc.entries:
|
||||||
row.is_outward = 0
|
row.is_outward = 0
|
||||||
row.qty = abs(row.qty)
|
row.qty = abs(row.qty)
|
||||||
row.stock_value_difference = abs(row.stock_value_difference)
|
row.stock_value_difference = abs(row.stock_value_difference)
|
||||||
@ -398,8 +398,7 @@ class StockController(AccountsController):
|
|||||||
|
|
||||||
row.warehouse = warehouse
|
row.warehouse = warehouse
|
||||||
|
|
||||||
bundle_doc.set_total_qty()
|
bundle_doc.calculate_qty_and_amount()
|
||||||
bundle_doc.set_avg_rate()
|
|
||||||
bundle_doc.flags.ignore_permissions = True
|
bundle_doc.flags.ignore_permissions = True
|
||||||
|
|
||||||
if not do_not_submit:
|
if not do_not_submit:
|
||||||
|
|||||||
@ -509,7 +509,7 @@ class SubcontractingController(StockController):
|
|||||||
|
|
||||||
qty -= qty_to_consumed
|
qty -= qty_to_consumed
|
||||||
if qty_to_consumed > 0:
|
if qty_to_consumed > 0:
|
||||||
bundle.append("ledgers", {"batch_no": batch_no, "qty": qty_to_consumed * -1})
|
bundle.append("entries", {"batch_no": batch_no, "qty": qty_to_consumed * -1})
|
||||||
|
|
||||||
def __set_serial_nos_for_bundle(self, bundle, qty, key):
|
def __set_serial_nos_for_bundle(self, bundle, qty, key):
|
||||||
bundle.has_serial_no = 1
|
bundle.has_serial_no = 1
|
||||||
@ -525,7 +525,7 @@ class SubcontractingController(StockController):
|
|||||||
if batch_no:
|
if batch_no:
|
||||||
self.available_materials[key]["batch_no"][batch_no] -= 1
|
self.available_materials[key]["batch_no"][batch_no] -= 1
|
||||||
|
|
||||||
bundle.append("ledgers", {"serial_no": sn, "batch_no": batch_no, "qty": -1})
|
bundle.append("entries", {"serial_no": sn, "batch_no": batch_no, "qty": -1})
|
||||||
|
|
||||||
self.available_materials[key]["serial_no"].remove(sn)
|
self.available_materials[key]["serial_no"].remove(sn)
|
||||||
|
|
||||||
|
|||||||
@ -360,7 +360,7 @@ erpnext.buying.BuyingController = class BuyingController extends erpnext.Transac
|
|||||||
item.is_rejected = false;
|
item.is_rejected = false;
|
||||||
|
|
||||||
frappe.require(path, function() {
|
frappe.require(path, function() {
|
||||||
new erpnext.SerialNoBatchBundleUpdate(
|
new erpnext.SerialBatchPackageSelector(
|
||||||
me.frm, item, (r) => {
|
me.frm, item, (r) => {
|
||||||
if (r) {
|
if (r) {
|
||||||
me.frm.refresh_fields();
|
me.frm.refresh_fields();
|
||||||
@ -388,7 +388,7 @@ erpnext.buying.BuyingController = class BuyingController extends erpnext.Transac
|
|||||||
item.is_rejected = true;
|
item.is_rejected = true;
|
||||||
|
|
||||||
frappe.require(path, function() {
|
frappe.require(path, function() {
|
||||||
new erpnext.SerialNoBatchBundleUpdate(
|
new erpnext.SerialBatchPackageSelector(
|
||||||
me.frm, item, (r) => {
|
me.frm, item, (r) => {
|
||||||
if (r) {
|
if (r) {
|
||||||
me.frm.refresh_fields();
|
me.frm.refresh_fields();
|
||||||
|
|||||||
@ -2318,7 +2318,16 @@ erpnext.show_serial_batch_selector = function (frm, item_row, callback, on_close
|
|||||||
}
|
}
|
||||||
|
|
||||||
frappe.require("assets/erpnext/js/utils/serial_no_batch_selector.js", function() {
|
frappe.require("assets/erpnext/js/utils/serial_no_batch_selector.js", function() {
|
||||||
new erpnext.SerialNoBatchBundleUpdate(frm, item_row, (r) => {
|
if (in_list(["Sales Invoice", "Delivery Note"], frm.doc.doctype)) {
|
||||||
|
item_row.outward = frm.doc.is_return ? 0 : 1;
|
||||||
|
} else {
|
||||||
|
item_row.outward = frm.doc.is_return ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
item_row.type_of_transaction = (item_row.outward === 1
|
||||||
|
? "Outward":"Inward");
|
||||||
|
|
||||||
|
new erpnext.SerialBatchPackageSelector(frm, item_row, (r) => {
|
||||||
if (r) {
|
if (r) {
|
||||||
frm.refresh_fields();
|
frm.refresh_fields();
|
||||||
frappe.model.set_value(item_row.doctype, item_row.name,
|
frappe.model.set_value(item_row.doctype, item_row.name,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
erpnext.SerialNoBatchBundleUpdate = class SerialNoBatchBundleUpdate {
|
erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
|
||||||
constructor(frm, item, callback) {
|
constructor(frm, item, callback) {
|
||||||
this.frm = frm;
|
this.frm = frm;
|
||||||
this.item = item;
|
this.item = item;
|
||||||
@ -105,7 +105,7 @@ erpnext.SerialNoBatchBundleUpdate = class SerialNoBatchBundleUpdate {
|
|||||||
});
|
});
|
||||||
|
|
||||||
fields.push({
|
fields.push({
|
||||||
fieldname: 'ledgers',
|
fieldname: 'entries',
|
||||||
fieldtype: 'Table',
|
fieldtype: 'Table',
|
||||||
allow_bulk_edit: true,
|
allow_bulk_edit: true,
|
||||||
data: [],
|
data: [],
|
||||||
@ -228,8 +228,8 @@ erpnext.SerialNoBatchBundleUpdate = class SerialNoBatchBundleUpdate {
|
|||||||
callback: (r) => {
|
callback: (r) => {
|
||||||
debugger
|
debugger
|
||||||
if (r.message) {
|
if (r.message) {
|
||||||
this.dialog.fields_dict.ledgers.df.data = r.message;
|
this.dialog.fields_dict.entries.df.data = r.message;
|
||||||
this.dialog.fields_dict.ledgers.grid.refresh();
|
this.dialog.fields_dict.entries.grid.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -239,44 +239,40 @@ erpnext.SerialNoBatchBundleUpdate = class SerialNoBatchBundleUpdate {
|
|||||||
const { scan_serial_no, scan_batch_no } = this.dialog.get_values();
|
const { scan_serial_no, scan_batch_no } = this.dialog.get_values();
|
||||||
|
|
||||||
if (scan_serial_no) {
|
if (scan_serial_no) {
|
||||||
this.dialog.fields_dict.ledgers.df.data.push({
|
this.dialog.fields_dict.entries.df.data.push({
|
||||||
serial_no: scan_serial_no
|
serial_no: scan_serial_no
|
||||||
});
|
});
|
||||||
|
|
||||||
this.dialog.fields_dict.scan_serial_no.set_value('');
|
this.dialog.fields_dict.scan_serial_no.set_value('');
|
||||||
} else if (scan_batch_no) {
|
} else if (scan_batch_no) {
|
||||||
this.dialog.fields_dict.ledgers.df.data.push({
|
this.dialog.fields_dict.entries.df.data.push({
|
||||||
batch_no: scan_batch_no
|
batch_no: scan_batch_no
|
||||||
});
|
});
|
||||||
|
|
||||||
this.dialog.fields_dict.scan_batch_no.set_value('');
|
this.dialog.fields_dict.scan_batch_no.set_value('');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dialog.fields_dict.ledgers.grid.refresh();
|
this.dialog.fields_dict.entries.grid.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
update_ledgers() {
|
update_ledgers() {
|
||||||
if (!this.frm.is_new()) {
|
let entries = this.dialog.get_values().entries;
|
||||||
let ledgers = this.dialog.get_values().ledgers;
|
|
||||||
|
|
||||||
if (ledgers && !ledgers.length || !ledgers) {
|
if (entries && !entries.length || !entries) {
|
||||||
frappe.throw(__('Please add atleast one Serial No / Batch No'));
|
frappe.throw(__('Please add atleast one Serial No / Batch No'));
|
||||||
}
|
|
||||||
|
|
||||||
frappe.call({
|
|
||||||
method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.add_serial_batch_ledgers',
|
|
||||||
args: {
|
|
||||||
ledgers: ledgers,
|
|
||||||
child_row: this.item,
|
|
||||||
doc: this.frm.doc,
|
|
||||||
}
|
|
||||||
}).then(r => {
|
|
||||||
this.callback && this.callback(r.message);
|
|
||||||
this.dialog.hide();
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
frappe.msgprint(__('Please save the document first'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frappe.call({
|
||||||
|
method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.add_serial_batch_ledgers',
|
||||||
|
args: {
|
||||||
|
entries: entries,
|
||||||
|
child_row: this.item,
|
||||||
|
doc: this.frm.doc,
|
||||||
|
}
|
||||||
|
}).then(r => {
|
||||||
|
this.callback && this.callback(r.message);
|
||||||
|
this.dialog.hide();
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
render_data() {
|
render_data() {
|
||||||
@ -298,9 +294,9 @@ erpnext.SerialNoBatchBundleUpdate = class SerialNoBatchBundleUpdate {
|
|||||||
|
|
||||||
set_data(data) {
|
set_data(data) {
|
||||||
data.forEach(d => {
|
data.forEach(d => {
|
||||||
this.dialog.fields_dict.ledgers.df.data.push(d);
|
this.dialog.fields_dict.entries.df.data.push(d);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.dialog.fields_dict.ledgers.grid.refresh();
|
this.dialog.fields_dict.entries.grid.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,7 +441,7 @@ erpnext.selling.SellingController = class SellingController extends erpnext.Tran
|
|||||||
}
|
}
|
||||||
|
|
||||||
frappe.require(path, function() {
|
frappe.require(path, function() {
|
||||||
new erpnext.SerialNoBatchBundleUpdate(
|
new erpnext.SerialBatchPackageSelector(
|
||||||
me.frm, item, (r) => {
|
me.frm, item, (r) => {
|
||||||
if (r) {
|
if (r) {
|
||||||
me.frm.refresh_fields();
|
me.frm.refresh_fields();
|
||||||
|
|||||||
@ -67,8 +67,8 @@ class DeprecatedSerialNoValuation:
|
|||||||
|
|
||||||
class DeprecatedBatchNoValuation:
|
class DeprecatedBatchNoValuation:
|
||||||
def calculate_avg_rate_from_deprecarated_ledgers(self):
|
def calculate_avg_rate_from_deprecarated_ledgers(self):
|
||||||
ledgers = self.get_sle_for_batches()
|
entries = self.get_sle_for_batches()
|
||||||
for ledger in ledgers:
|
for ledger in entries:
|
||||||
self.batch_avg_rate[ledger.batch_no] += flt(ledger.batch_value) / flt(ledger.batch_qty)
|
self.batch_avg_rate[ledger.batch_no] += flt(ledger.batch_value) / flt(ledger.batch_qty)
|
||||||
self.available_qty[ledger.batch_no] += flt(ledger.batch_qty)
|
self.available_qty[ledger.batch_no] += flt(ledger.batch_qty)
|
||||||
|
|
||||||
|
|||||||
@ -240,11 +240,6 @@ class PurchaseReceipt(BuyingController):
|
|||||||
# because updating ordered qty, reserved_qty_for_subcontract in bin
|
# because updating ordered qty, reserved_qty_for_subcontract in bin
|
||||||
# depends upon updated ordered qty in PO
|
# depends upon updated ordered qty in PO
|
||||||
self.update_stock_ledger()
|
self.update_stock_ledger()
|
||||||
|
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
|
|
||||||
|
|
||||||
update_serial_nos_after_submit(self, "items")
|
|
||||||
|
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
self.repost_future_sle_and_gle()
|
self.repost_future_sle_and_gle()
|
||||||
self.set_consumed_qty_in_subcontract_order()
|
self.set_consumed_qty_in_subcontract_order()
|
||||||
|
|||||||
@ -16,7 +16,7 @@ frappe.ui.form.on('Serial and Batch Bundle', {
|
|||||||
method: "set_warehouse",
|
method: "set_warehouse",
|
||||||
doc: frm.doc,
|
doc: frm.doc,
|
||||||
callback(r) {
|
callback(r) {
|
||||||
refresh_field("ledgers");
|
refresh_field("entries");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -31,11 +31,11 @@ frappe.ui.form.on('Serial and Batch Bundle', {
|
|||||||
},
|
},
|
||||||
|
|
||||||
toggle_fields(frm) {
|
toggle_fields(frm) {
|
||||||
frm.fields_dict.ledgers.grid.update_docfield_property(
|
frm.fields_dict.entries.grid.update_docfield_property(
|
||||||
'serial_no', 'read_only', !frm.doc.has_serial_no
|
'serial_no', 'read_only', !frm.doc.has_serial_no
|
||||||
);
|
);
|
||||||
|
|
||||||
frm.fields_dict.ledgers.grid.update_docfield_property(
|
frm.fields_dict.entries.grid.update_docfield_property(
|
||||||
'batch_no', 'read_only', !frm.doc.has_batch_no
|
'batch_no', 'read_only', !frm.doc.has_batch_no
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -74,7 +74,7 @@ frappe.ui.form.on('Serial and Batch Bundle', {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.set_query('serial_no', 'ledgers', () => {
|
frm.set_query('serial_no', 'entries', () => {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
item_code: frm.doc.item_code,
|
item_code: frm.doc.item_code,
|
||||||
@ -82,7 +82,7 @@ frappe.ui.form.on('Serial and Batch Bundle', {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.set_query('batch_no', 'ledgers', () => {
|
frm.set_query('batch_no', 'entries', () => {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
item: frm.doc.item_code,
|
item: frm.doc.item_code,
|
||||||
@ -90,7 +90,7 @@ frappe.ui.form.on('Serial and Batch Bundle', {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.set_query('warehouse', 'ledgers', () => {
|
frm.set_query('warehouse', 'entries', () => {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
company: frm.doc.company,
|
company: frm.doc.company,
|
||||||
@ -101,7 +101,7 @@ frappe.ui.form.on('Serial and Batch Bundle', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
frappe.ui.form.on("Serial and Batch Ledger", {
|
frappe.ui.form.on("Serial and Batch Entry", {
|
||||||
ledgers_add(frm, cdt, cdn) {
|
ledgers_add(frm, cdt, cdn) {
|
||||||
if (frm.doc.warehouse) {
|
if (frm.doc.warehouse) {
|
||||||
locals[cdt][cdn].warehouse = frm.doc.warehouse;
|
locals[cdt][cdn].warehouse = frm.doc.warehouse;
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
"has_serial_no",
|
"has_serial_no",
|
||||||
"has_batch_no",
|
"has_batch_no",
|
||||||
"serial_no_and_batch_no_tab",
|
"serial_no_and_batch_no_tab",
|
||||||
"ledgers",
|
"entries",
|
||||||
"quantity_and_rate_section",
|
"quantity_and_rate_section",
|
||||||
"total_qty",
|
"total_qty",
|
||||||
"item_group",
|
"item_group",
|
||||||
@ -95,15 +95,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "serial_no_and_batch_no_tab",
|
"fieldname": "serial_no_and_batch_no_tab",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break",
|
||||||
},
|
"label": "Serial / Batch No"
|
||||||
{
|
|
||||||
"allow_bulk_edit": 1,
|
|
||||||
"fieldname": "ledgers",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"label": "Ledgers",
|
|
||||||
"options": "Serial and Batch Ledger",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "voucher_type",
|
"fieldname": "voucher_type",
|
||||||
@ -232,12 +225,19 @@
|
|||||||
"label": "Voucher Detail No",
|
"label": "Voucher Detail No",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 1,
|
||||||
|
"fieldname": "entries",
|
||||||
|
"fieldtype": "Table",
|
||||||
|
"options": "Serial and Batch Entry",
|
||||||
|
"reqd": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-03-12 16:05:18.141958",
|
"modified": "2023-03-21 10:52:25.105421",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Serial and Batch Bundle",
|
"name": "Serial and Batch Bundle",
|
||||||
|
|||||||
@ -28,19 +28,16 @@ class SerialandBatchBundle(Document):
|
|||||||
|
|
||||||
def before_save(self):
|
def before_save(self):
|
||||||
self.set_is_outward()
|
self.set_is_outward()
|
||||||
self.set_total_qty()
|
self.calculate_qty_and_amount()
|
||||||
self.set_warehouse()
|
self.set_warehouse()
|
||||||
self.set_incoming_rate()
|
self.set_incoming_rate()
|
||||||
self.validate_qty_and_stock_value_difference()
|
self.validate_qty_and_stock_value_difference()
|
||||||
|
|
||||||
if self.ledgers:
|
|
||||||
self.set_avg_rate()
|
|
||||||
|
|
||||||
def validate_serial_nos_inventory(self):
|
def validate_serial_nos_inventory(self):
|
||||||
if not (self.has_serial_no and self.type_of_transaction == "Outward"):
|
if not (self.has_serial_no and self.type_of_transaction == "Outward"):
|
||||||
return
|
return
|
||||||
|
|
||||||
serial_nos = [d.serial_no for d in self.ledgers if d.serial_no]
|
serial_nos = [d.serial_no for d in self.entries if d.serial_no]
|
||||||
serial_no_warehouse = frappe._dict(
|
serial_no_warehouse = frappe._dict(
|
||||||
frappe.get_all(
|
frappe.get_all(
|
||||||
"Serial No",
|
"Serial No",
|
||||||
@ -68,7 +65,7 @@ class SerialandBatchBundle(Document):
|
|||||||
if self.type_of_transaction != "Outward":
|
if self.type_of_transaction != "Outward":
|
||||||
return
|
return
|
||||||
|
|
||||||
for d in self.ledgers:
|
for d in self.entries:
|
||||||
if d.qty and d.qty > 0:
|
if d.qty and d.qty > 0:
|
||||||
d.qty *= -1
|
d.qty *= -1
|
||||||
|
|
||||||
@ -76,7 +73,7 @@ class SerialandBatchBundle(Document):
|
|||||||
d.stock_value_difference *= -1
|
d.stock_value_difference *= -1
|
||||||
|
|
||||||
def get_serial_nos(self):
|
def get_serial_nos(self):
|
||||||
return [d.serial_no for d in self.ledgers if d.serial_no]
|
return [d.serial_no for d in self.entries if d.serial_no]
|
||||||
|
|
||||||
def set_incoming_rate_for_outward_transaction(self, row=None, save=False):
|
def set_incoming_rate_for_outward_transaction(self, row=None, save=False):
|
||||||
sle = self.get_sle_for_outward_transaction(row)
|
sle = self.get_sle_for_outward_transaction(row)
|
||||||
@ -94,7 +91,7 @@ class SerialandBatchBundle(Document):
|
|||||||
item_code=self.warehouse,
|
item_code=self.warehouse,
|
||||||
)
|
)
|
||||||
|
|
||||||
for d in self.ledgers:
|
for d in self.entries:
|
||||||
available_qty = 0
|
available_qty = 0
|
||||||
if self.has_serial_no:
|
if self.has_serial_no:
|
||||||
d.incoming_rate = abs(sn_obj.serial_no_incoming_rate.get(d.serial_no, 0.0))
|
d.incoming_rate = abs(sn_obj.serial_no_incoming_rate.get(d.serial_no, 0.0))
|
||||||
@ -130,19 +127,23 @@ class SerialandBatchBundle(Document):
|
|||||||
"serial_and_batch_bundle": self.name,
|
"serial_and_batch_bundle": self.name,
|
||||||
"actual_qty": self.total_qty,
|
"actual_qty": self.total_qty,
|
||||||
"company": self.company,
|
"company": self.company,
|
||||||
"serial_nos": [row.serial_no for row in self.ledgers if row.serial_no],
|
"serial_nos": [row.serial_no for row in self.entries if row.serial_no],
|
||||||
"batch_nos": {row.batch_no: row for row in self.ledgers if row.batch_no},
|
"batch_nos": {row.batch_no: row for row in self.entries if row.batch_no},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_incoming_rate_for_inward_transaction(self, row=None, save=False):
|
def set_incoming_rate_for_inward_transaction(self, row=None, save=False):
|
||||||
rate = row.valuation_rate if row else 0.0
|
valuation_field = "valuation_rate"
|
||||||
precision = frappe.get_precision(self.child_table, "valuation_rate") or 2
|
if self.voucher_type in ["Sales Invoice", "Delivery Note"]:
|
||||||
|
valuation_field = "incoming_rate"
|
||||||
|
|
||||||
|
rate = row.get(valuation_field) if row else 0.0
|
||||||
|
precision = frappe.get_precision(self.child_table, valuation_field) or 2
|
||||||
|
|
||||||
if not rate and self.voucher_detail_no and self.voucher_no:
|
if not rate and self.voucher_detail_no and self.voucher_no:
|
||||||
rate = frappe.db.get_value(self.child_table, self.voucher_detail_no, "valuation_rate")
|
rate = frappe.db.get_value(self.child_table, self.voucher_detail_no, valuation_field)
|
||||||
|
|
||||||
for d in self.ledgers:
|
for d in self.entries:
|
||||||
if self.voucher_type in ["Stock Reconciliation", "Stock Entry"] and d.incoming_rate:
|
if self.voucher_type in ["Stock Reconciliation", "Stock Entry"] and d.incoming_rate:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -180,8 +181,9 @@ class SerialandBatchBundle(Document):
|
|||||||
self.db_set(values_to_set)
|
self.db_set(values_to_set)
|
||||||
|
|
||||||
# self.validate_voucher_no()
|
# self.validate_voucher_no()
|
||||||
self.validate_quantity(row)
|
|
||||||
self.set_incoming_rate(save=True, row=row)
|
self.set_incoming_rate(save=True, row=row)
|
||||||
|
self.calculate_qty_and_amount(save=True)
|
||||||
|
self.validate_quantity(row)
|
||||||
|
|
||||||
def validate_voucher_no(self):
|
def validate_voucher_no(self):
|
||||||
if self.is_new():
|
if self.is_new():
|
||||||
@ -215,10 +217,13 @@ class SerialandBatchBundle(Document):
|
|||||||
if not self.has_serial_no:
|
if not self.has_serial_no:
|
||||||
return
|
return
|
||||||
|
|
||||||
serial_nos = [d.serial_no for d in self.ledgers if d.serial_no]
|
serial_nos = [d.serial_no for d in self.entries if d.serial_no]
|
||||||
|
|
||||||
|
if not serial_nos:
|
||||||
|
return
|
||||||
|
|
||||||
parent = frappe.qb.DocType("Serial and Batch Bundle")
|
parent = frappe.qb.DocType("Serial and Batch Bundle")
|
||||||
child = frappe.qb.DocType("Serial and Batch Ledger")
|
child = frappe.qb.DocType("Serial and Batch Entry")
|
||||||
|
|
||||||
timestamp_condition = CombineDatetime(
|
timestamp_condition = CombineDatetime(
|
||||||
parent.posting_date, parent.posting_time
|
parent.posting_date, parent.posting_time
|
||||||
@ -260,8 +265,6 @@ class SerialandBatchBundle(Document):
|
|||||||
frappe.throw(_(msg), title=_(title), exc=SerialNoExistsInFutureTransactionError)
|
frappe.throw(_(msg), title=_(title), exc=SerialNoExistsInFutureTransactionError)
|
||||||
|
|
||||||
def validate_quantity(self, row):
|
def validate_quantity(self, row):
|
||||||
self.set_total_qty(save=True)
|
|
||||||
|
|
||||||
precision = row.precision
|
precision = row.precision
|
||||||
qty_field = "qty"
|
qty_field = "qty"
|
||||||
if self.voucher_type in ["Subcontracting Receipt"]:
|
if self.voucher_type in ["Subcontracting Receipt"]:
|
||||||
@ -275,7 +278,7 @@ class SerialandBatchBundle(Document):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def set_is_outward(self):
|
def set_is_outward(self):
|
||||||
for row in self.ledgers:
|
for row in self.entries:
|
||||||
if self.type_of_transaction == "Outward" and row.qty > 0:
|
if self.type_of_transaction == "Outward" and row.qty > 0:
|
||||||
row.qty *= -1
|
row.qty *= -1
|
||||||
elif self.type_of_transaction == "Inward" and row.qty < 0:
|
elif self.type_of_transaction == "Inward" and row.qty < 0:
|
||||||
@ -285,30 +288,34 @@ class SerialandBatchBundle(Document):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def set_warehouse(self):
|
def set_warehouse(self):
|
||||||
for row in self.ledgers:
|
for row in self.entries:
|
||||||
if row.warehouse != self.warehouse:
|
if row.warehouse != self.warehouse:
|
||||||
row.warehouse = self.warehouse
|
row.warehouse = self.warehouse
|
||||||
|
|
||||||
def set_total_qty(self, save=False):
|
def calculate_qty_and_amount(self, save=False):
|
||||||
if not self.ledgers:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.total_qty = sum([row.qty for row in self.ledgers])
|
|
||||||
if save:
|
|
||||||
self.db_set("total_qty", self.total_qty)
|
|
||||||
|
|
||||||
def set_avg_rate(self):
|
|
||||||
self.total_amount = 0.0
|
self.total_amount = 0.0
|
||||||
|
self.total_qty = 0.0
|
||||||
|
self.avg_rate = 0.0
|
||||||
|
|
||||||
for row in self.ledgers:
|
for row in self.entries:
|
||||||
rate = flt(row.incoming_rate) or flt(row.outgoing_rate)
|
rate = flt(row.incoming_rate) or flt(row.outgoing_rate)
|
||||||
self.total_amount += flt(row.qty) * rate
|
self.total_amount += flt(row.qty) * rate
|
||||||
|
self.total_qty += flt(row.qty)
|
||||||
|
|
||||||
if self.total_qty:
|
if self.total_qty:
|
||||||
self.avg_rate = flt(self.total_amount) / flt(self.total_qty)
|
self.avg_rate = flt(self.total_amount) / flt(self.total_qty)
|
||||||
|
|
||||||
|
if save:
|
||||||
|
self.db_set(
|
||||||
|
{
|
||||||
|
"total_qty": self.total_qty,
|
||||||
|
"avg_rate": self.avg_rate,
|
||||||
|
"total_amount": self.total_amount,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def calculate_outgoing_rate(self):
|
def calculate_outgoing_rate(self):
|
||||||
if not (self.has_serial_no and self.ledgers):
|
if not (self.has_serial_no and self.entries):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not (self.voucher_type and self.voucher_no):
|
if not (self.voucher_type and self.voucher_no):
|
||||||
@ -332,7 +339,7 @@ class SerialandBatchBundle(Document):
|
|||||||
serial_nos = []
|
serial_nos = []
|
||||||
batch_nos = []
|
batch_nos = []
|
||||||
|
|
||||||
for row in self.ledgers:
|
for row in self.entries:
|
||||||
if row.serial_no:
|
if row.serial_no:
|
||||||
serial_nos.append(row.serial_no)
|
serial_nos.append(row.serial_no)
|
||||||
|
|
||||||
@ -362,7 +369,7 @@ class SerialandBatchBundle(Document):
|
|||||||
frappe.db.set_value("Stock Ledger Entry", sle.name, "serial_and_batch_bundle", None)
|
frappe.db.set_value("Stock Ledger Entry", sle.name, "serial_and_batch_bundle", None)
|
||||||
|
|
||||||
def clear_table(self):
|
def clear_table(self):
|
||||||
self.set("ledgers", [])
|
self.set("entries", [])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def child_table(self):
|
def child_table(self):
|
||||||
@ -434,15 +441,15 @@ def get_serial_batch_ledgers(item_code, voucher_no, name=None):
|
|||||||
return frappe.get_all(
|
return frappe.get_all(
|
||||||
"Serial and Batch Bundle",
|
"Serial and Batch Bundle",
|
||||||
fields=[
|
fields=[
|
||||||
"`tabSerial and Batch Ledger`.`name`",
|
"`tabSerial and Batch Entry`.`name`",
|
||||||
"`tabSerial and Batch Ledger`.`qty`",
|
"`tabSerial and Batch Entry`.`qty`",
|
||||||
"`tabSerial and Batch Ledger`.`warehouse`",
|
"`tabSerial and Batch Entry`.`warehouse`",
|
||||||
"`tabSerial and Batch Ledger`.`batch_no`",
|
"`tabSerial and Batch Entry`.`batch_no`",
|
||||||
"`tabSerial and Batch Ledger`.`serial_no`",
|
"`tabSerial and Batch Entry`.`serial_no`",
|
||||||
],
|
],
|
||||||
filters=[
|
filters=[
|
||||||
["Serial and Batch Bundle", "item_code", "=", item_code],
|
["Serial and Batch Bundle", "item_code", "=", item_code],
|
||||||
["Serial and Batch Ledger", "parent", "=", name],
|
["Serial and Batch Entry", "parent", "=", name],
|
||||||
["Serial and Batch Bundle", "voucher_no", "=", voucher_no],
|
["Serial and Batch Bundle", "voucher_no", "=", voucher_no],
|
||||||
["Serial and Batch Bundle", "docstatus", "!=", 2],
|
["Serial and Batch Bundle", "docstatus", "!=", 2],
|
||||||
],
|
],
|
||||||
@ -450,31 +457,30 @@ def get_serial_batch_ledgers(item_code, voucher_no, name=None):
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def add_serial_batch_ledgers(ledgers, child_row, doc) -> object:
|
def add_serial_batch_ledgers(entries, child_row, doc) -> object:
|
||||||
if isinstance(child_row, str):
|
if isinstance(child_row, str):
|
||||||
child_row = frappe._dict(frappe.parse_json(child_row))
|
child_row = frappe._dict(frappe.parse_json(child_row))
|
||||||
|
|
||||||
if isinstance(ledgers, str):
|
if isinstance(entries, str):
|
||||||
ledgers = frappe.parse_json(ledgers)
|
entries = frappe.parse_json(entries)
|
||||||
|
|
||||||
if doc and isinstance(doc, str):
|
if doc and isinstance(doc, str):
|
||||||
d = frappe.parse_json(doc)
|
parent_doc = frappe.parse_json(doc)
|
||||||
parent_doc = frappe.get_doc(d.doctype, d.name)
|
|
||||||
|
|
||||||
if frappe.db.exists("Serial and Batch Bundle", child_row.serial_and_batch_bundle):
|
if frappe.db.exists("Serial and Batch Bundle", child_row.serial_and_batch_bundle):
|
||||||
doc = update_serial_batch_no_ledgers(ledgers, child_row, parent_doc)
|
doc = update_serial_batch_no_ledgers(entries, child_row, parent_doc)
|
||||||
else:
|
else:
|
||||||
doc = create_serial_batch_no_ledgers(ledgers, child_row, parent_doc)
|
doc = create_serial_batch_no_ledgers(entries, child_row, parent_doc)
|
||||||
|
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
|
|
||||||
def create_serial_batch_no_ledgers(ledgers, child_row, parent_doc) -> object:
|
def create_serial_batch_no_ledgers(entries, child_row, parent_doc) -> object:
|
||||||
|
|
||||||
warehouse = child_row.rejected_warhouse if child_row.is_rejected else child_row.warehouse
|
warehouse = child_row.rejected_warhouse if child_row.is_rejected else child_row.warehouse
|
||||||
|
|
||||||
type_of_transaction = child_row.type_of_transaction
|
type_of_transaction = child_row.type_of_transaction
|
||||||
if parent_doc.doctype == "Stock Entry":
|
if parent_doc.get("doctype") == "Stock Entry":
|
||||||
type_of_transaction = "Outward" if child_row.s_warehouse else "Inward"
|
type_of_transaction = "Outward" if child_row.s_warehouse else "Inward"
|
||||||
warehouse = child_row.s_warehouse or child_row.t_warehouse
|
warehouse = child_row.s_warehouse or child_row.t_warehouse
|
||||||
|
|
||||||
@ -482,21 +488,19 @@ def create_serial_batch_no_ledgers(ledgers, child_row, parent_doc) -> object:
|
|||||||
{
|
{
|
||||||
"doctype": "Serial and Batch Bundle",
|
"doctype": "Serial and Batch Bundle",
|
||||||
"voucher_type": child_row.parenttype,
|
"voucher_type": child_row.parenttype,
|
||||||
"voucher_no": child_row.parent,
|
|
||||||
"item_code": child_row.item_code,
|
"item_code": child_row.item_code,
|
||||||
"warehouse": warehouse,
|
"warehouse": warehouse,
|
||||||
"voucher_detail_no": child_row.name,
|
|
||||||
"is_rejected": child_row.is_rejected,
|
"is_rejected": child_row.is_rejected,
|
||||||
"type_of_transaction": type_of_transaction,
|
"type_of_transaction": type_of_transaction,
|
||||||
"posting_date": parent_doc.posting_date,
|
"posting_date": parent_doc.get("posting_date"),
|
||||||
"posting_time": parent_doc.posting_time,
|
"posting_time": parent_doc.get("posting_time"),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
for row in ledgers:
|
for row in entries:
|
||||||
row = frappe._dict(row)
|
row = frappe._dict(row)
|
||||||
doc.append(
|
doc.append(
|
||||||
"ledgers",
|
"entries",
|
||||||
{
|
{
|
||||||
"qty": (row.qty or 1.0) * (1 if type_of_transaction == "Inward" else -1),
|
"qty": (row.qty or 1.0) * (1 if type_of_transaction == "Inward" else -1),
|
||||||
"warehouse": warehouse,
|
"warehouse": warehouse,
|
||||||
@ -514,16 +518,16 @@ def create_serial_batch_no_ledgers(ledgers, child_row, parent_doc) -> object:
|
|||||||
return doc
|
return doc
|
||||||
|
|
||||||
|
|
||||||
def update_serial_batch_no_ledgers(ledgers, child_row, parent_doc) -> object:
|
def update_serial_batch_no_ledgers(entries, child_row, parent_doc) -> object:
|
||||||
doc = frappe.get_doc("Serial and Batch Bundle", child_row.serial_and_batch_bundle)
|
doc = frappe.get_doc("Serial and Batch Bundle", child_row.serial_and_batch_bundle)
|
||||||
doc.voucher_detail_no = child_row.name
|
doc.voucher_detail_no = child_row.name
|
||||||
doc.posting_date = parent_doc.posting_date
|
doc.posting_date = parent_doc.posting_date
|
||||||
doc.posting_time = parent_doc.posting_time
|
doc.posting_time = parent_doc.posting_time
|
||||||
doc.set("ledgers", [])
|
doc.set("entries", [])
|
||||||
|
|
||||||
for d in ledgers:
|
for d in entries:
|
||||||
doc.append(
|
doc.append(
|
||||||
"ledgers",
|
"entries",
|
||||||
{
|
{
|
||||||
"qty": 1 if doc.type_of_transaction == "Inward" else -1,
|
"qty": 1 if doc.type_of_transaction == "Inward" else -1,
|
||||||
"warehouse": d.get("warehouse"),
|
"warehouse": d.get("warehouse"),
|
||||||
@ -543,7 +547,7 @@ def get_serial_and_batch_ledger(**kwargs):
|
|||||||
kwargs = frappe._dict(kwargs)
|
kwargs = frappe._dict(kwargs)
|
||||||
|
|
||||||
sle_table = frappe.qb.DocType("Stock Ledger Entry")
|
sle_table = frappe.qb.DocType("Stock Ledger Entry")
|
||||||
serial_batch_table = frappe.qb.DocType("Serial and Batch Ledger")
|
serial_batch_table = frappe.qb.DocType("Serial and Batch Entry")
|
||||||
|
|
||||||
query = (
|
query = (
|
||||||
frappe.qb.from_(sle_table)
|
frappe.qb.from_(sle_table)
|
||||||
@ -638,7 +642,7 @@ def get_auto_batch_nos(kwargs):
|
|||||||
|
|
||||||
def get_available_batches(kwargs):
|
def get_available_batches(kwargs):
|
||||||
stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry")
|
stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry")
|
||||||
batch_ledger = frappe.qb.DocType("Serial and Batch Ledger")
|
batch_ledger = frappe.qb.DocType("Serial and Batch Entry")
|
||||||
batch_table = frappe.qb.DocType("Batch")
|
batch_table = frappe.qb.DocType("Batch")
|
||||||
|
|
||||||
query = (
|
query = (
|
||||||
@ -708,7 +712,7 @@ def get_voucher_wise_serial_batch_from_bundle(**kwargs) -> Dict[str, Dict]:
|
|||||||
|
|
||||||
def get_ledgers_from_serial_batch_bundle(**kwargs) -> List[frappe._dict]:
|
def get_ledgers_from_serial_batch_bundle(**kwargs) -> List[frappe._dict]:
|
||||||
bundle_table = frappe.qb.DocType("Serial and Batch Bundle")
|
bundle_table = frappe.qb.DocType("Serial and Batch Bundle")
|
||||||
serial_batch_table = frappe.qb.DocType("Serial and Batch Ledger")
|
serial_batch_table = frappe.qb.DocType("Serial and Batch Entry")
|
||||||
|
|
||||||
query = (
|
query = (
|
||||||
frappe.qb.from_(bundle_table)
|
frappe.qb.from_(bundle_table)
|
||||||
@ -776,7 +780,7 @@ def get_available_batch_nos(item_code, warehouse):
|
|||||||
|
|
||||||
def get_stock_ledger_entries(item_code, warehouse):
|
def get_stock_ledger_entries(item_code, warehouse):
|
||||||
stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry")
|
stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry")
|
||||||
batch_ledger = frappe.qb.DocType("Serial and Batch Ledger")
|
batch_ledger = frappe.qb.DocType("Serial and Batch Entry")
|
||||||
|
|
||||||
return (
|
return (
|
||||||
frappe.qb.from_(stock_ledger_entry)
|
frappe.qb.from_(stock_ledger_entry)
|
||||||
|
|||||||
@ -110,7 +110,7 @@
|
|||||||
"modified": "2023-03-17 09:11:31.548862",
|
"modified": "2023-03-17 09:11:31.548862",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Serial and Batch Ledger",
|
"name": "Serial and Batch Entry",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
@ -5,5 +5,5 @@
|
|||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
class SerialandBatchLedger(Document):
|
class SerialandBatchEntry(Document):
|
||||||
pass
|
pass
|
||||||
@ -1114,7 +1114,7 @@ erpnext.stock.select_batch_and_serial_no = (frm, item) => {
|
|||||||
item.outward = item.s_warehouse ? 1 : 0;
|
item.outward = item.s_warehouse ? 1 : 0;
|
||||||
|
|
||||||
frappe.require(path, function() {
|
frappe.require(path, function() {
|
||||||
new erpnext.SerialNoBatchBundleUpdate(
|
new erpnext.SerialBatchPackageSelector(
|
||||||
frm, item, (r) => {
|
frm, item, (r) => {
|
||||||
if (r) {
|
if (r) {
|
||||||
frm.refresh_fields();
|
frm.refresh_fields();
|
||||||
|
|||||||
@ -242,6 +242,9 @@ class StockEntry(StockController):
|
|||||||
if self.purpose == "Material Transfer" and self.outgoing_stock_entry:
|
if self.purpose == "Material Transfer" and self.outgoing_stock_entry:
|
||||||
self.set_material_request_transfer_status("In Transit")
|
self.set_material_request_transfer_status("In Transit")
|
||||||
|
|
||||||
|
def on_update(self):
|
||||||
|
self.set_serial_and_batch_bundle()
|
||||||
|
|
||||||
def set_job_card_data(self):
|
def set_job_card_data(self):
|
||||||
if self.job_card and not self.work_order:
|
if self.job_card and not self.work_order:
|
||||||
data = frappe.db.get_value(
|
data = frappe.db.get_value(
|
||||||
@ -696,6 +699,9 @@ class StockEntry(StockController):
|
|||||||
self.set_total_incoming_outgoing_value()
|
self.set_total_incoming_outgoing_value()
|
||||||
self.set_total_amount()
|
self.set_total_amount()
|
||||||
|
|
||||||
|
if not reset_outgoing_rate:
|
||||||
|
self.set_serial_and_batch_bundle()
|
||||||
|
|
||||||
def set_basic_rate(self, reset_outgoing_rate=True, raise_error_if_no_rate=True):
|
def set_basic_rate(self, reset_outgoing_rate=True, raise_error_if_no_rate=True):
|
||||||
"""
|
"""
|
||||||
Set rate for outgoing, scrapped and finished items
|
Set rate for outgoing, scrapped and finished items
|
||||||
@ -2830,7 +2836,7 @@ def create_serial_and_batch_bundle(row, child, type_of_transaction=None):
|
|||||||
while qty > 0:
|
while qty > 0:
|
||||||
qty -= 1
|
qty -= 1
|
||||||
doc.append(
|
doc.append(
|
||||||
"ledgers",
|
"entries",
|
||||||
{
|
{
|
||||||
"batch_no": batch_no,
|
"batch_no": batch_no,
|
||||||
"serial_no": batchwise_serial_nos.get(batch_no).pop(0),
|
"serial_no": batchwise_serial_nos.get(batch_no).pop(0),
|
||||||
@ -2842,12 +2848,12 @@ def create_serial_and_batch_bundle(row, child, type_of_transaction=None):
|
|||||||
elif row.serial_nos:
|
elif row.serial_nos:
|
||||||
doc.has_serial_no = 1
|
doc.has_serial_no = 1
|
||||||
for serial_no in row.serial_nos:
|
for serial_no in row.serial_nos:
|
||||||
doc.append("ledgers", {"serial_no": serial_no, "warehouse": row.warehouse, "qty": -1})
|
doc.append("entries", {"serial_no": serial_no, "warehouse": row.warehouse, "qty": -1})
|
||||||
|
|
||||||
elif row.batches_to_be_consume:
|
elif row.batches_to_be_consume:
|
||||||
doc.has_batch_no = 1
|
doc.has_batch_no = 1
|
||||||
for batch_no, qty in row.batches_to_be_consume.items():
|
for batch_no, qty in row.batches_to_be_consume.items():
|
||||||
doc.append("ledgers", {"batch_no": batch_no, "warehouse": row.warehouse, "qty": qty * -1})
|
doc.append("entries", {"batch_no": batch_no, "warehouse": row.warehouse, "qty": qty * -1})
|
||||||
|
|
||||||
return doc.insert(ignore_permissions=True).name
|
return doc.insert(ignore_permissions=True).name
|
||||||
|
|
||||||
|
|||||||
@ -63,10 +63,6 @@ class StockReconciliation(StockController):
|
|||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
self.repost_future_sle_and_gle()
|
self.repost_future_sle_and_gle()
|
||||||
|
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
|
|
||||||
|
|
||||||
update_serial_nos_after_submit(self, "items")
|
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.validate_reserved_stock()
|
self.validate_reserved_stock()
|
||||||
self.ignore_linked_doctypes = (
|
self.ignore_linked_doctypes = (
|
||||||
@ -108,7 +104,7 @@ class StockReconciliation(StockController):
|
|||||||
|
|
||||||
for serial_no_row in serial_nos_details:
|
for serial_no_row in serial_nos_details:
|
||||||
serial_and_batch_bundle.append(
|
serial_and_batch_bundle.append(
|
||||||
"ledgers",
|
"entries",
|
||||||
{
|
{
|
||||||
"serial_no": serial_no_row.serial_no,
|
"serial_no": serial_no_row.serial_no,
|
||||||
"qty": -1,
|
"qty": -1,
|
||||||
@ -122,7 +118,7 @@ class StockReconciliation(StockController):
|
|||||||
|
|
||||||
for batch_no, qty in batch_nos_details.items():
|
for batch_no, qty in batch_nos_details.items():
|
||||||
serial_and_batch_bundle.append(
|
serial_and_batch_bundle.append(
|
||||||
"ledgers",
|
"entries",
|
||||||
{
|
{
|
||||||
"batch_no": batch_no,
|
"batch_no": batch_no,
|
||||||
"qty": qty * -1,
|
"qty": qty * -1,
|
||||||
@ -144,7 +140,7 @@ class StockReconciliation(StockController):
|
|||||||
bundle_doc.warehouse = item.warehouse
|
bundle_doc.warehouse = item.warehouse
|
||||||
bundle_doc.type_of_transaction = "Inward"
|
bundle_doc.type_of_transaction = "Inward"
|
||||||
|
|
||||||
for row in bundle_doc.ledgers:
|
for row in bundle_doc.entries:
|
||||||
if row.qty < 0:
|
if row.qty < 0:
|
||||||
row.qty = abs(row.qty)
|
row.qty = abs(row.qty)
|
||||||
|
|
||||||
@ -153,8 +149,7 @@ class StockReconciliation(StockController):
|
|||||||
|
|
||||||
row.is_outward = 0
|
row.is_outward = 0
|
||||||
|
|
||||||
bundle_doc.set_total_qty()
|
bundle_doc.calculate_qty_and_amount()
|
||||||
bundle_doc.set_avg_rate()
|
|
||||||
bundle_doc.flags.ignore_permissions = True
|
bundle_doc.flags.ignore_permissions = True
|
||||||
bundle_doc.save()
|
bundle_doc.save()
|
||||||
item.serial_and_batch_bundle = bundle_doc.name
|
item.serial_and_batch_bundle = bundle_doc.name
|
||||||
|
|||||||
@ -141,12 +141,8 @@ class SerialBatchBundle:
|
|||||||
self.add_serial_no_to_bundle(sn_doc, sr_nos, incoming_rate, batch_no)
|
self.add_serial_no_to_bundle(sn_doc, sr_nos, incoming_rate, batch_no)
|
||||||
elif self.item_details.has_batch_no:
|
elif self.item_details.has_batch_no:
|
||||||
self.add_batch_no_to_bundle(sn_doc, batch_no, incoming_rate)
|
self.add_batch_no_to_bundle(sn_doc, batch_no, incoming_rate)
|
||||||
sn_doc.save()
|
|
||||||
|
|
||||||
sn_doc.load_from_db()
|
|
||||||
sn_doc.flags.ignore_validate = True
|
|
||||||
sn_doc.flags.ignore_mandatory = True
|
|
||||||
|
|
||||||
|
sn_doc.save()
|
||||||
sn_doc.submit()
|
sn_doc.submit()
|
||||||
self.set_serial_and_batch_bundle(sn_doc)
|
self.set_serial_and_batch_bundle(sn_doc)
|
||||||
|
|
||||||
@ -174,39 +170,19 @@ class SerialBatchBundle:
|
|||||||
return is_rejected(self.sle.voucher_type, self.sle.voucher_detail_no, self.sle.warehouse)
|
return is_rejected(self.sle.voucher_type, self.sle.voucher_detail_no, self.sle.warehouse)
|
||||||
|
|
||||||
def add_serial_no_to_bundle(self, sn_doc, serial_nos, incoming_rate, batch_no=None):
|
def add_serial_no_to_bundle(self, sn_doc, serial_nos, incoming_rate, batch_no=None):
|
||||||
ledgers = []
|
|
||||||
|
|
||||||
fields = [
|
|
||||||
"name",
|
|
||||||
"serial_no",
|
|
||||||
"batch_no",
|
|
||||||
"warehouse",
|
|
||||||
"item_code",
|
|
||||||
"qty",
|
|
||||||
"incoming_rate",
|
|
||||||
"parent",
|
|
||||||
"parenttype",
|
|
||||||
"parentfield",
|
|
||||||
]
|
|
||||||
|
|
||||||
for serial_no in serial_nos:
|
for serial_no in serial_nos:
|
||||||
ledgers.append(
|
sn_doc.append(
|
||||||
(
|
"entries",
|
||||||
frappe.generate_hash("Serial and Batch Ledger", 10),
|
{
|
||||||
serial_no,
|
"serial_no": serial_no,
|
||||||
batch_no,
|
"qty": 1,
|
||||||
self.warehouse,
|
"incoming_rate": incoming_rate,
|
||||||
self.item_details.item_code,
|
"batch_no": batch_no,
|
||||||
1,
|
"warehouse": self.warehouse,
|
||||||
incoming_rate,
|
"is_outward": 0,
|
||||||
sn_doc.name,
|
},
|
||||||
sn_doc.doctype,
|
|
||||||
"ledgers",
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
frappe.db.bulk_insert("Serial and Batch Ledger", fields=fields, values=set(ledgers))
|
|
||||||
|
|
||||||
def add_batch_no_to_bundle(self, sn_doc, batch_no, incoming_rate):
|
def add_batch_no_to_bundle(self, sn_doc, batch_no, incoming_rate):
|
||||||
stock_value_difference = flt(self.sle.actual_qty) * flt(incoming_rate)
|
stock_value_difference = flt(self.sle.actual_qty) * flt(incoming_rate)
|
||||||
|
|
||||||
@ -214,7 +190,7 @@ class SerialBatchBundle:
|
|||||||
stock_value_difference *= -1
|
stock_value_difference *= -1
|
||||||
|
|
||||||
sn_doc.append(
|
sn_doc.append(
|
||||||
"ledgers",
|
"entries",
|
||||||
{
|
{
|
||||||
"batch_no": batch_no,
|
"batch_no": batch_no,
|
||||||
"qty": self.sle.actual_qty,
|
"qty": self.sle.actual_qty,
|
||||||
@ -336,14 +312,14 @@ class SerialBatchBundle:
|
|||||||
).run()
|
).run()
|
||||||
|
|
||||||
def set_batch_no_in_serial_nos(self):
|
def set_batch_no_in_serial_nos(self):
|
||||||
ledgers = frappe.get_all(
|
entries = frappe.get_all(
|
||||||
"Serial and Batch Ledger",
|
"Serial and Batch Entry",
|
||||||
fields=["serial_no", "batch_no"],
|
fields=["serial_no", "batch_no"],
|
||||||
filters={"parent": self.sle.serial_and_batch_bundle},
|
filters={"parent": self.sle.serial_and_batch_bundle},
|
||||||
)
|
)
|
||||||
|
|
||||||
batch_serial_nos = {}
|
batch_serial_nos = {}
|
||||||
for ledger in ledgers:
|
for ledger in entries:
|
||||||
batch_serial_nos.setdefault(ledger.batch_no, []).append(ledger.serial_no)
|
batch_serial_nos.setdefault(ledger.batch_no, []).append(ledger.serial_no)
|
||||||
|
|
||||||
for batch_no, serial_nos in batch_serial_nos.items():
|
for batch_no, serial_nos in batch_serial_nos.items():
|
||||||
@ -360,9 +336,9 @@ def get_serial_nos(serial_and_batch_bundle, check_outward=True):
|
|||||||
if check_outward:
|
if check_outward:
|
||||||
filters["is_outward"] = 1
|
filters["is_outward"] = 1
|
||||||
|
|
||||||
ledgers = frappe.get_all("Serial and Batch Ledger", fields=["serial_no"], filters=filters)
|
entries = frappe.get_all("Serial and Batch Entry", fields=["serial_no"], filters=filters)
|
||||||
|
|
||||||
return [d.serial_no for d in ledgers]
|
return [d.serial_no for d in entries]
|
||||||
|
|
||||||
|
|
||||||
class SerialNoBundleValuation(DeprecatedSerialNoValuation):
|
class SerialNoBundleValuation(DeprecatedSerialNoValuation):
|
||||||
@ -380,12 +356,12 @@ class SerialNoBundleValuation(DeprecatedSerialNoValuation):
|
|||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
ledgers = self.get_serial_no_ledgers()
|
entries = self.get_serial_no_ledgers()
|
||||||
|
|
||||||
self.serial_no_incoming_rate = defaultdict(float)
|
self.serial_no_incoming_rate = defaultdict(float)
|
||||||
self.stock_value_change = 0.0
|
self.stock_value_change = 0.0
|
||||||
|
|
||||||
for ledger in ledgers:
|
for ledger in entries:
|
||||||
self.stock_value_change += ledger.incoming_rate * -1
|
self.stock_value_change += ledger.incoming_rate * -1
|
||||||
self.serial_no_incoming_rate[ledger.serial_no] = ledger.incoming_rate
|
self.serial_no_incoming_rate[ledger.serial_no] = ledger.incoming_rate
|
||||||
|
|
||||||
@ -403,7 +379,7 @@ class SerialNoBundleValuation(DeprecatedSerialNoValuation):
|
|||||||
), child.name, child.serial_no, child.warehouse
|
), child.name, child.serial_no, child.warehouse
|
||||||
FROM
|
FROM
|
||||||
`tabSerial and Batch Bundle` as parent,
|
`tabSerial and Batch Bundle` as parent,
|
||||||
`tabSerial and Batch Ledger` as child
|
`tabSerial and Batch Entry` as child
|
||||||
WHERE
|
WHERE
|
||||||
parent.name = child.parent
|
parent.name = child.parent
|
||||||
AND child.serial_no IN ({', '.join([frappe.db.escape(s) for s in serial_nos])})
|
AND child.serial_no IN ({', '.join([frappe.db.escape(s) for s in serial_nos])})
|
||||||
@ -428,7 +404,7 @@ class SerialNoBundleValuation(DeprecatedSerialNoValuation):
|
|||||||
SELECT
|
SELECT
|
||||||
ledger.serial_no, ledger.incoming_rate, ledger.warehouse
|
ledger.serial_no, ledger.incoming_rate, ledger.warehouse
|
||||||
FROM
|
FROM
|
||||||
`tabSerial and Batch Ledger` AS ledger,
|
`tabSerial and Batch Entry` AS ledger,
|
||||||
({subquery}) AS SubQuery
|
({subquery}) AS SubQuery
|
||||||
WHERE
|
WHERE
|
||||||
ledger.name = SubQuery.name
|
ledger.name = SubQuery.name
|
||||||
@ -508,11 +484,11 @@ class BatchNoBundleValuation(DeprecatedBatchNoValuation):
|
|||||||
"Serial and Batch Bundle", self.sle.serial_and_batch_bundle, "total_amount"
|
"Serial and Batch Bundle", self.sle.serial_and_batch_bundle, "total_amount"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
ledgers = self.get_batch_no_ledgers()
|
entries = self.get_batch_no_ledgers()
|
||||||
|
|
||||||
self.batch_avg_rate = defaultdict(float)
|
self.batch_avg_rate = defaultdict(float)
|
||||||
self.available_qty = defaultdict(float)
|
self.available_qty = defaultdict(float)
|
||||||
for ledger in ledgers:
|
for ledger in entries:
|
||||||
self.batch_avg_rate[ledger.batch_no] += flt(ledger.incoming_rate) / flt(ledger.qty)
|
self.batch_avg_rate[ledger.batch_no] += flt(ledger.incoming_rate) / flt(ledger.qty)
|
||||||
self.available_qty[ledger.batch_no] += flt(ledger.qty)
|
self.available_qty[ledger.batch_no] += flt(ledger.qty)
|
||||||
|
|
||||||
@ -521,7 +497,7 @@ class BatchNoBundleValuation(DeprecatedBatchNoValuation):
|
|||||||
|
|
||||||
def get_batch_no_ledgers(self) -> List[dict]:
|
def get_batch_no_ledgers(self) -> List[dict]:
|
||||||
parent = frappe.qb.DocType("Serial and Batch Bundle")
|
parent = frappe.qb.DocType("Serial and Batch Bundle")
|
||||||
child = frappe.qb.DocType("Serial and Batch Ledger")
|
child = frappe.qb.DocType("Serial and Batch Entry")
|
||||||
|
|
||||||
batch_nos = list(self.batch_nos.keys())
|
batch_nos = list(self.batch_nos.keys())
|
||||||
|
|
||||||
@ -554,13 +530,13 @@ class BatchNoBundleValuation(DeprecatedBatchNoValuation):
|
|||||||
if self.sle.get("batch_nos"):
|
if self.sle.get("batch_nos"):
|
||||||
return self.sle.batch_nos
|
return self.sle.batch_nos
|
||||||
|
|
||||||
ledgers = frappe.get_all(
|
entries = frappe.get_all(
|
||||||
"Serial and Batch Ledger",
|
"Serial and Batch Entry",
|
||||||
fields=["batch_no", "qty", "name"],
|
fields=["batch_no", "qty", "name"],
|
||||||
filters={"parent": self.sle.serial_and_batch_bundle, "is_outward": 1},
|
filters={"parent": self.sle.serial_and_batch_bundle, "is_outward": 1},
|
||||||
)
|
)
|
||||||
|
|
||||||
return {d.batch_no: d for d in ledgers}
|
return {d.batch_no: d for d in entries}
|
||||||
|
|
||||||
def set_stock_value_difference(self):
|
def set_stock_value_difference(self):
|
||||||
self.stock_value_change = 0
|
self.stock_value_change = 0
|
||||||
@ -568,7 +544,7 @@ class BatchNoBundleValuation(DeprecatedBatchNoValuation):
|
|||||||
stock_value_change = self.batch_avg_rate[batch_no] * ledger.qty
|
stock_value_change = self.batch_avg_rate[batch_no] * ledger.qty
|
||||||
self.stock_value_change += stock_value_change
|
self.stock_value_change += stock_value_change
|
||||||
frappe.db.set_value(
|
frappe.db.set_value(
|
||||||
"Serial and Batch Ledger", ledger.name, "stock_value_difference", stock_value_change
|
"Serial and Batch Entry", ledger.name, "stock_value_difference", stock_value_change
|
||||||
)
|
)
|
||||||
|
|
||||||
def calculate_valuation_rate(self):
|
def calculate_valuation_rate(self):
|
||||||
@ -638,7 +614,7 @@ def get_batches_from_stock_entries(work_order):
|
|||||||
|
|
||||||
def set_batch_details_from_package(ids, batches):
|
def set_batch_details_from_package(ids, batches):
|
||||||
entries = frappe.get_all(
|
entries = frappe.get_all(
|
||||||
"Serial and Batch Ledger",
|
"Serial and Batch Entry",
|
||||||
filters={"parent": ("in", ids), "is_outward": 0},
|
filters={"parent": ("in", ids), "is_outward": 0},
|
||||||
fields=["batch_no", "qty"],
|
fields=["batch_no", "qty"],
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1370,7 +1370,7 @@ def get_batch_incoming_rate(
|
|||||||
):
|
):
|
||||||
|
|
||||||
sle = frappe.qb.DocType("Stock Ledger Entry")
|
sle = frappe.qb.DocType("Stock Ledger Entry")
|
||||||
batch_ledger = frappe.qb.DocType("Serial and Batch Ledger")
|
batch_ledger = frappe.qb.DocType("Serial and Batch Entry")
|
||||||
|
|
||||||
timestamp_condition = CombineDatetime(sle.posting_date, sle.posting_time) < CombineDatetime(
|
timestamp_condition = CombineDatetime(sle.posting_date, sle.posting_time) < CombineDatetime(
|
||||||
posting_date, posting_time
|
posting_date, posting_time
|
||||||
@ -1382,7 +1382,7 @@ def get_batch_incoming_rate(
|
|||||||
) & (sle.creation < creation)
|
) & (sle.creation < creation)
|
||||||
|
|
||||||
batches = frappe.get_all(
|
batches = frappe.get_all(
|
||||||
"Serial and Batch Ledger", fields=["batch_no"], filters={"parent": serial_and_batch_bundle}
|
"Serial and Batch Entry", fields=["batch_no"], filters={"parent": serial_and_batch_bundle}
|
||||||
)
|
)
|
||||||
|
|
||||||
batch_details = (
|
batch_details = (
|
||||||
|
|||||||
@ -95,11 +95,6 @@ class SubcontractingReceipt(SubcontractingController):
|
|||||||
self.set_subcontracting_order_status()
|
self.set_subcontracting_order_status()
|
||||||
self.set_consumed_qty_in_subcontract_order()
|
self.set_consumed_qty_in_subcontract_order()
|
||||||
self.update_stock_ledger()
|
self.update_stock_ledger()
|
||||||
|
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
|
|
||||||
|
|
||||||
update_serial_nos_after_submit(self, "items")
|
|
||||||
|
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
self.repost_future_sle_and_gle()
|
self.repost_future_sle_and_gle()
|
||||||
self.update_status()
|
self.update_status()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user