Merge branch 'develop' into serialized-item-consumption
This commit is contained in:
commit
7a15f85f22
@ -434,7 +434,7 @@ def get_pi_matching_query(amount_condition):
|
||||
|
||||
def get_ec_matching_query(bank_account, company, amount_condition):
|
||||
# get matching Expense Claim query
|
||||
mode_of_payments = [x["parent"] for x in frappe.db.get_list("Mode of Payment Account",
|
||||
mode_of_payments = [x["parent"] for x in frappe.db.get_all("Mode of Payment Account",
|
||||
filters={"default_account": bank_account}, fields=["parent"])]
|
||||
mode_of_payments = '(\'' + '\', \''.join(mode_of_payments) + '\' )'
|
||||
company_currency = get_company_currency(company)
|
||||
|
@ -339,7 +339,7 @@ class PaymentEntry(AccountsController):
|
||||
for k, v in no_oustanding_refs.items():
|
||||
frappe.msgprint(
|
||||
_("{} - {} now have {} as they had no outstanding amount left before submitting the Payment Entry.")
|
||||
.format(k, frappe.bold(", ".join(d.reference_name for d in v)), frappe.bold("negative outstanding amount"))
|
||||
.format(_(k), frappe.bold(", ".join(d.reference_name for d in v)), frappe.bold(_("negative outstanding amount")))
|
||||
+ "<br><br>" + _("If this is undesirable please cancel the corresponding Payment Entry."),
|
||||
title=_("Warning"), indicator="orange")
|
||||
|
||||
@ -611,7 +611,7 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
if not total_negative_outstanding:
|
||||
frappe.throw(_("Cannot {0} {1} {2} without any negative outstanding invoice")
|
||||
.format(self.payment_type, ("to" if self.party_type=="Customer" else "from"),
|
||||
.format(_(self.payment_type), (_("to") if self.party_type=="Customer" else _("from")),
|
||||
self.party_type), InvalidPaymentEntry)
|
||||
|
||||
elif paid_amount - additional_charges > total_negative_outstanding:
|
||||
@ -1092,7 +1092,7 @@ def get_outstanding_reference_documents(args):
|
||||
|
||||
if not data:
|
||||
frappe.msgprint(_("No outstanding invoices found for the {0} {1} which qualify the filters you have specified.")
|
||||
.format(args.get("party_type").lower(), frappe.bold(args.get("party"))))
|
||||
.format(_(args.get("party_type")).lower(), frappe.bold(args.get("party"))))
|
||||
|
||||
return data
|
||||
|
||||
|
@ -728,7 +728,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"account": self.stock_received_but_not_billed,
|
||||
"against": self.supplier,
|
||||
"debit": flt(item.item_tax_amount, item.precision("item_tax_amount")),
|
||||
"remarks": self.remarks or "Accounting Entry for Stock",
|
||||
"remarks": self.remarks or _("Accounting Entry for Stock"),
|
||||
"cost_center": self.cost_center,
|
||||
"project": item.project or self.project
|
||||
}, item=item)
|
||||
@ -936,7 +936,7 @@ class PurchaseInvoice(BuyingController):
|
||||
"cost_center": tax.cost_center,
|
||||
"against": self.supplier,
|
||||
"credit": valuation_tax[tax.name],
|
||||
"remarks": self.remarks or "Accounting Entry for Stock"
|
||||
"remarks": self.remarks or _("Accounting Entry for Stock")
|
||||
}, item=tax))
|
||||
|
||||
@property
|
||||
|
@ -978,7 +978,7 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
}
|
||||
|
||||
if (frm.doc.is_debit_note) {
|
||||
frm.set_df_property('return_against', 'label', 'Adjustment Against');
|
||||
frm.set_df_property('return_against', 'label', __('Adjustment Against'));
|
||||
}
|
||||
|
||||
if (frappe.boot.active_domains.includes("Healthcare")) {
|
||||
@ -988,10 +988,10 @@ frappe.ui.form.on('Sales Invoice', {
|
||||
if (cint(frm.doc.docstatus==0) && cur_frm.page.current_view_name!=="pos" && !frm.doc.is_return) {
|
||||
frm.add_custom_button(__('Healthcare Services'), function() {
|
||||
get_healthcare_services_to_invoice(frm);
|
||||
},"Get Items From");
|
||||
},__("Get Items From"));
|
||||
frm.add_custom_button(__('Prescriptions'), function() {
|
||||
get_drugs_to_invoice(frm);
|
||||
},"Get Items From");
|
||||
},__("Get Items From"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -134,7 +134,7 @@ class StockController(AccountsController):
|
||||
"against": expense_account,
|
||||
"cost_center": item_row.cost_center,
|
||||
"project": item_row.project or self.get('project'),
|
||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"debit": flt(sle.stock_value_difference, precision),
|
||||
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
|
||||
}, warehouse_account[sle.warehouse]["account_currency"], item=item_row))
|
||||
@ -143,7 +143,7 @@ class StockController(AccountsController):
|
||||
"account": expense_account,
|
||||
"against": warehouse_account[sle.warehouse]["account"],
|
||||
"cost_center": item_row.cost_center,
|
||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"credit": flt(sle.stock_value_difference, precision),
|
||||
"project": item_row.get("project") or self.get("project"),
|
||||
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No"
|
||||
|
@ -248,20 +248,18 @@ doc_events = {
|
||||
"validate": "erpnext.regional.india.utils.validate_tax_category"
|
||||
},
|
||||
"Sales Invoice": {
|
||||
"after_insert": "erpnext.regional.saudi_arabia.utils.create_qr_code",
|
||||
"on_submit": [
|
||||
"erpnext.regional.create_transaction_log",
|
||||
"erpnext.regional.italy.utils.sales_invoice_on_submit",
|
||||
"erpnext.regional.saudi_arabia.utils.create_qr_code",
|
||||
"erpnext.erpnext_integrations.taxjar_integration.create_transaction"
|
||||
],
|
||||
"on_cancel": [
|
||||
"erpnext.regional.italy.utils.sales_invoice_on_cancel",
|
||||
"erpnext.erpnext_integrations.taxjar_integration.delete_transaction"
|
||||
],
|
||||
"on_trash": [
|
||||
"erpnext.regional.check_deletion_permission",
|
||||
"erpnext.erpnext_integrations.taxjar_integration.delete_transaction",
|
||||
"erpnext.regional.saudi_arabia.utils.delete_qr_code_file"
|
||||
],
|
||||
"on_trash": "erpnext.regional.check_deletion_permission",
|
||||
"validate": [
|
||||
"erpnext.regional.india.utils.validate_document_name",
|
||||
"erpnext.regional.india.utils.update_taxable_values"
|
||||
|
@ -5,6 +5,7 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.query_builder.functions import Sum
|
||||
from frappe.utils import flt, nowdate
|
||||
|
||||
import erpnext
|
||||
@ -41,24 +42,34 @@ class EmployeeAdvance(Document):
|
||||
self.status = "Cancelled"
|
||||
|
||||
def set_total_advance_paid(self):
|
||||
paid_amount = frappe.db.sql("""
|
||||
select ifnull(sum(debit), 0) as paid_amount
|
||||
from `tabGL Entry`
|
||||
where against_voucher_type = 'Employee Advance'
|
||||
and against_voucher = %s
|
||||
and party_type = 'Employee'
|
||||
and party = %s
|
||||
""", (self.name, self.employee), as_dict=1)[0].paid_amount
|
||||
gle = frappe.qb.DocType("GL Entry")
|
||||
|
||||
return_amount = frappe.db.sql("""
|
||||
select ifnull(sum(credit), 0) as return_amount
|
||||
from `tabGL Entry`
|
||||
where against_voucher_type = 'Employee Advance'
|
||||
and voucher_type != 'Expense Claim'
|
||||
and against_voucher = %s
|
||||
and party_type = 'Employee'
|
||||
and party = %s
|
||||
""", (self.name, self.employee), as_dict=1)[0].return_amount
|
||||
paid_amount = (
|
||||
frappe.qb.from_(gle)
|
||||
.select(Sum(gle.debit).as_("paid_amount"))
|
||||
.where(
|
||||
(gle.against_voucher_type == 'Employee Advance')
|
||||
& (gle.against_voucher == self.name)
|
||||
& (gle.party_type == 'Employee')
|
||||
& (gle.party == self.employee)
|
||||
& (gle.docstatus == 1)
|
||||
& (gle.is_cancelled == 0)
|
||||
)
|
||||
).run(as_dict=True)[0].paid_amount or 0
|
||||
|
||||
return_amount = (
|
||||
frappe.qb.from_(gle)
|
||||
.select(Sum(gle.credit).as_("return_amount"))
|
||||
.where(
|
||||
(gle.against_voucher_type == 'Employee Advance')
|
||||
& (gle.voucher_type != 'Expense Claim')
|
||||
& (gle.against_voucher == self.name)
|
||||
& (gle.party_type == 'Employee')
|
||||
& (gle.party == self.employee)
|
||||
& (gle.docstatus == 1)
|
||||
& (gle.is_cancelled == 0)
|
||||
)
|
||||
).run(as_dict=True)[0].return_amount or 0
|
||||
|
||||
if paid_amount != 0:
|
||||
paid_amount = flt(paid_amount) / flt(self.exchange_rate)
|
||||
|
@ -34,6 +34,24 @@ class TestEmployeeAdvance(unittest.TestCase):
|
||||
journal_entry1 = make_payment_entry(advance)
|
||||
self.assertRaises(EmployeeAdvanceOverPayment, journal_entry1.submit)
|
||||
|
||||
def test_paid_amount_on_pe_cancellation(self):
|
||||
employee_name = make_employee("_T@employe.advance")
|
||||
advance = make_employee_advance(employee_name)
|
||||
|
||||
pe = make_payment_entry(advance)
|
||||
pe.submit()
|
||||
|
||||
advance.reload()
|
||||
|
||||
self.assertEqual(advance.paid_amount, 1000)
|
||||
self.assertEqual(advance.status, "Paid")
|
||||
|
||||
pe.cancel()
|
||||
advance.reload()
|
||||
|
||||
self.assertEqual(advance.paid_amount, 0)
|
||||
self.assertEqual(advance.status, "Unpaid")
|
||||
|
||||
def test_repay_unclaimed_amount_from_salary(self):
|
||||
employee_name = make_employee("_T@employe.advance")
|
||||
advance = make_employee_advance(employee_name, {"repay_unclaimed_amount_from_salary": 1})
|
||||
|
@ -94,7 +94,6 @@
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Sanctioned Amount",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "sanctioned_amount",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
@ -120,7 +119,7 @@
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-09-18 17:26:09.703215",
|
||||
"modified": "2021-11-26 14:23:45.539922",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Expense Claim Detail",
|
||||
|
@ -178,8 +178,9 @@
|
||||
},
|
||||
{
|
||||
"fieldname": "batch_size",
|
||||
"fieldtype": "Int",
|
||||
"label": "Batch Size"
|
||||
"fieldtype": "Float",
|
||||
"label": "Batch Size",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "sequence_id",
|
||||
@ -200,7 +201,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-11-24 04:52:54.295168",
|
||||
"modified": "2021-11-29 16:37:18.824489",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Work Order Operation",
|
||||
|
@ -89,7 +89,7 @@ def get_bom_stock(filters):
|
||||
GROUP BY bom_item.item_code""".format(qty_field=qty_field, table=table, conditions=conditions, bom=bom), as_dict=1)
|
||||
|
||||
def get_manufacturer_records():
|
||||
details = frappe.get_list('Item Manufacturer', fields = ["manufacturer", "manufacturer_part_no", "parent"])
|
||||
details = frappe.get_all('Item Manufacturer', fields = ["manufacturer", "manufacturer_part_no", "parent"])
|
||||
manufacture_details = frappe._dict()
|
||||
for detail in details:
|
||||
dic = manufacture_details.setdefault(detail.get('parent'), {})
|
||||
|
@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
/* eslint-disable */
|
||||
|
||||
frappe.query_reports["Work Order Consumed Materials"] = {
|
||||
"filters": [
|
||||
{
|
||||
label: __("Company"),
|
||||
fieldname: "company",
|
||||
fieldtype: "Link",
|
||||
options: "Company",
|
||||
default: frappe.defaults.get_user_default("Company"),
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
label: __("From Date"),
|
||||
fieldname:"from_date",
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.add_months(frappe.datetime.get_today(), -1),
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname:"to_date",
|
||||
label: __("To Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.get_today(),
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
label: __("Work Order"),
|
||||
fieldname: "name",
|
||||
fieldtype: "Link",
|
||||
options: "Work Order",
|
||||
get_query: function() {
|
||||
return {
|
||||
filters: {
|
||||
status: ["in", ["In Process", "Completed", "Stopped"]]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: __("Production Item"),
|
||||
fieldname: "production_item",
|
||||
fieldtype: "Link",
|
||||
depends_on: "eval: !doc.name",
|
||||
options: "Item"
|
||||
},
|
||||
{
|
||||
label: __("Status"),
|
||||
fieldname: "status",
|
||||
fieldtype: "Select",
|
||||
options: ["In Process", "Completed", "Stopped"]
|
||||
},
|
||||
{
|
||||
label: __("Excess Materials Consumed"),
|
||||
fieldname: "show_extra_consumed_materials",
|
||||
fieldtype: "Check"
|
||||
}
|
||||
],
|
||||
"formatter": function(value, row, column, data, default_formatter) {
|
||||
value = default_formatter(value, row, column, data);
|
||||
|
||||
if (column.fieldname == "raw_material_name" && data && data.extra_consumed_qty > 0 ) {
|
||||
value = `<div style="color:red">${value}</div>`;
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
};
|
@ -0,0 +1,30 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"columns": [],
|
||||
"creation": "2021-11-22 17:36:11.886939",
|
||||
"disable_prepared_report": 0,
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"filters": [],
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"letter_head": "Gadgets International",
|
||||
"modified": "2021-11-22 17:36:14.999091",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Work Order Consumed Materials",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"ref_doctype": "Work Order",
|
||||
"report_name": "Work Order Consumed Materials",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Manufacturing User"
|
||||
},
|
||||
{
|
||||
"role": "Stock User"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
columns, data = [], []
|
||||
columns = get_columns()
|
||||
data = get_data(filters)
|
||||
|
||||
return columns, data
|
||||
|
||||
def get_data(report_filters):
|
||||
fields = get_fields()
|
||||
filters = get_filter_condition(report_filters)
|
||||
|
||||
wo_items = {}
|
||||
for d in frappe.get_all("Work Order", filters = filters, fields=fields):
|
||||
d.extra_consumed_qty = 0.0
|
||||
if d.consumed_qty and d.consumed_qty > d.required_qty:
|
||||
d.extra_consumed_qty = d.consumed_qty - d.required_qty
|
||||
|
||||
if d.extra_consumed_qty or not report_filters.show_extra_consumed_materials:
|
||||
wo_items.setdefault((d.name, d.production_item), []).append(d)
|
||||
|
||||
data = []
|
||||
for key, wo_data in wo_items.items():
|
||||
for index, row in enumerate(wo_data):
|
||||
if index != 0:
|
||||
#If one work order has multiple raw materials then show parent data in the first row only
|
||||
for field in ["name", "status", "production_item", "qty", "produced_qty"]:
|
||||
row[field] = ""
|
||||
|
||||
data.append(row)
|
||||
|
||||
return data
|
||||
|
||||
def get_fields():
|
||||
return ["`tabWork Order Item`.`parent`", "`tabWork Order Item`.`item_code` as raw_material_item_code",
|
||||
"`tabWork Order Item`.`item_name` as raw_material_name", "`tabWork Order Item`.`required_qty`",
|
||||
"`tabWork Order Item`.`transferred_qty`", "`tabWork Order Item`.`consumed_qty`", "`tabWork Order`.`status`",
|
||||
"`tabWork Order`.`name`", "`tabWork Order`.`production_item`", "`tabWork Order`.`qty`",
|
||||
"`tabWork Order`.`produced_qty`"]
|
||||
|
||||
def get_filter_condition(report_filters):
|
||||
filters = {
|
||||
"docstatus": 1, "status": ("in", ["In Process", "Completed", "Stopped"]),
|
||||
"creation": ("between", [report_filters.from_date, report_filters.to_date])
|
||||
}
|
||||
|
||||
for field in ["name", "production_item", "company", "status"]:
|
||||
value = report_filters.get(field)
|
||||
if value:
|
||||
key = f"`{field}`"
|
||||
filters.update({key: value})
|
||||
|
||||
return filters
|
||||
|
||||
def get_columns():
|
||||
return [
|
||||
{
|
||||
"label": _("Id"),
|
||||
"fieldname": "name",
|
||||
"fieldtype": "Link",
|
||||
"options": "Work Order",
|
||||
"width": 80
|
||||
},
|
||||
{
|
||||
"label": _("Status"),
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Data",
|
||||
"width": 80
|
||||
},
|
||||
{
|
||||
"label": _("Production Item"),
|
||||
"fieldname": "production_item",
|
||||
"fieldtype": "Link",
|
||||
"options": "Item",
|
||||
"width": 130
|
||||
},
|
||||
{
|
||||
"label": _("Qty to Produce"),
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 120
|
||||
},
|
||||
{
|
||||
"label": _("Produced Qty"),
|
||||
"fieldname": "produced_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 110
|
||||
},
|
||||
{
|
||||
"label": _("Raw Material Item"),
|
||||
"fieldname": "raw_material_item_code",
|
||||
"fieldtype": "Link",
|
||||
"options": "Item",
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"label": _("Item Name"),
|
||||
"fieldname": "raw_material_name",
|
||||
"width": 130
|
||||
},
|
||||
{
|
||||
"label": _("Required Qty"),
|
||||
"fieldname": "required_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Transferred Qty"),
|
||||
"fieldname": "transferred_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Consumed Qty"),
|
||||
"fieldname": "consumed_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Extra Consumed Qty"),
|
||||
"fieldname": "extra_consumed_qty",
|
||||
"fieldtype": "Float",
|
||||
"width": 100
|
||||
}
|
||||
]
|
@ -1,10 +1,6 @@
|
||||
{
|
||||
"charts": [
|
||||
{
|
||||
"chart_name": "Produced Quantity"
|
||||
}
|
||||
],
|
||||
"content": "[{\"type\": \"onboarding\", \"data\": {\"onboarding_name\":\"Manufacturing\", \"col\": 12}}, {\"type\": \"chart\", \"data\": {\"chart_name\": null, \"col\": 12}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Your Shortcuts\", \"level\": 4, \"col\": 12}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Item\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"BOM\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Work Order\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Production Plan\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Forecasting\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Work Order Summary\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"BOM Stock Report\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Production Planning Report\", \"col\": 4}}, {\"type\": \"shortcut\", \"data\": {\"shortcut_name\": \"Dashboard\", \"col\": 4}}, {\"type\": \"spacer\", \"data\": {\"col\": 12}}, {\"type\": \"header\", \"data\": {\"text\": \"Reports & Masters\", \"level\": 4, \"col\": 12}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Production\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Bill of Materials\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Reports\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Tools\", \"col\": 4}}, {\"type\": \"card\", \"data\": {\"card_name\": \"Settings\", \"col\": 4}}]",
|
||||
"charts": [],
|
||||
"content": "[{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Work Order\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Plan\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Forecasting\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Work Order Summary\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM Stock Report\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Planning Report\",\"col\":4}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":4}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"level\":4,\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Production\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Bill of Materials\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
|
||||
"creation": "2020-03-02 17:11:37.032604",
|
||||
"docstatus": 0,
|
||||
"doctype": "Workspace",
|
||||
@ -140,14 +136,6 @@
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Reports",
|
||||
"link_count": 0,
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "Work Order",
|
||||
"hidden": 0,
|
||||
@ -295,9 +283,126 @@
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Reports",
|
||||
"link_count": 10,
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "Work Order",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Production Planning Report",
|
||||
"link_count": 0,
|
||||
"link_to": "Production Planning Report",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Work Order",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Work Order Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Work Order Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Quality Inspection",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Quality Inspection Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Quality Inspection Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Downtime Entry",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Downtime Analysis",
|
||||
"link_count": 0,
|
||||
"link_to": "Downtime Analysis",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Job Card",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Job Card Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Job Card Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "BOM",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "BOM Search",
|
||||
"link_count": 0,
|
||||
"link_to": "BOM Search",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "BOM",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "BOM Stock Report",
|
||||
"link_count": 0,
|
||||
"link_to": "BOM Stock Report",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Work Order",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Production Analytics",
|
||||
"link_count": 0,
|
||||
"link_to": "Production Analytics",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "BOM",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "BOM Operations Time",
|
||||
"link_count": 0,
|
||||
"link_to": "BOM Operations Time",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Work Order Consumed Materials",
|
||||
"link_count": 0,
|
||||
"link_to": "Work Order Consumed Materials",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2021-08-05 12:16:00.825742",
|
||||
"modified": "2021-11-22 17:55:03.524496",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Manufacturing",
|
||||
|
@ -287,7 +287,7 @@ erpnext.patches.v14_0.delete_einvoicing_doctypes
|
||||
erpnext.patches.v13_0.custom_fields_for_taxjar_integration #08-11-2021
|
||||
erpnext.patches.v13_0.set_operation_time_based_on_operating_cost
|
||||
erpnext.patches.v13_0.validate_options_for_data_field
|
||||
erpnext.patches.v13_0.create_gst_payment_entry_fields
|
||||
erpnext.patches.v13_0.create_gst_payment_entry_fields #27-11-2021
|
||||
erpnext.patches.v14_0.delete_shopify_doctypes
|
||||
erpnext.patches.v13_0.fix_invoice_statuses
|
||||
erpnext.patches.v13_0.replace_supplier_item_group_with_party_specific_item
|
||||
|
@ -9,24 +9,29 @@ def execute():
|
||||
frappe.reload_doc('accounts', 'doctype', 'advance_taxes_and_charges')
|
||||
frappe.reload_doc('accounts', 'doctype', 'payment_entry')
|
||||
|
||||
custom_fields = {
|
||||
'Payment Entry': [
|
||||
dict(fieldname='gst_section', label='GST Details', fieldtype='Section Break', insert_after='deductions',
|
||||
print_hide=1, collapsible=1),
|
||||
dict(fieldname='company_address', label='Company Address', fieldtype='Link', insert_after='gst_section',
|
||||
print_hide=1, options='Address'),
|
||||
dict(fieldname='company_gstin', label='Company GSTIN',
|
||||
fieldtype='Data', insert_after='company_address',
|
||||
fetch_from='company_address.gstin', print_hide=1, read_only=1),
|
||||
dict(fieldname='place_of_supply', label='Place of Supply',
|
||||
fieldtype='Data', insert_after='company_gstin',
|
||||
print_hide=1, read_only=1),
|
||||
dict(fieldname='customer_address', label='Customer Address', fieldtype='Link', insert_after='place_of_supply',
|
||||
print_hide=1, options='Address', depends_on = 'eval:doc.party_type == "Customer"'),
|
||||
dict(fieldname='customer_gstin', label='Customer GSTIN',
|
||||
fieldtype='Data', insert_after='customer_address',
|
||||
fetch_from='customer_address.gstin', print_hide=1, read_only=1)
|
||||
]
|
||||
}
|
||||
if frappe.db.exists('Company', {'country': 'India'}):
|
||||
custom_fields = {
|
||||
'Payment Entry': [
|
||||
dict(fieldname='gst_section', label='GST Details', fieldtype='Section Break', insert_after='deductions',
|
||||
print_hide=1, collapsible=1),
|
||||
dict(fieldname='company_address', label='Company Address', fieldtype='Link', insert_after='gst_section',
|
||||
print_hide=1, options='Address'),
|
||||
dict(fieldname='company_gstin', label='Company GSTIN',
|
||||
fieldtype='Data', insert_after='company_address',
|
||||
fetch_from='company_address.gstin', print_hide=1, read_only=1),
|
||||
dict(fieldname='place_of_supply', label='Place of Supply',
|
||||
fieldtype='Data', insert_after='company_gstin',
|
||||
print_hide=1, read_only=1),
|
||||
dict(fieldname='customer_address', label='Customer Address', fieldtype='Link', insert_after='place_of_supply',
|
||||
print_hide=1, options='Address', depends_on = 'eval:doc.party_type == "Customer"'),
|
||||
dict(fieldname='customer_gstin', label='Customer GSTIN',
|
||||
fieldtype='Data', insert_after='customer_address',
|
||||
fetch_from='customer_address.gstin', print_hide=1, read_only=1)
|
||||
]
|
||||
}
|
||||
|
||||
create_custom_fields(custom_fields, update=True)
|
||||
create_custom_fields(custom_fields, update=True)
|
||||
else:
|
||||
fields = ['gst_section', 'company_address', 'company_gstin', 'place_of_supply', 'customer_address', 'customer_gstin']
|
||||
for field in fields:
|
||||
frappe.delete_doc_if_exists("Custom Field", f"Payment Entry-{field}")
|
@ -569,17 +569,17 @@ def get_item_list(data, doc, hsn_wise=False):
|
||||
}
|
||||
item_data_attrs = ['sgstRate', 'cgstRate', 'igstRate', 'cessRate', 'cessNonAdvol']
|
||||
hsn_wise_charges, hsn_taxable_amount = get_itemised_tax_breakup_data(doc, account_wise=True, hsn_wise=hsn_wise)
|
||||
for hsn_code, taxable_amount in hsn_taxable_amount.items():
|
||||
for item_or_hsn, taxable_amount in hsn_taxable_amount.items():
|
||||
item_data = frappe._dict()
|
||||
if not hsn_code:
|
||||
if not item_or_hsn:
|
||||
frappe.throw(_('GST HSN Code does not exist for one or more items'))
|
||||
item_data.hsnCode = int(hsn_code)
|
||||
item_data.hsnCode = int(item_or_hsn) if hsn_wise else item_or_hsn
|
||||
item_data.taxableAmount = taxable_amount
|
||||
item_data.qtyUnit = ""
|
||||
for attr in item_data_attrs:
|
||||
item_data[attr] = 0
|
||||
|
||||
for account, tax_detail in hsn_wise_charges.get(hsn_code, {}).items():
|
||||
for account, tax_detail in hsn_wise_charges.get(item_or_hsn, {}).items():
|
||||
account_type = gst_accounts.get(account, '')
|
||||
for tax_acc, attrs in tax_map.items():
|
||||
if account_type == tax_acc:
|
||||
|
File diff suppressed because one or more lines are too long
@ -106,14 +106,14 @@ def set_address_details(row, special_characters):
|
||||
row.update({'ship_to_state': row.to_state})
|
||||
|
||||
def set_taxes(row, filters):
|
||||
taxes = frappe.get_list("Sales Taxes and Charges",
|
||||
taxes = frappe.get_all("Sales Taxes and Charges",
|
||||
filters={
|
||||
'parent': row.dn_id
|
||||
},
|
||||
fields=('item_wise_tax_detail', 'account_head'))
|
||||
|
||||
account_list = ["cgst_account", "sgst_account", "igst_account", "cess_account"]
|
||||
taxes_list = frappe.get_list("GST Account",
|
||||
taxes_list = frappe.get_all("GST Account",
|
||||
filters={
|
||||
"parent": "GST Settings",
|
||||
"company": filters.company
|
||||
|
@ -41,7 +41,7 @@ class VATAuditReport(object):
|
||||
return self.columns, self.data
|
||||
|
||||
def get_sa_vat_accounts(self):
|
||||
self.sa_vat_accounts = frappe.get_list("South Africa VAT Account",
|
||||
self.sa_vat_accounts = frappe.get_all("South Africa VAT Account",
|
||||
filters = {"parent": self.filters.company}, pluck="account")
|
||||
if not self.sa_vat_accounts and not frappe.flags.in_test and not frappe.flags.in_migrate:
|
||||
link_to_settings = get_link_to_form("South Africa VAT Settings", "", label="South Africa VAT Settings")
|
||||
|
@ -1,7 +1,10 @@
|
||||
import io
|
||||
import os
|
||||
from base64 import b64encode
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils.data import add_to_date, get_time, getdate
|
||||
from pyqrcode import create as qr_create
|
||||
|
||||
from erpnext import get_region
|
||||
@ -28,24 +31,74 @@ def create_qr_code(doc, method):
|
||||
|
||||
for field in meta.get_image_fields():
|
||||
if field.fieldname == 'qr_code':
|
||||
from urllib.parse import urlencode
|
||||
''' TLV conversion for
|
||||
1. Seller's Name
|
||||
2. VAT Number
|
||||
3. Time Stamp
|
||||
4. Invoice Amount
|
||||
5. VAT Amount
|
||||
'''
|
||||
tlv_array = []
|
||||
# Sellers Name
|
||||
|
||||
# Creating public url to print format
|
||||
default_print_format = frappe.db.get_value('Property Setter', dict(property='default_print_format', doc_type=doc.doctype), "value")
|
||||
seller_name = frappe.db.get_value(
|
||||
'Company',
|
||||
doc.company,
|
||||
'company_name_in_arabic')
|
||||
|
||||
# System Language
|
||||
language = frappe.get_system_settings('language')
|
||||
if not seller_name:
|
||||
frappe.throw(_('Arabic name missing for {} in the company document').format(doc.company))
|
||||
|
||||
params = urlencode({
|
||||
'format': default_print_format or 'Standard',
|
||||
'_lang': language,
|
||||
'key': doc.get_signature()
|
||||
})
|
||||
tag = bytes([1]).hex()
|
||||
length = bytes([len(seller_name.encode('utf-8'))]).hex()
|
||||
value = seller_name.encode('utf-8').hex()
|
||||
tlv_array.append(''.join([tag, length, value]))
|
||||
|
||||
# VAT Number
|
||||
tax_id = frappe.db.get_value('Company', doc.company, 'tax_id')
|
||||
if not tax_id:
|
||||
frappe.throw(_('Tax ID missing for {} in the company document').format(doc.company))
|
||||
|
||||
tag = bytes([2]).hex()
|
||||
length = bytes([len(tax_id)]).hex()
|
||||
value = tax_id.encode('utf-8').hex()
|
||||
tlv_array.append(''.join([tag, length, value]))
|
||||
|
||||
# Time Stamp
|
||||
posting_date = getdate(doc.posting_date)
|
||||
time = get_time(doc.posting_time)
|
||||
seconds = time.hour * 60 * 60 + time.minute * 60 + time.second
|
||||
time_stamp = add_to_date(posting_date, seconds=seconds)
|
||||
time_stamp = time_stamp.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
|
||||
tag = bytes([3]).hex()
|
||||
length = bytes([len(time_stamp)]).hex()
|
||||
value = time_stamp.encode('utf-8').hex()
|
||||
tlv_array.append(''.join([tag, length, value]))
|
||||
|
||||
# Invoice Amount
|
||||
invoice_amount = str(doc.total)
|
||||
tag = bytes([4]).hex()
|
||||
length = bytes([len(invoice_amount)]).hex()
|
||||
value = invoice_amount.encode('utf-8').hex()
|
||||
tlv_array.append(''.join([tag, length, value]))
|
||||
|
||||
# VAT Amount
|
||||
vat_amount = str(doc.total_taxes_and_charges)
|
||||
|
||||
tag = bytes([5]).hex()
|
||||
length = bytes([len(vat_amount)]).hex()
|
||||
value = vat_amount.encode('utf-8').hex()
|
||||
tlv_array.append(''.join([tag, length, value]))
|
||||
|
||||
# Joining bytes into one
|
||||
tlv_buff = ''.join(tlv_array)
|
||||
|
||||
# base64 conversion for QR Code
|
||||
base64_string = b64encode(bytes.fromhex(tlv_buff)).decode()
|
||||
|
||||
# creating qr code for the url
|
||||
url = f"{ frappe.utils.get_url() }/{ doc.doctype }/{ doc.name }?{ params }"
|
||||
qr_image = io.BytesIO()
|
||||
url = qr_create(url, error='L')
|
||||
url = qr_create(base64_string, error='L')
|
||||
url.png(qr_image, scale=2, quiet_zone=1)
|
||||
|
||||
# making file
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe.query_builder import Case
|
||||
from frappe.query_builder.functions import Coalesce, Sum
|
||||
from frappe.utils import flt, nowdate
|
||||
|
||||
|
||||
@ -19,34 +21,42 @@ class Bin(Document):
|
||||
- flt(self.reserved_qty_for_production) - flt(self.reserved_qty_for_sub_contract))
|
||||
|
||||
def get_first_sle(self):
|
||||
sle = frappe.db.sql("""
|
||||
select * from `tabStock Ledger Entry`
|
||||
where item_code = %s
|
||||
and warehouse = %s
|
||||
order by timestamp(posting_date, posting_time) asc, creation asc
|
||||
limit 1
|
||||
""", (self.item_code, self.warehouse), as_dict=1)
|
||||
return sle and sle[0] or None
|
||||
sle = frappe.qb.DocType("Stock Ledger Entry")
|
||||
first_sle = (
|
||||
frappe.qb.from_(sle)
|
||||
.select("*")
|
||||
.where((sle.item_code == self.item_code) & (sle.warehouse == self.warehouse))
|
||||
.orderby(sle.posting_date, sle.posting_time, sle.creation)
|
||||
.limit(1)
|
||||
).run(as_dict=True)
|
||||
|
||||
return first_sle and first_sle[0] or None
|
||||
|
||||
def update_reserved_qty_for_production(self):
|
||||
'''Update qty reserved for production from Production Item tables
|
||||
in open work orders'''
|
||||
self.reserved_qty_for_production = frappe.db.sql('''
|
||||
SELECT
|
||||
CASE WHEN ifnull(skip_transfer, 0) = 0 THEN
|
||||
SUM(item.required_qty - item.transferred_qty)
|
||||
ELSE
|
||||
SUM(item.required_qty - item.consumed_qty)
|
||||
END
|
||||
FROM `tabWork Order` pro, `tabWork Order Item` item
|
||||
WHERE
|
||||
item.item_code = %s
|
||||
and item.parent = pro.name
|
||||
and pro.docstatus = 1
|
||||
and item.source_warehouse = %s
|
||||
and pro.status not in ("Stopped", "Completed")
|
||||
and (item.required_qty > item.transferred_qty or item.required_qty > item.consumed_qty)
|
||||
''', (self.item_code, self.warehouse))[0][0]
|
||||
|
||||
wo = frappe.qb.DocType("Work Order")
|
||||
wo_item = frappe.qb.DocType("Work Order Item")
|
||||
|
||||
self.reserved_qty_for_production = (
|
||||
frappe.qb
|
||||
.from_(wo)
|
||||
.from_(wo_item)
|
||||
.select(Case()
|
||||
.when(wo.skip_transfer == 0, Sum(wo_item.required_qty - wo_item.transferred_qty))
|
||||
.else_(Sum(wo_item.required_qty - wo_item.consumed_qty))
|
||||
)
|
||||
.where(
|
||||
(wo_item.item_code == self.item_code)
|
||||
& (wo_item.parent == wo.name)
|
||||
& (wo.docstatus == 1)
|
||||
& (wo_item.source_warehouse == self.warehouse)
|
||||
& (wo.status.notin(["Stopped", "Completed"]))
|
||||
& ((wo_item.required_qty > wo_item.transferred_qty)
|
||||
| (wo_item.required_qty > wo_item.consumed_qty))
|
||||
)
|
||||
).run()[0][0] or 0.0
|
||||
|
||||
self.set_projected_qty()
|
||||
|
||||
@ -55,36 +65,53 @@ class Bin(Document):
|
||||
|
||||
def update_reserved_qty_for_sub_contracting(self):
|
||||
#reserved qty
|
||||
reserved_qty_for_sub_contract = frappe.db.sql('''
|
||||
select ifnull(sum(itemsup.required_qty),0)
|
||||
from `tabPurchase Order` po, `tabPurchase Order Item Supplied` itemsup
|
||||
where
|
||||
itemsup.rm_item_code = %s
|
||||
and itemsup.parent = po.name
|
||||
and po.docstatus = 1
|
||||
and po.is_subcontracted = 'Yes'
|
||||
and po.status != 'Closed'
|
||||
and po.per_received < 100
|
||||
and itemsup.reserve_warehouse = %s''', (self.item_code, self.warehouse))[0][0]
|
||||
|
||||
#Get Transferred Entries
|
||||
materials_transferred = frappe.db.sql("""
|
||||
select
|
||||
ifnull(sum(CASE WHEN se.is_return = 1 THEN (transfer_qty * -1) ELSE transfer_qty END),0)
|
||||
from
|
||||
`tabStock Entry` se, `tabStock Entry Detail` sed, `tabPurchase Order` po
|
||||
where
|
||||
se.docstatus=1
|
||||
and se.purpose='Send to Subcontractor'
|
||||
and ifnull(se.purchase_order, '') !=''
|
||||
and (sed.item_code = %(item)s or sed.original_item = %(item)s)
|
||||
and se.name = sed.parent
|
||||
and se.purchase_order = po.name
|
||||
and po.docstatus = 1
|
||||
and po.is_subcontracted = 'Yes'
|
||||
and po.status != 'Closed'
|
||||
and po.per_received < 100
|
||||
""", {'item': self.item_code})[0][0]
|
||||
po = frappe.qb.DocType("Purchase Order")
|
||||
supplied_item = frappe.qb.DocType("Purchase Order Item Supplied")
|
||||
|
||||
reserved_qty_for_sub_contract = (
|
||||
frappe.qb
|
||||
.from_(po)
|
||||
.from_(supplied_item)
|
||||
.select(Sum(Coalesce(supplied_item.required_qty, 0)))
|
||||
.where(
|
||||
(supplied_item.rm_item_code == self.item_code)
|
||||
& (po.name == supplied_item.parent)
|
||||
& (po.docstatus == 1)
|
||||
& (po.is_subcontracted == "Yes")
|
||||
& (po.status != "Closed")
|
||||
& (po.per_received < 100)
|
||||
& (supplied_item.reserve_warehouse == self.warehouse)
|
||||
)
|
||||
).run()[0][0] or 0.0
|
||||
|
||||
se = frappe.qb.DocType("Stock Entry")
|
||||
se_item = frappe.qb.DocType("Stock Entry Detail")
|
||||
|
||||
materials_transferred = (
|
||||
frappe.qb
|
||||
.from_(se)
|
||||
.from_(se_item)
|
||||
.from_(po)
|
||||
.select(Sum(
|
||||
Case()
|
||||
.when(se.is_return == 1, se_item.transfer_qty * -1)
|
||||
.else_(se_item.transfer_qty)
|
||||
))
|
||||
.where(
|
||||
(se.docstatus == 1)
|
||||
& (se.purpose == "Send to Subcontractor")
|
||||
& (Coalesce(se.purchase_order, "") != "")
|
||||
& ((se_item.item_code == self.item_code)
|
||||
| (se_item.original_item == self.item_code))
|
||||
& (se.name == se_item.parent)
|
||||
& (po.name == se.purchase_order)
|
||||
& (po.docstatus == 1)
|
||||
& (po.is_subcontracted == "Yes")
|
||||
& (po.status != "Closed")
|
||||
& (po.per_received < 100)
|
||||
)
|
||||
).run()[0][0] or 0.0
|
||||
|
||||
if reserved_qty_for_sub_contract > materials_transferred:
|
||||
reserved_qty_for_sub_contract = reserved_qty_for_sub_contract - materials_transferred
|
||||
@ -160,4 +187,4 @@ def update_qty(bin_name, args):
|
||||
'indented_qty': indented_qty,
|
||||
'planned_qty': planned_qty,
|
||||
'projected_qty': projected_qty
|
||||
})
|
||||
})
|
||||
|
@ -222,10 +222,11 @@ class Item(WebsiteGenerator):
|
||||
'route')) + '/' + self.scrub((self.item_name or self.item_code) + '-' + random_string(5))
|
||||
|
||||
def validate_website_image(self):
|
||||
"""Validate if the website image is a public file"""
|
||||
|
||||
if frappe.flags.in_import:
|
||||
return
|
||||
|
||||
"""Validate if the website image is a public file"""
|
||||
auto_set_website_image = False
|
||||
if not self.website_image and self.image:
|
||||
auto_set_website_image = True
|
||||
@ -255,10 +256,11 @@ class Item(WebsiteGenerator):
|
||||
self.website_image = None
|
||||
|
||||
def make_thumbnail(self):
|
||||
"""Make a thumbnail of `website_image`"""
|
||||
|
||||
if frappe.flags.in_import:
|
||||
return
|
||||
|
||||
"""Make a thumbnail of `website_image`"""
|
||||
import requests.exceptions
|
||||
|
||||
if not self.is_new() and self.website_image != frappe.db.get_value(self.doctype, self.name, "website_image"):
|
||||
|
@ -488,7 +488,7 @@ class TestItem(ERPNextTestCase):
|
||||
item_doc.save()
|
||||
|
||||
# Check values saved correctly
|
||||
barcodes = frappe.get_list(
|
||||
barcodes = frappe.get_all(
|
||||
'Item Barcode',
|
||||
fields=['barcode', 'barcode_type'],
|
||||
filters={'parent': item_code})
|
||||
|
@ -299,7 +299,7 @@ def get_basic_details(args, item, overwrite_warehouse=True):
|
||||
"warehouse": warehouse,
|
||||
"income_account": get_default_income_account(args, item_defaults, item_group_defaults, brand_defaults),
|
||||
"expense_account": expense_account or get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults) ,
|
||||
"discount_account": None or get_default_discount_account(args, item_defaults),
|
||||
"discount_account": get_default_discount_account(args, item_defaults),
|
||||
"cost_center": get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults),
|
||||
'has_serial_no': item.has_serial_no,
|
||||
'has_batch_no': item.has_batch_no,
|
||||
@ -317,6 +317,7 @@ def get_basic_details(args, item, overwrite_warehouse=True):
|
||||
"net_rate": 0.0,
|
||||
"net_amount": 0.0,
|
||||
"discount_percentage": 0.0,
|
||||
"discount_amount": 0.0,
|
||||
"supplier": get_default_supplier(args, item_defaults, item_group_defaults, brand_defaults),
|
||||
"update_stock": args.get("update_stock") if args.get('doctype') in ['Sales Invoice', 'Purchase Invoice'] else 0,
|
||||
"delivered_by_supplier": item.delivered_by_supplier if args.get("doctype") in ["Sales Order", "Sales Invoice"] else 0,
|
||||
|
Loading…
x
Reference in New Issue
Block a user