Merge branch 'develop' into crm-carry-forward-communication-comments
This commit is contained in:
commit
83e3e58fe9
@ -434,7 +434,7 @@ def get_pi_matching_query(amount_condition):
|
|||||||
|
|
||||||
def get_ec_matching_query(bank_account, company, amount_condition):
|
def get_ec_matching_query(bank_account, company, amount_condition):
|
||||||
# get matching Expense Claim query
|
# 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"])]
|
filters={"default_account": bank_account}, fields=["parent"])]
|
||||||
mode_of_payments = '(\'' + '\', \''.join(mode_of_payments) + '\' )'
|
mode_of_payments = '(\'' + '\', \''.join(mode_of_payments) + '\' )'
|
||||||
company_currency = get_company_currency(company)
|
company_currency = get_company_currency(company)
|
||||||
|
@ -60,6 +60,10 @@ frappe.ui.form.on('Asset Repair', {
|
|||||||
if (frm.doc.repair_status == "Completed") {
|
if (frm.doc.repair_status == "Completed") {
|
||||||
frm.set_value('completion_date', frappe.datetime.now_datetime());
|
frm.set_value('completion_date', frappe.datetime.now_datetime());
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
stock_items_on_form_rendered() {
|
||||||
|
erpnext.setup_serial_or_batch_no();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -118,9 +118,10 @@ class AssetRepair(AccountsController):
|
|||||||
for stock_item in self.get('stock_items'):
|
for stock_item in self.get('stock_items'):
|
||||||
stock_entry.append('items', {
|
stock_entry.append('items', {
|
||||||
"s_warehouse": self.warehouse,
|
"s_warehouse": self.warehouse,
|
||||||
"item_code": stock_item.item,
|
"item_code": stock_item.item_code,
|
||||||
"qty": stock_item.consumed_quantity,
|
"qty": stock_item.consumed_quantity,
|
||||||
"basic_rate": stock_item.valuation_rate
|
"basic_rate": stock_item.valuation_rate,
|
||||||
|
"serial_no": stock_item.serial_no
|
||||||
})
|
})
|
||||||
|
|
||||||
stock_entry.insert()
|
stock_entry.insert()
|
||||||
|
@ -11,12 +11,15 @@ from erpnext.assets.doctype.asset.test_asset import (
|
|||||||
create_asset_data,
|
create_asset_data,
|
||||||
set_depreciation_settings_in_company,
|
set_depreciation_settings_in_company,
|
||||||
)
|
)
|
||||||
|
from erpnext.stock.doctype.item.test_item import create_item
|
||||||
|
|
||||||
|
|
||||||
class TestAssetRepair(unittest.TestCase):
|
class TestAssetRepair(unittest.TestCase):
|
||||||
def setUp(self):
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
set_depreciation_settings_in_company()
|
set_depreciation_settings_in_company()
|
||||||
create_asset_data()
|
create_asset_data()
|
||||||
|
create_item("_Test Stock Item")
|
||||||
frappe.db.sql("delete from `tabTax Rule`")
|
frappe.db.sql("delete from `tabTax Rule`")
|
||||||
|
|
||||||
def test_update_status(self):
|
def test_update_status(self):
|
||||||
@ -70,9 +73,28 @@ class TestAssetRepair(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(stock_entry.stock_entry_type, "Material Issue")
|
self.assertEqual(stock_entry.stock_entry_type, "Material Issue")
|
||||||
self.assertEqual(stock_entry.items[0].s_warehouse, asset_repair.warehouse)
|
self.assertEqual(stock_entry.items[0].s_warehouse, asset_repair.warehouse)
|
||||||
self.assertEqual(stock_entry.items[0].item_code, asset_repair.stock_items[0].item)
|
self.assertEqual(stock_entry.items[0].item_code, asset_repair.stock_items[0].item_code)
|
||||||
self.assertEqual(stock_entry.items[0].qty, asset_repair.stock_items[0].consumed_quantity)
|
self.assertEqual(stock_entry.items[0].qty, asset_repair.stock_items[0].consumed_quantity)
|
||||||
|
|
||||||
|
def test_serialized_item_consumption(self):
|
||||||
|
from erpnext.stock.doctype.serial_no.serial_no import SerialNoRequiredError
|
||||||
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
||||||
|
|
||||||
|
stock_entry = make_serialized_item()
|
||||||
|
serial_nos = stock_entry.get("items")[0].serial_no
|
||||||
|
serial_no = serial_nos.split("\n")[0]
|
||||||
|
|
||||||
|
# should not raise any error
|
||||||
|
create_asset_repair(stock_consumption = 1, item_code = stock_entry.get("items")[0].item_code,
|
||||||
|
warehouse = "_Test Warehouse - _TC", serial_no = serial_no, submit = 1)
|
||||||
|
|
||||||
|
# should raise error
|
||||||
|
asset_repair = create_asset_repair(stock_consumption = 1, warehouse = "_Test Warehouse - _TC",
|
||||||
|
item_code = stock_entry.get("items")[0].item_code)
|
||||||
|
|
||||||
|
asset_repair.repair_status = "Completed"
|
||||||
|
self.assertRaises(SerialNoRequiredError, asset_repair.submit)
|
||||||
|
|
||||||
def test_increase_in_asset_value_due_to_stock_consumption(self):
|
def test_increase_in_asset_value_due_to_stock_consumption(self):
|
||||||
asset = create_asset(calculate_depreciation = 1, submit=1)
|
asset = create_asset(calculate_depreciation = 1, submit=1)
|
||||||
initial_asset_value = get_asset_value(asset)
|
initial_asset_value = get_asset_value(asset)
|
||||||
@ -137,11 +159,12 @@ def create_asset_repair(**args):
|
|||||||
|
|
||||||
if args.stock_consumption:
|
if args.stock_consumption:
|
||||||
asset_repair.stock_consumption = 1
|
asset_repair.stock_consumption = 1
|
||||||
asset_repair.warehouse = create_warehouse("Test Warehouse", company = asset.company)
|
asset_repair.warehouse = args.warehouse or create_warehouse("Test Warehouse", company = asset.company)
|
||||||
asset_repair.append("stock_items", {
|
asset_repair.append("stock_items", {
|
||||||
"item": args.item or args.item_code or "_Test Item",
|
"item_code": args.item_code or "_Test Stock Item",
|
||||||
"valuation_rate": args.rate if args.get("rate") is not None else 100,
|
"valuation_rate": args.rate if args.get("rate") is not None else 100,
|
||||||
"consumed_quantity": args.qty or 1
|
"consumed_quantity": args.qty or 1,
|
||||||
|
"serial_no": args.serial_no
|
||||||
})
|
})
|
||||||
|
|
||||||
asset_repair.insert(ignore_if_duplicate=True)
|
asset_repair.insert(ignore_if_duplicate=True)
|
||||||
@ -158,7 +181,7 @@ def create_asset_repair(**args):
|
|||||||
})
|
})
|
||||||
stock_entry.append('items', {
|
stock_entry.append('items', {
|
||||||
"t_warehouse": asset_repair.warehouse,
|
"t_warehouse": asset_repair.warehouse,
|
||||||
"item_code": asset_repair.stock_items[0].item,
|
"item_code": asset_repair.stock_items[0].item_code,
|
||||||
"qty": asset_repair.stock_items[0].consumed_quantity
|
"qty": asset_repair.stock_items[0].consumed_quantity
|
||||||
})
|
})
|
||||||
stock_entry.submit()
|
stock_entry.submit()
|
||||||
|
@ -5,19 +5,13 @@
|
|||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"item",
|
"item_code",
|
||||||
"valuation_rate",
|
"valuation_rate",
|
||||||
"consumed_quantity",
|
"consumed_quantity",
|
||||||
"total_value"
|
"total_value",
|
||||||
|
"serial_no"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
|
||||||
"fieldname": "item",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Item",
|
|
||||||
"options": "Item"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fetch_from": "item.valuation_rate",
|
"fetch_from": "item.valuation_rate",
|
||||||
"fieldname": "valuation_rate",
|
"fieldname": "valuation_rate",
|
||||||
@ -38,12 +32,24 @@
|
|||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Total Value",
|
"label": "Total Value",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "serial_no",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Serial No"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "item_code",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Item",
|
||||||
|
"options": "Item"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-05-12 03:19:55.006300",
|
"modified": "2021-11-11 18:23:00.492483",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Assets",
|
"module": "Assets",
|
||||||
"name": "Asset Repair Consumed Item",
|
"name": "Asset Repair Consumed Item",
|
||||||
|
@ -248,20 +248,18 @@ doc_events = {
|
|||||||
"validate": "erpnext.regional.india.utils.validate_tax_category"
|
"validate": "erpnext.regional.india.utils.validate_tax_category"
|
||||||
},
|
},
|
||||||
"Sales Invoice": {
|
"Sales Invoice": {
|
||||||
"after_insert": "erpnext.regional.saudi_arabia.utils.create_qr_code",
|
|
||||||
"on_submit": [
|
"on_submit": [
|
||||||
"erpnext.regional.create_transaction_log",
|
"erpnext.regional.create_transaction_log",
|
||||||
"erpnext.regional.italy.utils.sales_invoice_on_submit",
|
"erpnext.regional.italy.utils.sales_invoice_on_submit",
|
||||||
|
"erpnext.regional.saudi_arabia.utils.create_qr_code",
|
||||||
"erpnext.erpnext_integrations.taxjar_integration.create_transaction"
|
"erpnext.erpnext_integrations.taxjar_integration.create_transaction"
|
||||||
],
|
],
|
||||||
"on_cancel": [
|
"on_cancel": [
|
||||||
"erpnext.regional.italy.utils.sales_invoice_on_cancel",
|
"erpnext.regional.italy.utils.sales_invoice_on_cancel",
|
||||||
"erpnext.erpnext_integrations.taxjar_integration.delete_transaction"
|
"erpnext.erpnext_integrations.taxjar_integration.delete_transaction",
|
||||||
],
|
|
||||||
"on_trash": [
|
|
||||||
"erpnext.regional.check_deletion_permission",
|
|
||||||
"erpnext.regional.saudi_arabia.utils.delete_qr_code_file"
|
"erpnext.regional.saudi_arabia.utils.delete_qr_code_file"
|
||||||
],
|
],
|
||||||
|
"on_trash": "erpnext.regional.check_deletion_permission",
|
||||||
"validate": [
|
"validate": [
|
||||||
"erpnext.regional.india.utils.validate_document_name",
|
"erpnext.regional.india.utils.validate_document_name",
|
||||||
"erpnext.regional.india.utils.update_taxable_values"
|
"erpnext.regional.india.utils.update_taxable_values"
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
from frappe.query_builder.functions import Sum
|
||||||
from frappe.utils import flt, nowdate
|
from frappe.utils import flt, nowdate
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
@ -41,24 +42,34 @@ class EmployeeAdvance(Document):
|
|||||||
self.status = "Cancelled"
|
self.status = "Cancelled"
|
||||||
|
|
||||||
def set_total_advance_paid(self):
|
def set_total_advance_paid(self):
|
||||||
paid_amount = frappe.db.sql("""
|
gle = frappe.qb.DocType("GL Entry")
|
||||||
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
|
|
||||||
|
|
||||||
return_amount = frappe.db.sql("""
|
paid_amount = (
|
||||||
select ifnull(sum(credit), 0) as return_amount
|
frappe.qb.from_(gle)
|
||||||
from `tabGL Entry`
|
.select(Sum(gle.debit).as_("paid_amount"))
|
||||||
where against_voucher_type = 'Employee Advance'
|
.where(
|
||||||
and voucher_type != 'Expense Claim'
|
(gle.against_voucher_type == 'Employee Advance')
|
||||||
and against_voucher = %s
|
& (gle.against_voucher == self.name)
|
||||||
and party_type = 'Employee'
|
& (gle.party_type == 'Employee')
|
||||||
and party = %s
|
& (gle.party == self.employee)
|
||||||
""", (self.name, self.employee), as_dict=1)[0].return_amount
|
& (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:
|
if paid_amount != 0:
|
||||||
paid_amount = flt(paid_amount) / flt(self.exchange_rate)
|
paid_amount = flt(paid_amount) / flt(self.exchange_rate)
|
||||||
|
@ -34,6 +34,24 @@ class TestEmployeeAdvance(unittest.TestCase):
|
|||||||
journal_entry1 = make_payment_entry(advance)
|
journal_entry1 = make_payment_entry(advance)
|
||||||
self.assertRaises(EmployeeAdvanceOverPayment, journal_entry1.submit)
|
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):
|
def test_repay_unclaimed_amount_from_salary(self):
|
||||||
employee_name = make_employee("_T@employe.advance")
|
employee_name = make_employee("_T@employe.advance")
|
||||||
advance = make_employee_advance(employee_name, {"repay_unclaimed_amount_from_salary": 1})
|
advance = make_employee_advance(employee_name, {"repay_unclaimed_amount_from_salary": 1})
|
||||||
|
@ -94,7 +94,6 @@
|
|||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Sanctioned Amount",
|
"label": "Sanctioned Amount",
|
||||||
"no_copy": 1,
|
|
||||||
"oldfieldname": "sanctioned_amount",
|
"oldfieldname": "sanctioned_amount",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
@ -120,7 +119,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-09-18 17:26:09.703215",
|
"modified": "2021-11-26 14:23:45.539922",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Expense Claim Detail",
|
"name": "Expense Claim Detail",
|
||||||
|
@ -178,8 +178,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "batch_size",
|
"fieldname": "batch_size",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Float",
|
||||||
"label": "Batch Size"
|
"label": "Batch Size",
|
||||||
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "sequence_id",
|
"fieldname": "sequence_id",
|
||||||
@ -200,7 +201,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-11-24 04:52:54.295168",
|
"modified": "2021-11-29 16:37:18.824489",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Work Order Operation",
|
"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)
|
GROUP BY bom_item.item_code""".format(qty_field=qty_field, table=table, conditions=conditions, bom=bom), as_dict=1)
|
||||||
|
|
||||||
def get_manufacturer_records():
|
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()
|
manufacture_details = frappe._dict()
|
||||||
for detail in details:
|
for detail in details:
|
||||||
dic = manufacture_details.setdefault(detail.get('parent'), {})
|
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": [
|
"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}}]",
|
||||||
"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}}]",
|
|
||||||
"creation": "2020-03-02 17:11:37.032604",
|
"creation": "2020-03-02 17:11:37.032604",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Workspace",
|
"doctype": "Workspace",
|
||||||
@ -140,14 +136,6 @@
|
|||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Link"
|
"type": "Link"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Reports",
|
|
||||||
"link_count": 0,
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Card Break"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"dependencies": "Work Order",
|
"dependencies": "Work Order",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -295,9 +283,126 @@
|
|||||||
"link_type": "DocType",
|
"link_type": "DocType",
|
||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Link"
|
"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",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Manufacturing",
|
"name": "Manufacturing",
|
||||||
|
@ -495,6 +495,11 @@
|
|||||||
font-size: var(--text-md);
|
font-size: var(--text-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> .item-qty-total-container {
|
||||||
|
@extend .net-total-container;
|
||||||
|
padding: 5px 0px 0px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
> .taxes-container {
|
> .taxes-container {
|
||||||
display: none;
|
display: none;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -569,17 +569,17 @@ def get_item_list(data, doc, hsn_wise=False):
|
|||||||
}
|
}
|
||||||
item_data_attrs = ['sgstRate', 'cgstRate', 'igstRate', 'cessRate', 'cessNonAdvol']
|
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)
|
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()
|
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'))
|
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.taxableAmount = taxable_amount
|
||||||
item_data.qtyUnit = ""
|
item_data.qtyUnit = ""
|
||||||
for attr in item_data_attrs:
|
for attr in item_data_attrs:
|
||||||
item_data[attr] = 0
|
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, '')
|
account_type = gst_accounts.get(account, '')
|
||||||
for tax_acc, attrs in tax_map.items():
|
for tax_acc, attrs in tax_map.items():
|
||||||
if account_type == tax_acc:
|
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})
|
row.update({'ship_to_state': row.to_state})
|
||||||
|
|
||||||
def set_taxes(row, filters):
|
def set_taxes(row, filters):
|
||||||
taxes = frappe.get_list("Sales Taxes and Charges",
|
taxes = frappe.get_all("Sales Taxes and Charges",
|
||||||
filters={
|
filters={
|
||||||
'parent': row.dn_id
|
'parent': row.dn_id
|
||||||
},
|
},
|
||||||
fields=('item_wise_tax_detail', 'account_head'))
|
fields=('item_wise_tax_detail', 'account_head'))
|
||||||
|
|
||||||
account_list = ["cgst_account", "sgst_account", "igst_account", "cess_account"]
|
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={
|
filters={
|
||||||
"parent": "GST Settings",
|
"parent": "GST Settings",
|
||||||
"company": filters.company
|
"company": filters.company
|
||||||
|
@ -41,7 +41,7 @@ class VATAuditReport(object):
|
|||||||
return self.columns, self.data
|
return self.columns, self.data
|
||||||
|
|
||||||
def get_sa_vat_accounts(self):
|
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")
|
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:
|
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")
|
link_to_settings = get_link_to_form("South Africa VAT Settings", "", label="South Africa VAT Settings")
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
|
from base64 import b64encode
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.utils.data import add_to_date, get_time, getdate
|
||||||
from pyqrcode import create as qr_create
|
from pyqrcode import create as qr_create
|
||||||
|
|
||||||
from erpnext import get_region
|
from erpnext import get_region
|
||||||
@ -28,24 +31,74 @@ def create_qr_code(doc, method):
|
|||||||
|
|
||||||
for field in meta.get_image_fields():
|
for field in meta.get_image_fields():
|
||||||
if field.fieldname == 'qr_code':
|
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
|
seller_name = frappe.db.get_value(
|
||||||
default_print_format = frappe.db.get_value('Property Setter', dict(property='default_print_format', doc_type=doc.doctype), "value")
|
'Company',
|
||||||
|
doc.company,
|
||||||
|
'company_name_in_arabic')
|
||||||
|
|
||||||
# System Language
|
if not seller_name:
|
||||||
language = frappe.get_system_settings('language')
|
frappe.throw(_('Arabic name missing for {} in the company document').format(doc.company))
|
||||||
|
|
||||||
params = urlencode({
|
tag = bytes([1]).hex()
|
||||||
'format': default_print_format or 'Standard',
|
length = bytes([len(seller_name.encode('utf-8'))]).hex()
|
||||||
'_lang': language,
|
value = seller_name.encode('utf-8').hex()
|
||||||
'key': doc.get_signature()
|
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()
|
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)
|
url.png(qr_image, scale=2, quiet_zone=1)
|
||||||
|
|
||||||
# making file
|
# making file
|
||||||
|
@ -100,6 +100,10 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
`<div class="add-discount-wrapper">
|
`<div class="add-discount-wrapper">
|
||||||
${this.get_discount_icon()} ${__('Add Discount')}
|
${this.get_discount_icon()} ${__('Add Discount')}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="item-qty-total-container">
|
||||||
|
<div class="item-qty-total-label">${__('Total Items')}</div>
|
||||||
|
<div class="item-qty-total-value">0.00</div>
|
||||||
|
</div>
|
||||||
<div class="net-total-container">
|
<div class="net-total-container">
|
||||||
<div class="net-total-label">${__("Net Total")}</div>
|
<div class="net-total-label">${__("Net Total")}</div>
|
||||||
<div class="net-total-value">0.00</div>
|
<div class="net-total-value">0.00</div>
|
||||||
@ -142,6 +146,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
|
|
||||||
this.$numpad_section.prepend(
|
this.$numpad_section.prepend(
|
||||||
`<div class="numpad-totals">
|
`<div class="numpad-totals">
|
||||||
|
<span class="numpad-item-qty-total"></span>
|
||||||
<span class="numpad-net-total"></span>
|
<span class="numpad-net-total"></span>
|
||||||
<span class="numpad-grand-total"></span>
|
<span class="numpad-grand-total"></span>
|
||||||
</div>`
|
</div>`
|
||||||
@ -470,6 +475,7 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
if (!frm) frm = this.events.get_frm();
|
if (!frm) frm = this.events.get_frm();
|
||||||
|
|
||||||
this.render_net_total(frm.doc.net_total);
|
this.render_net_total(frm.doc.net_total);
|
||||||
|
this.render_total_item_qty(frm.doc.items);
|
||||||
const grand_total = cint(frappe.sys_defaults.disable_rounded_total) ? frm.doc.grand_total : frm.doc.rounded_total;
|
const grand_total = cint(frappe.sys_defaults.disable_rounded_total) ? frm.doc.grand_total : frm.doc.rounded_total;
|
||||||
this.render_grand_total(grand_total);
|
this.render_grand_total(grand_total);
|
||||||
|
|
||||||
@ -487,6 +493,21 @@ erpnext.PointOfSale.ItemCart = class {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render_total_item_qty(items) {
|
||||||
|
var total_item_qty = 0;
|
||||||
|
items.map((item) => {
|
||||||
|
total_item_qty = total_item_qty + item.qty;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$totals_section.find('.item-qty-total-container').html(
|
||||||
|
`<div>${__('Total Quantity')}</div><div>${total_item_qty}</div>`
|
||||||
|
);
|
||||||
|
|
||||||
|
this.$numpad_section.find('.numpad-item-qty-total').html(
|
||||||
|
`<div>${__('Total Quantity')}: <span>${total_item_qty}</span></div>`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
render_grand_total(value) {
|
render_grand_total(value) {
|
||||||
const currency = this.events.get_frm().doc.currency;
|
const currency = this.events.get_frm().doc.currency;
|
||||||
this.$totals_section.find('.grand-total-container').html(
|
this.$totals_section.find('.grand-total-container').html(
|
||||||
|
@ -222,10 +222,11 @@ class Item(WebsiteGenerator):
|
|||||||
'route')) + '/' + self.scrub((self.item_name or self.item_code) + '-' + random_string(5))
|
'route')) + '/' + self.scrub((self.item_name or self.item_code) + '-' + random_string(5))
|
||||||
|
|
||||||
def validate_website_image(self):
|
def validate_website_image(self):
|
||||||
|
"""Validate if the website image is a public file"""
|
||||||
|
|
||||||
if frappe.flags.in_import:
|
if frappe.flags.in_import:
|
||||||
return
|
return
|
||||||
|
|
||||||
"""Validate if the website image is a public file"""
|
|
||||||
auto_set_website_image = False
|
auto_set_website_image = False
|
||||||
if not self.website_image and self.image:
|
if not self.website_image and self.image:
|
||||||
auto_set_website_image = True
|
auto_set_website_image = True
|
||||||
@ -255,10 +256,11 @@ class Item(WebsiteGenerator):
|
|||||||
self.website_image = None
|
self.website_image = None
|
||||||
|
|
||||||
def make_thumbnail(self):
|
def make_thumbnail(self):
|
||||||
|
"""Make a thumbnail of `website_image`"""
|
||||||
|
|
||||||
if frappe.flags.in_import:
|
if frappe.flags.in_import:
|
||||||
return
|
return
|
||||||
|
|
||||||
"""Make a thumbnail of `website_image`"""
|
|
||||||
import requests.exceptions
|
import requests.exceptions
|
||||||
|
|
||||||
if not self.is_new() and self.website_image != frappe.db.get_value(self.doctype, self.name, "website_image"):
|
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()
|
item_doc.save()
|
||||||
|
|
||||||
# Check values saved correctly
|
# Check values saved correctly
|
||||||
barcodes = frappe.get_list(
|
barcodes = frappe.get_all(
|
||||||
'Item Barcode',
|
'Item Barcode',
|
||||||
fields=['barcode', 'barcode_type'],
|
fields=['barcode', 'barcode_type'],
|
||||||
filters={'parent': item_code})
|
filters={'parent': item_code})
|
||||||
|
@ -299,7 +299,7 @@ def get_basic_details(args, item, overwrite_warehouse=True):
|
|||||||
"warehouse": warehouse,
|
"warehouse": warehouse,
|
||||||
"income_account": get_default_income_account(args, item_defaults, item_group_defaults, brand_defaults),
|
"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) ,
|
"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),
|
"cost_center": get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults),
|
||||||
'has_serial_no': item.has_serial_no,
|
'has_serial_no': item.has_serial_no,
|
||||||
'has_batch_no': item.has_batch_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_rate": 0.0,
|
||||||
"net_amount": 0.0,
|
"net_amount": 0.0,
|
||||||
"discount_percentage": 0.0,
|
"discount_percentage": 0.0,
|
||||||
|
"discount_amount": 0.0,
|
||||||
"supplier": get_default_supplier(args, item_defaults, item_group_defaults, brand_defaults),
|
"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,
|
"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,
|
"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