Merge branch 'develop' into help-links-fix
This commit is contained in:
commit
3da2df55f4
@ -376,6 +376,12 @@ class POSInvoice(SalesInvoice):
|
|||||||
"campaign": profile.get("campaign"),
|
"campaign": profile.get("campaign"),
|
||||||
"allow_print_before_pay": profile.get("allow_print_before_pay")
|
"allow_print_before_pay": profile.get("allow_print_before_pay")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def reset_mode_of_payments(self):
|
||||||
|
if self.pos_profile:
|
||||||
|
pos_profile = frappe.get_cached_doc('POS Profile', self.pos_profile)
|
||||||
|
update_multi_mode_option(self, pos_profile)
|
||||||
|
self.paid_amount = 0
|
||||||
|
|
||||||
def set_account_for_mode_of_payment(self):
|
def set_account_for_mode_of_payment(self):
|
||||||
self.payments = [d for d in self.payments if d.amount or d.base_amount or d.default]
|
self.payments = [d for d in self.payments if d.amount or d.base_amount or d.default]
|
||||||
|
@ -51,7 +51,11 @@ def get_period_list(from_fiscal_year, to_fiscal_year, period_start_date, period_
|
|||||||
"from_date": start_date
|
"from_date": start_date
|
||||||
})
|
})
|
||||||
|
|
||||||
to_date = add_months(start_date, months_to_add)
|
if i==0 and filter_based_on == 'Date Range':
|
||||||
|
to_date = add_months(get_first_day(start_date), months_to_add)
|
||||||
|
else:
|
||||||
|
to_date = add_months(start_date, months_to_add)
|
||||||
|
|
||||||
start_date = to_date
|
start_date = to_date
|
||||||
|
|
||||||
# Subtract one day from to_date, as it may be first day in next fiscal year or month
|
# Subtract one day from to_date, as it may be first day in next fiscal year or month
|
||||||
|
@ -248,7 +248,6 @@ def make_quotation(source_name, target_doc=None):
|
|||||||
"doctype": "Quotation",
|
"doctype": "Quotation",
|
||||||
"field_map": {
|
"field_map": {
|
||||||
"opportunity_from": "quotation_to",
|
"opportunity_from": "quotation_to",
|
||||||
"opportunity_type": "order_type",
|
|
||||||
"name": "enq_no",
|
"name": "enq_no",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
"naming_series",
|
"naming_series",
|
||||||
"student",
|
"student",
|
||||||
"student_name",
|
"student_name",
|
||||||
|
"student_mobile_number",
|
||||||
"course_schedule",
|
"course_schedule",
|
||||||
"student_group",
|
"student_group",
|
||||||
"column_break_3",
|
"column_break_3",
|
||||||
@ -93,11 +94,19 @@
|
|||||||
"options": "Student Attendance",
|
"options": "Student Attendance",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "student.student_mobile_number",
|
||||||
|
"fieldname": "student_mobile_number",
|
||||||
|
"fieldtype": "Read Only",
|
||||||
|
"label": "Student Mobile Number",
|
||||||
|
"options": "Phone"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-07-08 13:55:42.580181",
|
"modified": "2021-03-24 00:02:11.005895",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Education",
|
"module": "Education",
|
||||||
"name": "Student Attendance",
|
"name": "Student Attendance",
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
"discharge_ordered_date",
|
"discharge_ordered_date",
|
||||||
"discharge_practitioner",
|
"discharge_practitioner",
|
||||||
"discharge_encounter",
|
"discharge_encounter",
|
||||||
"discharge_date",
|
"discharge_datetime",
|
||||||
"cb_discharge",
|
"cb_discharge",
|
||||||
"discharge_instructions",
|
"discharge_instructions",
|
||||||
"followup_date",
|
"followup_date",
|
||||||
@ -404,14 +404,15 @@
|
|||||||
"permlevel": 1
|
"permlevel": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "discharge_date",
|
"fieldname": "discharge_datetime",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Datetime",
|
||||||
"label": "Discharge Date",
|
"label": "Discharge Date",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-05-21 02:26:22.144575",
|
"modified": "2021-03-18 14:44:11.689956",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Healthcare",
|
"module": "Healthcare",
|
||||||
"name": "Inpatient Record",
|
"name": "Inpatient Record",
|
||||||
|
@ -151,7 +151,7 @@ def check_out_inpatient(inpatient_record):
|
|||||||
|
|
||||||
def discharge_patient(inpatient_record):
|
def discharge_patient(inpatient_record):
|
||||||
validate_inpatient_invoicing(inpatient_record)
|
validate_inpatient_invoicing(inpatient_record)
|
||||||
inpatient_record.discharge_date = today()
|
inpatient_record.discharge_datetime = now_datetime()
|
||||||
inpatient_record.status = "Discharged"
|
inpatient_record.status = "Discharged"
|
||||||
|
|
||||||
inpatient_record.save(ignore_permissions = True)
|
inpatient_record.save(ignore_permissions = True)
|
||||||
|
@ -324,6 +324,7 @@ scheduler_events = {
|
|||||||
"erpnext.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts",
|
"erpnext.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts",
|
||||||
"erpnext.support.doctype.issue.issue.set_service_level_agreement_variance",
|
"erpnext.support.doctype.issue.issue.set_service_level_agreement_variance",
|
||||||
"erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders",
|
"erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders",
|
||||||
|
"erpnext.stock.doctype.repost_item_valuation.repost_item_valuation.repost_entries"
|
||||||
],
|
],
|
||||||
"daily": [
|
"daily": [
|
||||||
"erpnext.stock.reorder_item.reorder_item",
|
"erpnext.stock.reorder_item.reorder_item",
|
||||||
|
@ -275,6 +275,11 @@ class TestLoan(unittest.TestCase):
|
|||||||
frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 250
|
frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 250
|
||||||
where loan_security='Test Security 2'""")
|
where loan_security='Test Security 2'""")
|
||||||
|
|
||||||
|
create_process_loan_security_shortfall()
|
||||||
|
loan_security_shortfall = frappe.get_doc("Loan Security Shortfall", {"loan": loan.name})
|
||||||
|
self.assertEquals(loan_security_shortfall.status, "Completed")
|
||||||
|
self.assertEquals(loan_security_shortfall.shortfall_amount, 0)
|
||||||
|
|
||||||
def test_loan_security_unpledge(self):
|
def test_loan_security_unpledge(self):
|
||||||
pledge = [{
|
pledge = [{
|
||||||
"loan_security": "Test Security 1",
|
"loan_security": "Test Security 1",
|
||||||
|
@ -55,6 +55,9 @@ def check_for_ltv_shortfall(process_loan_security_shortfall):
|
|||||||
'total_interest_payable', 'disbursed_amount', 'status'],
|
'total_interest_payable', 'disbursed_amount', 'status'],
|
||||||
filters={'status': ('in',['Disbursed','Partially Disbursed']), 'is_secured_loan': 1})
|
filters={'status': ('in',['Disbursed','Partially Disbursed']), 'is_secured_loan': 1})
|
||||||
|
|
||||||
|
loan_shortfall_map = frappe._dict(frappe.get_all("Loan Security Shortfall",
|
||||||
|
fields=["loan", "name"], filters={"status": "Pending"}, as_list=1))
|
||||||
|
|
||||||
loan_security_map = {}
|
loan_security_map = {}
|
||||||
|
|
||||||
for loan in loans:
|
for loan in loans:
|
||||||
@ -71,14 +74,19 @@ def check_for_ltv_shortfall(process_loan_security_shortfall):
|
|||||||
for security, qty in pledged_securities.items():
|
for security, qty in pledged_securities.items():
|
||||||
if not ltv_ratio:
|
if not ltv_ratio:
|
||||||
ltv_ratio = get_ltv_ratio(security)
|
ltv_ratio = get_ltv_ratio(security)
|
||||||
security_value += loan_security_price_map.get(security) * qty
|
security_value += flt(loan_security_price_map.get(security)) * flt(qty)
|
||||||
|
|
||||||
current_ratio = (outstanding_amount/security_value) * 100
|
current_ratio = (outstanding_amount/security_value) * 100 if security_value else 0
|
||||||
|
|
||||||
if current_ratio > ltv_ratio:
|
if current_ratio > ltv_ratio:
|
||||||
shortfall_amount = outstanding_amount - ((security_value * ltv_ratio) / 100)
|
shortfall_amount = outstanding_amount - ((security_value * ltv_ratio) / 100)
|
||||||
create_loan_security_shortfall(loan.name, outstanding_amount, security_value, shortfall_amount,
|
create_loan_security_shortfall(loan.name, outstanding_amount, security_value, shortfall_amount,
|
||||||
process_loan_security_shortfall)
|
process_loan_security_shortfall)
|
||||||
|
elif loan_shortfall_map.get(loan.name):
|
||||||
|
shortfall_amount = outstanding_amount - ((security_value * ltv_ratio) / 100)
|
||||||
|
if shortfall_amount <= 0:
|
||||||
|
shortfall = loan_shortfall_map.get(loan.name)
|
||||||
|
update_pending_shortfall(shortfall)
|
||||||
|
|
||||||
def create_loan_security_shortfall(loan, loan_amount, security_value, shortfall_amount, process_loan_security_shortfall):
|
def create_loan_security_shortfall(loan, loan_amount, security_value, shortfall_amount, process_loan_security_shortfall):
|
||||||
existing_shortfall = frappe.db.get_value("Loan Security Shortfall", {"loan": loan, "status": "Pending"}, "name")
|
existing_shortfall = frappe.db.get_value("Loan Security Shortfall", {"loan": loan, "status": "Pending"}, "name")
|
||||||
@ -101,3 +109,11 @@ def get_ltv_ratio(loan_security):
|
|||||||
ltv_ratio = frappe.db.get_value('Loan Security Type', loan_security_type, 'loan_to_value_ratio')
|
ltv_ratio = frappe.db.get_value('Loan Security Type', loan_security_type, 'loan_to_value_ratio')
|
||||||
return ltv_ratio
|
return ltv_ratio
|
||||||
|
|
||||||
|
def update_pending_shortfall(shortfall):
|
||||||
|
# Get all pending loan security shortfall
|
||||||
|
frappe.db.set_value("Loan Security Shortfall", shortfall,
|
||||||
|
{
|
||||||
|
"status": "Completed",
|
||||||
|
"shortfall_amount": 0
|
||||||
|
})
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ class TestWorkOrder(unittest.TestCase):
|
|||||||
wo_order.set_work_order_operations()
|
wo_order.set_work_order_operations()
|
||||||
self.assertEqual(wo_order.planned_operating_cost, cost*2)
|
self.assertEqual(wo_order.planned_operating_cost, cost*2)
|
||||||
|
|
||||||
def test_resered_qty_for_partial_completion(self):
|
def test_reserved_qty_for_partial_completion(self):
|
||||||
item = "_Test Item"
|
item = "_Test Item"
|
||||||
warehouse = create_warehouse("Test Warehouse for reserved_qty - _TC")
|
warehouse = create_warehouse("Test Warehouse for reserved_qty - _TC")
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ class TestWorkOrder(unittest.TestCase):
|
|||||||
s.submit()
|
s.submit()
|
||||||
|
|
||||||
bin1_at_completion = get_bin(item, warehouse)
|
bin1_at_completion = get_bin(item, warehouse)
|
||||||
|
|
||||||
self.assertEqual(cint(bin1_at_completion.reserved_qty_for_production),
|
self.assertEqual(cint(bin1_at_completion.reserved_qty_for_production),
|
||||||
reserved_qty_on_submission - 1)
|
reserved_qty_on_submission - 1)
|
||||||
|
|
||||||
@ -592,6 +592,55 @@ class TestWorkOrder(unittest.TestCase):
|
|||||||
|
|
||||||
frappe.db.set_value("Manufacturing Settings", None, "backflush_raw_materials_based_on", "BOM")
|
frappe.db.set_value("Manufacturing Settings", None, "backflush_raw_materials_based_on", "BOM")
|
||||||
|
|
||||||
|
def test_make_stock_entry_for_customer_provided_item(self):
|
||||||
|
finished_item = 'Test Item for Make Stock Entry 1'
|
||||||
|
make_item(finished_item, {
|
||||||
|
"include_item_in_manufacturing": 1,
|
||||||
|
"is_stock_item": 1
|
||||||
|
})
|
||||||
|
|
||||||
|
customer_provided_item = 'CUST-0987'
|
||||||
|
make_item(customer_provided_item, {
|
||||||
|
'is_purchase_item': 0,
|
||||||
|
'is_customer_provided_item': 1,
|
||||||
|
"is_stock_item": 1,
|
||||||
|
"include_item_in_manufacturing": 1,
|
||||||
|
'customer': '_Test Customer'
|
||||||
|
})
|
||||||
|
|
||||||
|
if not frappe.db.exists('BOM', {'item': finished_item}):
|
||||||
|
make_bom(item=finished_item, raw_materials=[customer_provided_item], rm_qty=1)
|
||||||
|
|
||||||
|
company = "_Test Company with perpetual inventory"
|
||||||
|
customer_warehouse = create_warehouse("Test Customer Provided Warehouse", company=company)
|
||||||
|
wo = make_wo_order_test_record(item=finished_item, qty=1, source_warehouse=customer_warehouse,
|
||||||
|
company=company)
|
||||||
|
|
||||||
|
ste = frappe.get_doc(make_stock_entry(wo.name, purpose='Material Transfer for Manufacture'))
|
||||||
|
ste.insert()
|
||||||
|
|
||||||
|
self.assertEqual(len(ste.items), 1)
|
||||||
|
for item in ste.items:
|
||||||
|
self.assertEqual(item.allow_zero_valuation_rate, 1)
|
||||||
|
self.assertEqual(item.valuation_rate, 0)
|
||||||
|
|
||||||
|
def test_valuation_rate_missing_on_make_stock_entry(self):
|
||||||
|
item_name = 'Test Valuation Rate Missing'
|
||||||
|
make_item(item_name, {
|
||||||
|
"is_stock_item": 1,
|
||||||
|
"include_item_in_manufacturing": 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
if not frappe.db.get_value('BOM', {'item': item_name}):
|
||||||
|
make_bom(item=item_name, raw_materials=[item_name], rm_qty=1)
|
||||||
|
|
||||||
|
company = "_Test Company with perpetual inventory"
|
||||||
|
source_warehouse = create_warehouse("Test Valuation Rate Missing Warehouse", company=company)
|
||||||
|
wo = make_wo_order_test_record(item=item_name, qty=1, source_warehouse=source_warehouse,
|
||||||
|
company=company)
|
||||||
|
|
||||||
|
self.assertRaises(frappe.ValidationError, make_stock_entry, wo.name, 'Material Transfer for Manufacture')
|
||||||
|
|
||||||
def get_scrap_item_details(bom_no):
|
def get_scrap_item_details(bom_no):
|
||||||
scrap_items = {}
|
scrap_items = {}
|
||||||
for item in frappe.db.sql("""select item_code, stock_qty from `tabBOM Scrap Item`
|
for item in frappe.db.sql("""select item_code, stock_qty from `tabBOM Scrap Item`
|
||||||
@ -609,6 +658,15 @@ def allow_overproduction(fieldname, percentage):
|
|||||||
|
|
||||||
def make_wo_order_test_record(**args):
|
def make_wo_order_test_record(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
if args.company and args.company != "_Test Company":
|
||||||
|
warehouse_map = {
|
||||||
|
"fg_warehouse": "_Test FG Warehouse",
|
||||||
|
"wip_warehouse": "_Test WIP Warehouse"
|
||||||
|
}
|
||||||
|
|
||||||
|
for attr, wh_name in warehouse_map.items():
|
||||||
|
if not args.get(attr):
|
||||||
|
args[attr] = create_warehouse(wh_name, company=args.company)
|
||||||
|
|
||||||
wo_order = frappe.new_doc("Work Order")
|
wo_order = frappe.new_doc("Work Order")
|
||||||
wo_order.production_item = args.production_item or args.item or args.item_code or "_Test FG Item"
|
wo_order.production_item = args.production_item or args.item or args.item_code or "_Test FG Item"
|
||||||
|
@ -61,7 +61,7 @@ class ForecastingReport(ExponentialSmoothingForecast):
|
|||||||
|
|
||||||
from_date = add_years(self.filters.from_date, cint(self.filters.no_of_years) * -1)
|
from_date = add_years(self.filters.from_date, cint(self.filters.no_of_years) * -1)
|
||||||
self.period_list = get_period_list(from_date, self.filters.to_date,
|
self.period_list = get_period_list(from_date, self.filters.to_date,
|
||||||
from_date, self.filters.to_date, None, self.filters.periodicity, ignore_fiscal_year=True)
|
from_date, self.filters.to_date, "Date Range", self.filters.periodicity, ignore_fiscal_year=True)
|
||||||
|
|
||||||
order_data = self.get_data_for_forecast() or []
|
order_data = self.get_data_for_forecast() or []
|
||||||
|
|
||||||
|
@ -759,4 +759,6 @@ erpnext.patches.v13_0.update_vehicle_no_reqd_condition
|
|||||||
erpnext.patches.v13_0.setup_fields_for_80g_certificate_and_donation
|
erpnext.patches.v13_0.setup_fields_for_80g_certificate_and_donation
|
||||||
erpnext.patches.v13_0.rename_membership_settings_to_non_profit_settings
|
erpnext.patches.v13_0.rename_membership_settings_to_non_profit_settings
|
||||||
erpnext.patches.v13_0.setup_gratuity_rule_for_india_and_uae
|
erpnext.patches.v13_0.setup_gratuity_rule_for_india_and_uae
|
||||||
|
erpnext.patches.v13_0.setup_uae_vat_fields
|
||||||
execute:frappe.db.set_value('System Settings', None, 'app_name', 'ERPNext')
|
execute:frappe.db.set_value('System Settings', None, 'app_name', 'ERPNext')
|
||||||
|
erpnext.patches.v13_0.rename_discharge_date_in_ip_record
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe.model.utils.rename_field import rename_field
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc("Healthcare", "doctype", "Inpatient Record")
|
||||||
|
if frappe.db.has_column("Inpatient Record", "discharge_date"):
|
||||||
|
rename_field("Inpatient Record", "discharge_date", "discharge_datetime")
|
12
erpnext/patches/v13_0/setup_uae_vat_fields.py
Normal file
12
erpnext/patches/v13_0/setup_uae_vat_fields.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Copyright (c) 2019, Frappe and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from erpnext.regional.united_arab_emirates.setup import setup
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
company = frappe.get_all('Company', filters = {'country': 'United Arab Emirates'})
|
||||||
|
if not company:
|
||||||
|
return
|
||||||
|
|
||||||
|
setup()
|
@ -74,43 +74,46 @@ frappe.ui.form.on("Salary Slip", {
|
|||||||
if (!frm.doc.letter_head && company.default_letter_head) {
|
if (!frm.doc.letter_head && company.default_letter_head) {
|
||||||
frm.set_value('letter_head', company.default_letter_head);
|
frm.set_value('letter_head', company.default_letter_head);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
currency: function(frm) {
|
||||||
frm.trigger("set_dynamic_labels");
|
frm.trigger("set_dynamic_labels");
|
||||||
},
|
},
|
||||||
|
|
||||||
set_dynamic_labels: function(frm) {
|
set_dynamic_labels: function(frm) {
|
||||||
var company_currency = frm.doc.company? erpnext.get_currency(frm.doc.company): frappe.defaults.get_default("currency");
|
var company_currency = frm.doc.company? erpnext.get_currency(frm.doc.company): frappe.defaults.get_default("currency");
|
||||||
frappe.run_serially([
|
if (frm.doc.employee && frm.doc.currency) {
|
||||||
() => frm.events.set_exchange_rate(frm, company_currency),
|
frappe.run_serially([
|
||||||
() => frm.events.change_form_labels(frm, company_currency),
|
() => frm.events.set_exchange_rate(frm, company_currency),
|
||||||
() => frm.events.change_grid_labels(frm),
|
() => frm.events.change_form_labels(frm, company_currency),
|
||||||
() => frm.refresh_fields()
|
() => frm.events.change_grid_labels(frm),
|
||||||
]);
|
() => frm.refresh_fields()
|
||||||
|
]);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
set_exchange_rate: function(frm, company_currency) {
|
set_exchange_rate: function(frm, company_currency) {
|
||||||
if (frm.doc.docstatus === 0) {
|
if (frm.doc.currency) {
|
||||||
if (frm.doc.currency) {
|
var from_currency = frm.doc.currency;
|
||||||
var from_currency = frm.doc.currency;
|
if (from_currency != company_currency) {
|
||||||
if (from_currency != company_currency) {
|
frm.events.hide_loan_section(frm);
|
||||||
frm.events.hide_loan_section(frm);
|
frappe.call({
|
||||||
frappe.call({
|
method: "erpnext.setup.utils.get_exchange_rate",
|
||||||
method: "erpnext.setup.utils.get_exchange_rate",
|
args: {
|
||||||
args: {
|
from_currency: from_currency,
|
||||||
from_currency: from_currency,
|
to_currency: company_currency,
|
||||||
to_currency: company_currency,
|
},
|
||||||
},
|
callback: function(r) {
|
||||||
callback: function(r) {
|
frm.set_value("exchange_rate", flt(r.message));
|
||||||
frm.set_value("exchange_rate", flt(r.message));
|
frm.set_df_property("exchange_rate", "hidden", 0);
|
||||||
frm.set_df_property('exchange_rate', 'hidden', 0);
|
frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency
|
||||||
frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency
|
+ " = [?] " + company_currency);
|
||||||
+ " = [?] " + company_currency);
|
}
|
||||||
}
|
});
|
||||||
});
|
} else {
|
||||||
} else {
|
frm.set_value("exchange_rate", 1.0);
|
||||||
frm.set_value("exchange_rate", 1.0);
|
frm.set_df_property("exchange_rate", "hidden", 1);
|
||||||
frm.set_df_property('exchange_rate', 'hidden', 1);
|
frm.set_df_property("exchange_rate", "description", "");
|
||||||
frm.set_df_property("exchange_rate", "description", "" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -738,21 +738,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var valid_serial_nos = [];
|
var valid_serial_nos = [];
|
||||||
|
var serialnos = [];
|
||||||
// Replacing all occurences of comma with carriage return
|
// Replacing all occurences of comma with carriage return
|
||||||
var serial_nos = item.serial_no.trim().replace(/,/g, '\n');
|
item.serial_no = item.serial_no.replace(/,/g, '\n');
|
||||||
|
serialnos = item.serial_no.split("\n");
|
||||||
serial_nos = serial_nos.trim().split('\n');
|
for (var i = 0; i < serialnos.length; i++) {
|
||||||
|
if (serialnos[i] != "") {
|
||||||
// Trim each string and push unique string to new list
|
valid_serial_nos.push(serialnos[i]);
|
||||||
for (var x=0; x<=serial_nos.length - 1; x++) {
|
|
||||||
if (serial_nos[x].trim() != "" && valid_serial_nos.indexOf(serial_nos[x].trim()) == -1) {
|
|
||||||
valid_serial_nos.push(serial_nos[x].trim());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the new list to the serial no. field in grid with each in new line
|
|
||||||
item.serial_no = valid_serial_nos.join('\n');
|
|
||||||
item.conversion_factor = item.conversion_factor || 1;
|
item.conversion_factor = item.conversion_factor || 1;
|
||||||
|
|
||||||
refresh_field("serial_no", item.name, item.parentfield);
|
refresh_field("serial_no", item.name, item.parentfield);
|
||||||
|
@ -78,7 +78,7 @@ class Gstr1Report(object):
|
|||||||
place_of_supply = invoice_details.get("place_of_supply")
|
place_of_supply = invoice_details.get("place_of_supply")
|
||||||
ecommerce_gstin = invoice_details.get("ecommerce_gstin")
|
ecommerce_gstin = invoice_details.get("ecommerce_gstin")
|
||||||
|
|
||||||
b2cs_output.setdefault((rate, place_of_supply, ecommerce_gstin, inv),{
|
b2cs_output.setdefault((rate, place_of_supply, ecommerce_gstin),{
|
||||||
"place_of_supply": "",
|
"place_of_supply": "",
|
||||||
"ecommerce_gstin": "",
|
"ecommerce_gstin": "",
|
||||||
"rate": "",
|
"rate": "",
|
||||||
@ -90,7 +90,7 @@ class Gstr1Report(object):
|
|||||||
"invoice_value": invoice_details.get("base_grand_total"),
|
"invoice_value": invoice_details.get("base_grand_total"),
|
||||||
})
|
})
|
||||||
|
|
||||||
row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin, inv))
|
row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin))
|
||||||
row["place_of_supply"] = place_of_supply
|
row["place_of_supply"] = place_of_supply
|
||||||
row["ecommerce_gstin"] = ecommerce_gstin
|
row["ecommerce_gstin"] = ecommerce_gstin
|
||||||
row["rate"] = rate
|
row["rate"] = rate
|
||||||
|
@ -397,6 +397,7 @@ erpnext.PointOfSale.Controller = class {
|
|||||||
this.recent_order_list.toggle_component(false);
|
this.recent_order_list.toggle_component(false);
|
||||||
frappe.run_serially([
|
frappe.run_serially([
|
||||||
() => this.frm.refresh(name),
|
() => this.frm.refresh(name),
|
||||||
|
() => this.frm.call('reset_mode_of_payments'),
|
||||||
() => this.cart.load_invoice(),
|
() => this.cart.load_invoice(),
|
||||||
() => this.item_selector.toggle_component(true)
|
() => this.item_selector.toggle_component(true)
|
||||||
]);
|
]);
|
||||||
|
@ -64,10 +64,7 @@ erpnext.PointOfSale.PastOrderSummary = class {
|
|||||||
{fieldname: 'print', fieldtype: 'Data', label: 'Print Preview'}
|
{fieldname: 'print', fieldtype: 'Data', label: 'Print Preview'}
|
||||||
],
|
],
|
||||||
primary_action: () => {
|
primary_action: () => {
|
||||||
const frm = this.events.get_frm();
|
this.print_receipt();
|
||||||
frm.doc = this.doc;
|
|
||||||
frm.print_preview.lang_code = frm.doc.language;
|
|
||||||
frm.print_preview.printit(true);
|
|
||||||
},
|
},
|
||||||
primary_action_label: __('Print'),
|
primary_action_label: __('Print'),
|
||||||
});
|
});
|
||||||
@ -192,13 +189,21 @@ erpnext.PointOfSale.PastOrderSummary = class {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.$summary_container.on('click', '.print-btn', () => {
|
this.$summary_container.on('click', '.print-btn', () => {
|
||||||
const frm = this.events.get_frm();
|
this.print_receipt();
|
||||||
frm.doc = this.doc;
|
|
||||||
frm.print_preview.lang_code = frm.doc.language;
|
|
||||||
frm.print_preview.printit(true);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print_receipt() {
|
||||||
|
const frm = this.events.get_frm();
|
||||||
|
frappe.utils.print(
|
||||||
|
frm.doctype,
|
||||||
|
frm.docname,
|
||||||
|
frm.pos_print_format,
|
||||||
|
frm.doc.letter_head,
|
||||||
|
frm.doc.language || frappe.boot.lang
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
attach_shortcuts() {
|
attach_shortcuts() {
|
||||||
const ctrl_label = frappe.utils.is_mac() ? '⌘' : 'Ctrl';
|
const ctrl_label = frappe.utils.is_mac() ? '⌘' : 'Ctrl';
|
||||||
this.$summary_container.find('.print-btn').attr("title", `${ctrl_label}+P`);
|
this.$summary_container.find('.print-btn').attr("title", `${ctrl_label}+P`);
|
||||||
|
@ -10,6 +10,7 @@ from frappe import msgprint, throw, _
|
|||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.model.naming import parse_naming_series
|
from frappe.model.naming import parse_naming_series
|
||||||
from frappe.permissions import get_doctypes_with_read
|
from frappe.permissions import get_doctypes_with_read
|
||||||
|
from frappe.core.doctype.doctype.doctype import validate_series
|
||||||
|
|
||||||
class NamingSeriesNotSetError(frappe.ValidationError): pass
|
class NamingSeriesNotSetError(frappe.ValidationError): pass
|
||||||
|
|
||||||
@ -126,7 +127,7 @@ class NamingSeries(Document):
|
|||||||
dt = frappe.get_doc("DocType", self.select_doc_for_series)
|
dt = frappe.get_doc("DocType", self.select_doc_for_series)
|
||||||
options = self.scrub_options_list(self.set_options.split("\n"))
|
options = self.scrub_options_list(self.set_options.split("\n"))
|
||||||
for series in options:
|
for series in options:
|
||||||
dt.validate_series(series)
|
validate_series(dt, series)
|
||||||
for i in sr:
|
for i in sr:
|
||||||
if i[0]:
|
if i[0]:
|
||||||
existing_series = [d.split('.')[0] for d in i[0].split("\n")]
|
existing_series = [d.split('.')[0] for d in i[0].split("\n")]
|
||||||
|
@ -1054,6 +1054,7 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "eval: doc.show_in_website || doc.show_variant_in_website",
|
||||||
"fieldname": "website_image_alt",
|
"fieldname": "website_image_alt",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Image Description"
|
"label": "Image Description"
|
||||||
@ -1066,7 +1067,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"max_attachments": 1,
|
"max_attachments": 1,
|
||||||
"modified": "2021-03-15 13:41:04.108932",
|
"modified": "2021-03-18 14:04:38.575519",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Item",
|
"name": "Item",
|
||||||
@ -1137,4 +1138,4 @@
|
|||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"title_field": "item_name",
|
"title_field": "item_name",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe, erpnext
|
import frappe, erpnext
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import cint, get_link_to_form
|
from frappe.utils import cint, get_link_to_form, add_to_date, today
|
||||||
from erpnext.stock.stock_ledger import repost_future_sle
|
from erpnext.stock.stock_ledger import repost_future_sle
|
||||||
from erpnext.accounts.utils import update_gl_entries_after, check_if_stock_and_account_balance_synced
|
from erpnext.accounts.utils import update_gl_entries_after, check_if_stock_and_account_balance_synced
|
||||||
from frappe.utils.user import get_users_with_role
|
from frappe.utils.user import get_users_with_role
|
||||||
@ -29,7 +29,7 @@ class RepostItemValuation(Document):
|
|||||||
self.company = frappe.get_cached_value(self.voucher_type, self.voucher_no, "company")
|
self.company = frappe.get_cached_value(self.voucher_type, self.voucher_no, "company")
|
||||||
elif self.warehouse:
|
elif self.warehouse:
|
||||||
self.company = frappe.get_cached_value("Warehouse", self.warehouse, "company")
|
self.company = frappe.get_cached_value("Warehouse", self.warehouse, "company")
|
||||||
|
|
||||||
def set_status(self, status=None):
|
def set_status(self, status=None):
|
||||||
if not status:
|
if not status:
|
||||||
status = 'Queued'
|
status = 'Queued'
|
||||||
@ -54,7 +54,6 @@ def repost(doc):
|
|||||||
|
|
||||||
repost_sl_entries(doc)
|
repost_sl_entries(doc)
|
||||||
repost_gl_entries(doc)
|
repost_gl_entries(doc)
|
||||||
check_if_stock_and_account_balance_synced(doc.posting_date, doc.company)
|
|
||||||
|
|
||||||
doc.set_status('Completed')
|
doc.set_status('Completed')
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -103,7 +102,7 @@ def notify_error_to_stock_managers(doc, traceback):
|
|||||||
recipients = get_users_with_role("Stock Manager")
|
recipients = get_users_with_role("Stock Manager")
|
||||||
if not recipients:
|
if not recipients:
|
||||||
get_users_with_role("System Manager")
|
get_users_with_role("System Manager")
|
||||||
|
|
||||||
subject = _("Error while reposting item valuation")
|
subject = _("Error while reposting item valuation")
|
||||||
message = (_("Hi,") + "<br>"
|
message = (_("Hi,") + "<br>"
|
||||||
+ _("An error has been appeared while reposting item valuation via {0}")
|
+ _("An error has been appeared while reposting item valuation via {0}")
|
||||||
@ -112,4 +111,24 @@ def notify_error_to_stock_managers(doc, traceback):
|
|||||||
)
|
)
|
||||||
frappe.sendmail(recipients=recipients, subject=subject, message=message)
|
frappe.sendmail(recipients=recipients, subject=subject, message=message)
|
||||||
|
|
||||||
|
def repost_entries():
|
||||||
|
riv_entries = get_repost_item_valuation_entries()
|
||||||
|
|
||||||
|
for row in riv_entries:
|
||||||
|
doc = frappe.get_cached_doc('Repost Item Valuation', row.name)
|
||||||
|
repost(doc)
|
||||||
|
|
||||||
|
riv_entries = get_repost_item_valuation_entries()
|
||||||
|
if riv_entries:
|
||||||
|
return
|
||||||
|
|
||||||
|
for d in frappe.get_all('Company', filters= {'enable_perpetual_inventory': 1}):
|
||||||
|
check_if_stock_and_account_balance_synced(today(), d.company)
|
||||||
|
|
||||||
|
def get_repost_item_valuation_entries():
|
||||||
|
date = add_to_date(today(), hours=-12)
|
||||||
|
|
||||||
|
return frappe.db.sql(""" SELECT name from `tabRepost Item Valuation`
|
||||||
|
WHERE status != 'Completed' and creation <= %s and docstatus = 1
|
||||||
|
ORDER BY timestamp(posting_date, posting_time) asc, creation asc
|
||||||
|
""", date, as_dict=1)
|
@ -458,7 +458,7 @@ class StockEntry(StockController):
|
|||||||
Set rate for outgoing, scrapped and finished items
|
Set rate for outgoing, scrapped and finished items
|
||||||
"""
|
"""
|
||||||
# Set rate for outgoing items
|
# Set rate for outgoing items
|
||||||
outgoing_items_cost = self.set_rate_for_outgoing_items(reset_outgoing_rate)
|
outgoing_items_cost = self.set_rate_for_outgoing_items(reset_outgoing_rate, raise_error_if_no_rate)
|
||||||
finished_item_qty = sum([d.transfer_qty for d in self.items if d.is_finished_item])
|
finished_item_qty = sum([d.transfer_qty for d in self.items if d.is_finished_item])
|
||||||
|
|
||||||
# Set basic rate for incoming items
|
# Set basic rate for incoming items
|
||||||
@ -482,13 +482,13 @@ class StockEntry(StockController):
|
|||||||
d.basic_rate = flt(d.basic_rate, d.precision("basic_rate"))
|
d.basic_rate = flt(d.basic_rate, d.precision("basic_rate"))
|
||||||
d.basic_amount = flt(flt(d.transfer_qty) * flt(d.basic_rate), d.precision("basic_amount"))
|
d.basic_amount = flt(flt(d.transfer_qty) * flt(d.basic_rate), d.precision("basic_amount"))
|
||||||
|
|
||||||
def set_rate_for_outgoing_items(self, reset_outgoing_rate=True):
|
def set_rate_for_outgoing_items(self, reset_outgoing_rate=True, raise_error_if_no_rate=True):
|
||||||
outgoing_items_cost = 0.0
|
outgoing_items_cost = 0.0
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if d.s_warehouse:
|
if d.s_warehouse:
|
||||||
if reset_outgoing_rate:
|
if reset_outgoing_rate:
|
||||||
args = self.get_args_for_incoming_rate(d)
|
args = self.get_args_for_incoming_rate(d)
|
||||||
rate = get_incoming_rate(args)
|
rate = get_incoming_rate(args, raise_error_if_no_rate)
|
||||||
if rate > 0:
|
if rate > 0:
|
||||||
d.basic_rate = rate
|
d.basic_rate = rate
|
||||||
|
|
||||||
@ -1010,7 +1010,8 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
self.set_scrap_items()
|
self.set_scrap_items()
|
||||||
self.set_actual_qty()
|
self.set_actual_qty()
|
||||||
self.calculate_rate_and_amount(raise_error_if_no_rate=False)
|
self.validate_customer_provided_item()
|
||||||
|
self.calculate_rate_and_amount()
|
||||||
|
|
||||||
def set_scrap_items(self):
|
def set_scrap_items(self):
|
||||||
if self.purpose != "Send to Subcontractor" and self.purpose in ["Manufacture", "Repack"]:
|
if self.purpose != "Send to Subcontractor" and self.purpose in ["Manufacture", "Repack"]:
|
||||||
|
Loading…
Reference in New Issue
Block a user