Merge branch 'develop' into fix-scrap-items-updation
This commit is contained in:
commit
3167b58aee
@ -9,19 +9,8 @@ import frappe
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
class TestFinanceBook(unittest.TestCase):
|
class TestFinanceBook(unittest.TestCase):
|
||||||
def create_finance_book(self):
|
|
||||||
if not frappe.db.exists("Finance Book", "_Test Finance Book"):
|
|
||||||
finance_book = frappe.get_doc({
|
|
||||||
"doctype": "Finance Book",
|
|
||||||
"finance_book_name": "_Test Finance Book"
|
|
||||||
}).insert()
|
|
||||||
else:
|
|
||||||
finance_book = frappe.get_doc("Finance Book", "_Test Finance Book")
|
|
||||||
|
|
||||||
return finance_book
|
|
||||||
|
|
||||||
def test_finance_book(self):
|
def test_finance_book(self):
|
||||||
finance_book = self.create_finance_book()
|
finance_book = create_finance_book()
|
||||||
|
|
||||||
# create jv entry
|
# create jv entry
|
||||||
jv = make_journal_entry("_Test Bank - _TC",
|
jv = make_journal_entry("_Test Bank - _TC",
|
||||||
@ -41,3 +30,14 @@ class TestFinanceBook(unittest.TestCase):
|
|||||||
|
|
||||||
for gl_entry in gl_entries:
|
for gl_entry in gl_entries:
|
||||||
self.assertEqual(gl_entry.finance_book, finance_book.name)
|
self.assertEqual(gl_entry.finance_book, finance_book.name)
|
||||||
|
|
||||||
|
def create_finance_book():
|
||||||
|
if not frappe.db.exists("Finance Book", "_Test Finance Book"):
|
||||||
|
finance_book = frappe.get_doc({
|
||||||
|
"doctype": "Finance Book",
|
||||||
|
"finance_book_name": "_Test Finance Book"
|
||||||
|
}).insert()
|
||||||
|
else:
|
||||||
|
finance_book = frappe.get_doc("Finance Book", "_Test Finance Book")
|
||||||
|
|
||||||
|
return finance_book
|
||||||
@ -50,9 +50,13 @@ class PeriodClosingVoucher(AccountsController):
|
|||||||
.format(pce[0][0], self.posting_date))
|
.format(pce[0][0], self.posting_date))
|
||||||
|
|
||||||
def make_gl_entries(self):
|
def make_gl_entries(self):
|
||||||
gl_entries = []
|
gl_entries = self.get_gl_entries()
|
||||||
net_pl_balance = 0
|
if gl_entries:
|
||||||
|
from erpnext.accounts.general_ledger import make_gl_entries
|
||||||
|
make_gl_entries(gl_entries)
|
||||||
|
|
||||||
|
def get_gl_entries(self):
|
||||||
|
gl_entries = []
|
||||||
pl_accounts = self.get_pl_balances()
|
pl_accounts = self.get_pl_balances()
|
||||||
|
|
||||||
for acc in pl_accounts:
|
for acc in pl_accounts:
|
||||||
@ -60,6 +64,7 @@ class PeriodClosingVoucher(AccountsController):
|
|||||||
gl_entries.append(self.get_gl_dict({
|
gl_entries.append(self.get_gl_dict({
|
||||||
"account": acc.account,
|
"account": acc.account,
|
||||||
"cost_center": acc.cost_center,
|
"cost_center": acc.cost_center,
|
||||||
|
"finance_book": acc.finance_book,
|
||||||
"account_currency": acc.account_currency,
|
"account_currency": acc.account_currency,
|
||||||
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0,
|
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0,
|
||||||
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0,
|
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0,
|
||||||
@ -67,35 +72,13 @@ class PeriodClosingVoucher(AccountsController):
|
|||||||
"credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0
|
"credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0
|
||||||
}, item=acc))
|
}, item=acc))
|
||||||
|
|
||||||
net_pl_balance += flt(acc.bal_in_company_currency)
|
if gl_entries:
|
||||||
|
gle_for_net_pl_bal = self.get_pnl_gl_entry(pl_accounts)
|
||||||
|
gl_entries += gle_for_net_pl_bal
|
||||||
|
|
||||||
if net_pl_balance:
|
return gl_entries
|
||||||
if self.cost_center_wise_pnl:
|
|
||||||
costcenter_wise_gl_entries = self.get_costcenter_wise_pnl_gl_entries(pl_accounts)
|
|
||||||
gl_entries += costcenter_wise_gl_entries
|
|
||||||
else:
|
|
||||||
gl_entry = self.get_pnl_gl_entry(net_pl_balance)
|
|
||||||
gl_entries.append(gl_entry)
|
|
||||||
|
|
||||||
from erpnext.accounts.general_ledger import make_gl_entries
|
def get_pnl_gl_entry(self, pl_accounts):
|
||||||
make_gl_entries(gl_entries)
|
|
||||||
|
|
||||||
def get_pnl_gl_entry(self, net_pl_balance):
|
|
||||||
cost_center = frappe.db.get_value("Company", self.company, "cost_center")
|
|
||||||
gl_entry = self.get_gl_dict({
|
|
||||||
"account": self.closing_account_head,
|
|
||||||
"debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
|
||||||
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
|
||||||
"credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
|
|
||||||
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0,
|
|
||||||
"cost_center": cost_center
|
|
||||||
})
|
|
||||||
|
|
||||||
self.update_default_dimensions(gl_entry)
|
|
||||||
|
|
||||||
return gl_entry
|
|
||||||
|
|
||||||
def get_costcenter_wise_pnl_gl_entries(self, pl_accounts):
|
|
||||||
company_cost_center = frappe.db.get_value("Company", self.company, "cost_center")
|
company_cost_center = frappe.db.get_value("Company", self.company, "cost_center")
|
||||||
gl_entries = []
|
gl_entries = []
|
||||||
|
|
||||||
@ -104,6 +87,7 @@ class PeriodClosingVoucher(AccountsController):
|
|||||||
gl_entry = self.get_gl_dict({
|
gl_entry = self.get_gl_dict({
|
||||||
"account": self.closing_account_head,
|
"account": self.closing_account_head,
|
||||||
"cost_center": acc.cost_center or company_cost_center,
|
"cost_center": acc.cost_center or company_cost_center,
|
||||||
|
"finance_book": acc.finance_book,
|
||||||
"account_currency": acc.account_currency,
|
"account_currency": acc.account_currency,
|
||||||
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0,
|
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0,
|
||||||
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0,
|
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0,
|
||||||
@ -130,7 +114,7 @@ class PeriodClosingVoucher(AccountsController):
|
|||||||
def get_pl_balances(self):
|
def get_pl_balances(self):
|
||||||
"""Get balance for dimension-wise pl accounts"""
|
"""Get balance for dimension-wise pl accounts"""
|
||||||
|
|
||||||
dimension_fields = ['t1.cost_center']
|
dimension_fields = ['t1.cost_center', 't1.finance_book']
|
||||||
|
|
||||||
self.accounting_dimensions = get_accounting_dimensions()
|
self.accounting_dimensions = get_accounting_dimensions()
|
||||||
for dimension in self.accounting_dimensions:
|
for dimension in self.accounting_dimensions:
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import frappe
|
|||||||
from frappe.utils import flt, today
|
from frappe.utils import flt, today
|
||||||
from erpnext.accounts.utils import get_fiscal_year, now
|
from erpnext.accounts.utils import get_fiscal_year, now
|
||||||
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
||||||
|
from erpnext.accounts.doctype.finance_book.test_finance_book import create_finance_book
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
|
|
||||||
class TestPeriodClosingVoucher(unittest.TestCase):
|
class TestPeriodClosingVoucher(unittest.TestCase):
|
||||||
@ -118,6 +119,58 @@ class TestPeriodClosingVoucher(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertTrue(pcv_gle, expected_gle)
|
self.assertTrue(pcv_gle, expected_gle)
|
||||||
|
|
||||||
|
def test_period_closing_with_finance_book_entries(self):
|
||||||
|
frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'")
|
||||||
|
|
||||||
|
company = create_company()
|
||||||
|
surplus_account = create_account()
|
||||||
|
cost_center = create_cost_center("Test Cost Center 1")
|
||||||
|
|
||||||
|
create_sales_invoice(
|
||||||
|
company=company,
|
||||||
|
income_account="Sales - TPC",
|
||||||
|
expense_account="Cost of Goods Sold - TPC",
|
||||||
|
cost_center=cost_center,
|
||||||
|
rate=400,
|
||||||
|
debit_to="Debtors - TPC"
|
||||||
|
)
|
||||||
|
jv = make_journal_entry(
|
||||||
|
account1="Cash - TPC",
|
||||||
|
account2="Sales - TPC",
|
||||||
|
amount=400,
|
||||||
|
cost_center=cost_center,
|
||||||
|
posting_date=now()
|
||||||
|
)
|
||||||
|
jv.company = company
|
||||||
|
jv.finance_book = create_finance_book().name
|
||||||
|
jv.save()
|
||||||
|
jv.submit()
|
||||||
|
|
||||||
|
pcv = frappe.get_doc({
|
||||||
|
"transaction_date": today(),
|
||||||
|
"posting_date": today(),
|
||||||
|
"fiscal_year": get_fiscal_year(today())[0],
|
||||||
|
"company": company,
|
||||||
|
"closing_account_head": surplus_account,
|
||||||
|
"remarks": "Test",
|
||||||
|
"doctype": "Period Closing Voucher"
|
||||||
|
})
|
||||||
|
pcv.insert()
|
||||||
|
pcv.submit()
|
||||||
|
|
||||||
|
expected_gle = (
|
||||||
|
(surplus_account, 0.0, 400.0, ''),
|
||||||
|
(surplus_account, 0.0, 400.0, jv.finance_book),
|
||||||
|
('Sales - TPC', 400.0, 0.0, ''),
|
||||||
|
('Sales - TPC', 400.0, 0.0, jv.finance_book)
|
||||||
|
)
|
||||||
|
|
||||||
|
pcv_gle = frappe.db.sql("""
|
||||||
|
select account, debit, credit, finance_book from `tabGL Entry` where voucher_no=%s
|
||||||
|
""", (pcv.name))
|
||||||
|
|
||||||
|
self.assertTrue(pcv_gle, expected_gle)
|
||||||
|
|
||||||
def make_period_closing_voucher(self):
|
def make_period_closing_voucher(self):
|
||||||
pcv = frappe.get_doc({
|
pcv = frappe.get_doc({
|
||||||
"doctype": "Period Closing Voucher",
|
"doctype": "Period Closing Voucher",
|
||||||
|
|||||||
@ -85,9 +85,15 @@ class TestPOSClosingEntry(unittest.TestCase):
|
|||||||
|
|
||||||
pcv_doc.load_from_db()
|
pcv_doc.load_from_db()
|
||||||
pcv_doc.cancel()
|
pcv_doc.cancel()
|
||||||
si_doc.load_from_db()
|
|
||||||
|
cancelled_invoice = frappe.db.get_value(
|
||||||
|
'POS Invoice Merge Log', {'pos_closing_entry': pcv_doc.name},
|
||||||
|
'consolidated_invoice'
|
||||||
|
)
|
||||||
|
docstatus = frappe.db.get_value("Sales Invoice", cancelled_invoice, 'docstatus')
|
||||||
|
self.assertEqual(docstatus, 2)
|
||||||
|
|
||||||
pos_inv1.load_from_db()
|
pos_inv1.load_from_db()
|
||||||
self.assertEqual(si_doc.docstatus, 2)
|
|
||||||
self.assertEqual(pos_inv1.status, 'Paid')
|
self.assertEqual(pos_inv1.status, 'Paid')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
|
|||||||
|
|
||||||
onload(doc) {
|
onload(doc) {
|
||||||
super.onload();
|
super.onload();
|
||||||
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log'];
|
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log', 'POS Closing Entry'];
|
||||||
if(doc.__islocal && doc.is_pos && frappe.get_route_str() !== 'point-of-sale') {
|
if(doc.__islocal && doc.is_pos && frappe.get_route_str() !== 'point-of-sale') {
|
||||||
this.frm.script_manager.trigger("is_pos");
|
this.frm.script_manager.trigger("is_pos");
|
||||||
this.frm.refresh_fields();
|
this.frm.refresh_fields();
|
||||||
|
|||||||
@ -99,6 +99,7 @@
|
|||||||
"loyalty_redemption_account",
|
"loyalty_redemption_account",
|
||||||
"loyalty_redemption_cost_center",
|
"loyalty_redemption_cost_center",
|
||||||
"section_break_49",
|
"section_break_49",
|
||||||
|
"coupon_code",
|
||||||
"apply_discount_on",
|
"apply_discount_on",
|
||||||
"base_discount_amount",
|
"base_discount_amount",
|
||||||
"column_break_51",
|
"column_break_51",
|
||||||
@ -1550,6 +1551,14 @@
|
|||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Sales Invoice",
|
"options": "Sales Invoice",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "coupon_code",
|
||||||
|
"fieldname": "coupon_code",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Coupon Code",
|
||||||
|
"options": "Coupon Code",
|
||||||
|
"print_hide": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
|
|||||||
@ -44,6 +44,9 @@ class POSInvoice(SalesInvoice):
|
|||||||
self.validate_pos()
|
self.validate_pos()
|
||||||
self.validate_payment_amount()
|
self.validate_payment_amount()
|
||||||
self.validate_loyalty_transaction()
|
self.validate_loyalty_transaction()
|
||||||
|
if self.coupon_code:
|
||||||
|
from erpnext.accounts.doctype.pricing_rule.utils import validate_coupon_code
|
||||||
|
validate_coupon_code(self.coupon_code)
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
# create the loyalty point ledger entry if the customer is enrolled in any loyalty program
|
# create the loyalty point ledger entry if the customer is enrolled in any loyalty program
|
||||||
@ -58,6 +61,10 @@ class POSInvoice(SalesInvoice):
|
|||||||
self.check_phone_payments()
|
self.check_phone_payments()
|
||||||
self.set_status(update=True)
|
self.set_status(update=True)
|
||||||
|
|
||||||
|
if self.coupon_code:
|
||||||
|
from erpnext.accounts.doctype.pricing_rule.utils import update_coupon_code_count
|
||||||
|
update_coupon_code_count(self.coupon_code,'used')
|
||||||
|
|
||||||
def before_cancel(self):
|
def before_cancel(self):
|
||||||
if self.consolidated_invoice and frappe.db.get_value('Sales Invoice', self.consolidated_invoice, 'docstatus') == 1:
|
if self.consolidated_invoice and frappe.db.get_value('Sales Invoice', self.consolidated_invoice, 'docstatus') == 1:
|
||||||
pos_closing_entry = frappe.get_all(
|
pos_closing_entry = frappe.get_all(
|
||||||
@ -84,6 +91,10 @@ class POSInvoice(SalesInvoice):
|
|||||||
against_psi_doc.delete_loyalty_point_entry()
|
against_psi_doc.delete_loyalty_point_entry()
|
||||||
against_psi_doc.make_loyalty_point_entry()
|
against_psi_doc.make_loyalty_point_entry()
|
||||||
|
|
||||||
|
if self.coupon_code:
|
||||||
|
from erpnext.accounts.doctype.pricing_rule.utils import update_coupon_code_count
|
||||||
|
update_coupon_code_count(self.coupon_code,'cancelled')
|
||||||
|
|
||||||
def check_phone_payments(self):
|
def check_phone_payments(self):
|
||||||
for pay in self.payments:
|
for pay in self.payments:
|
||||||
if pay.type == "Phone" and pay.amount >= 0:
|
if pay.type == "Phone" and pay.amount >= 0:
|
||||||
@ -127,7 +138,7 @@ class POSInvoice(SalesInvoice):
|
|||||||
.format(item.idx, bold_delivered_serial_nos), title=_("Item Unavailable"))
|
.format(item.idx, bold_delivered_serial_nos), title=_("Item Unavailable"))
|
||||||
|
|
||||||
def validate_stock_availablility(self):
|
def validate_stock_availablility(self):
|
||||||
if self.is_return:
|
if self.is_return or self.docstatus != 1:
|
||||||
return
|
return
|
||||||
|
|
||||||
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
|
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
|
||||||
|
|||||||
@ -198,12 +198,19 @@ def apply_pricing_rule(args, doc=None):
|
|||||||
set_serial_nos_based_on_fifo = frappe.db.get_single_value("Stock Settings",
|
set_serial_nos_based_on_fifo = frappe.db.get_single_value("Stock Settings",
|
||||||
"automatically_set_serial_nos_based_on_fifo")
|
"automatically_set_serial_nos_based_on_fifo")
|
||||||
|
|
||||||
|
item_code_list = tuple(item.get('item_code') for item in item_list)
|
||||||
|
query_items = frappe.get_all('Item', fields=['item_code','has_serial_no'], filters=[['item_code','in',item_code_list]],as_list=1)
|
||||||
|
serialized_items = dict()
|
||||||
|
for item_code, val in query_items:
|
||||||
|
serialized_items.setdefault(item_code, val)
|
||||||
|
|
||||||
for item in item_list:
|
for item in item_list:
|
||||||
args_copy = copy.deepcopy(args)
|
args_copy = copy.deepcopy(args)
|
||||||
args_copy.update(item)
|
args_copy.update(item)
|
||||||
data = get_pricing_rule_for_item(args_copy, item.get('price_list_rate'), doc=doc)
|
data = get_pricing_rule_for_item(args_copy, item.get('price_list_rate'), doc=doc)
|
||||||
out.append(data)
|
out.append(data)
|
||||||
if not item.get("serial_no") and set_serial_nos_based_on_fifo and not args.get('is_return'):
|
|
||||||
|
if serialized_items.get(item.get('item_code')) and not item.get("serial_no") and set_serial_nos_based_on_fifo and not args.get('is_return'):
|
||||||
out[0].update(get_serial_no_for_item(args_copy))
|
out[0].update(get_serial_no_for_item(args_copy))
|
||||||
|
|
||||||
return out
|
return out
|
||||||
|
|||||||
@ -101,7 +101,7 @@ def merge_similar_entries(gl_map, precision=None):
|
|||||||
|
|
||||||
def check_if_in_list(gle, gl_map, dimensions=None):
|
def check_if_in_list(gle, gl_map, dimensions=None):
|
||||||
account_head_fieldnames = ['voucher_detail_no', 'party', 'against_voucher',
|
account_head_fieldnames = ['voucher_detail_no', 'party', 'against_voucher',
|
||||||
'cost_center', 'against_voucher_type', 'party_type', 'project']
|
'cost_center', 'against_voucher_type', 'party_type', 'project', 'finance_book']
|
||||||
|
|
||||||
if dimensions:
|
if dimensions:
|
||||||
account_head_fieldnames = account_head_fieldnames + dimensions
|
account_head_fieldnames = account_head_fieldnames + dimensions
|
||||||
|
|||||||
@ -1,16 +1,20 @@
|
|||||||
{
|
{
|
||||||
"add_total_row": 1,
|
"add_total_row": 0,
|
||||||
|
"columns": [],
|
||||||
"creation": "2013-02-25 17:03:34",
|
"creation": "2013-02-25 17:03:34",
|
||||||
|
"disable_prepared_report": 0,
|
||||||
"disabled": 0,
|
"disabled": 0,
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Report",
|
"doctype": "Report",
|
||||||
|
"filters": [],
|
||||||
"idx": 3,
|
"idx": 3,
|
||||||
"is_standard": "Yes",
|
"is_standard": "Yes",
|
||||||
"modified": "2020-08-13 11:26:39.112352",
|
"modified": "2021-08-19 18:57:07.468202",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Gross Profit",
|
"name": "Gross Profit",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
"prepared_report": 0,
|
||||||
"ref_doctype": "Sales Invoice",
|
"ref_doctype": "Sales Invoice",
|
||||||
"report_name": "Gross Profit",
|
"report_name": "Gross Profit",
|
||||||
"report_type": "Script Report",
|
"report_type": "Script Report",
|
||||||
|
|||||||
@ -41,12 +41,14 @@ def execute(filters=None):
|
|||||||
|
|
||||||
columns = get_columns(group_wise_columns, filters)
|
columns = get_columns(group_wise_columns, filters)
|
||||||
|
|
||||||
for src in gross_profit_data.grouped_data:
|
for idx, src in enumerate(gross_profit_data.grouped_data):
|
||||||
row = []
|
row = []
|
||||||
for col in group_wise_columns.get(scrub(filters.group_by)):
|
for col in group_wise_columns.get(scrub(filters.group_by)):
|
||||||
row.append(src.get(col))
|
row.append(src.get(col))
|
||||||
|
|
||||||
row.append(filters.currency)
|
row.append(filters.currency)
|
||||||
|
if idx == len(gross_profit_data.grouped_data)-1:
|
||||||
|
row[0] = frappe.bold("Total")
|
||||||
data.append(row)
|
data.append(row)
|
||||||
|
|
||||||
return columns, data
|
return columns, data
|
||||||
@ -154,6 +156,15 @@ class GrossProfitGenerator(object):
|
|||||||
|
|
||||||
def get_average_rate_based_on_group_by(self):
|
def get_average_rate_based_on_group_by(self):
|
||||||
# sum buying / selling totals for group
|
# sum buying / selling totals for group
|
||||||
|
self.totals = frappe._dict(
|
||||||
|
qty=0,
|
||||||
|
base_amount=0,
|
||||||
|
buying_amount=0,
|
||||||
|
gross_profit=0,
|
||||||
|
gross_profit_percent=0,
|
||||||
|
base_rate=0,
|
||||||
|
buying_rate=0
|
||||||
|
)
|
||||||
for key in list(self.grouped):
|
for key in list(self.grouped):
|
||||||
if self.filters.get("group_by") != "Invoice":
|
if self.filters.get("group_by") != "Invoice":
|
||||||
for i, row in enumerate(self.grouped[key]):
|
for i, row in enumerate(self.grouped[key]):
|
||||||
@ -165,6 +176,7 @@ class GrossProfitGenerator(object):
|
|||||||
new_row.base_amount += flt(row.base_amount, self.currency_precision)
|
new_row.base_amount += flt(row.base_amount, self.currency_precision)
|
||||||
new_row = self.set_average_rate(new_row)
|
new_row = self.set_average_rate(new_row)
|
||||||
self.grouped_data.append(new_row)
|
self.grouped_data.append(new_row)
|
||||||
|
self.add_to_totals(new_row)
|
||||||
else:
|
else:
|
||||||
for i, row in enumerate(self.grouped[key]):
|
for i, row in enumerate(self.grouped[key]):
|
||||||
if row.parent in self.returned_invoices \
|
if row.parent in self.returned_invoices \
|
||||||
@ -177,15 +189,25 @@ class GrossProfitGenerator(object):
|
|||||||
if row.qty or row.base_amount:
|
if row.qty or row.base_amount:
|
||||||
row = self.set_average_rate(row)
|
row = self.set_average_rate(row)
|
||||||
self.grouped_data.append(row)
|
self.grouped_data.append(row)
|
||||||
|
self.add_to_totals(row)
|
||||||
|
self.set_average_gross_profit(self.totals)
|
||||||
|
self.grouped_data.append(self.totals)
|
||||||
|
|
||||||
def set_average_rate(self, new_row):
|
def set_average_rate(self, new_row):
|
||||||
|
self.set_average_gross_profit(new_row)
|
||||||
|
new_row.buying_rate = flt(new_row.buying_amount / new_row.qty, self.float_precision) if new_row.qty else 0
|
||||||
|
new_row.base_rate = flt(new_row.base_amount / new_row.qty, self.float_precision) if new_row.qty else 0
|
||||||
|
return new_row
|
||||||
|
|
||||||
|
def set_average_gross_profit(self, new_row):
|
||||||
new_row.gross_profit = flt(new_row.base_amount - new_row.buying_amount, self.currency_precision)
|
new_row.gross_profit = flt(new_row.base_amount - new_row.buying_amount, self.currency_precision)
|
||||||
new_row.gross_profit_percent = flt(((new_row.gross_profit / new_row.base_amount) * 100.0), self.currency_precision) \
|
new_row.gross_profit_percent = flt(((new_row.gross_profit / new_row.base_amount) * 100.0), self.currency_precision) \
|
||||||
if new_row.base_amount else 0
|
if new_row.base_amount else 0
|
||||||
new_row.buying_rate = flt(new_row.buying_amount / new_row.qty, self.float_precision) if new_row.qty else 0
|
|
||||||
new_row.base_rate = flt(new_row.base_amount / new_row.qty, self.float_precision) if new_row.qty else 0
|
|
||||||
|
|
||||||
return new_row
|
def add_to_totals(self, new_row):
|
||||||
|
for key in self.totals:
|
||||||
|
if new_row.get(key):
|
||||||
|
self.totals[key] += new_row[key]
|
||||||
|
|
||||||
def get_returned_invoice_items(self):
|
def get_returned_invoice_items(self):
|
||||||
returned_invoices = frappe.db.sql("""
|
returned_invoices = frappe.db.sql("""
|
||||||
|
|||||||
@ -329,7 +329,6 @@ def make_return_doc(doctype, source_name, target_doc=None):
|
|||||||
target_doc.po_detail = source_doc.po_detail
|
target_doc.po_detail = source_doc.po_detail
|
||||||
target_doc.pr_detail = source_doc.pr_detail
|
target_doc.pr_detail = source_doc.pr_detail
|
||||||
target_doc.purchase_invoice_item = source_doc.name
|
target_doc.purchase_invoice_item = source_doc.name
|
||||||
target_doc.price_list_rate = 0
|
|
||||||
|
|
||||||
elif doctype == "Delivery Note":
|
elif doctype == "Delivery Note":
|
||||||
returned_qty_map = get_returned_qty_map_for_row(source_doc.name, doctype)
|
returned_qty_map = get_returned_qty_map_for_row(source_doc.name, doctype)
|
||||||
@ -360,7 +359,6 @@ def make_return_doc(doctype, source_name, target_doc=None):
|
|||||||
else:
|
else:
|
||||||
target_doc.pos_invoice_item = source_doc.name
|
target_doc.pos_invoice_item = source_doc.name
|
||||||
|
|
||||||
target_doc.price_list_rate = 0
|
|
||||||
if default_warehouse_for_sales_return:
|
if default_warehouse_for_sales_return:
|
||||||
target_doc.warehouse = default_warehouse_for_sales_return
|
target_doc.warehouse = default_warehouse_for_sales_return
|
||||||
|
|
||||||
|
|||||||
@ -2242,12 +2242,19 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
|||||||
|
|
||||||
coupon_code() {
|
coupon_code() {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
if (this.frm.doc.coupon_code) {
|
||||||
frappe.run_serially([
|
frappe.run_serially([
|
||||||
() => this.frm.doc.ignore_pricing_rule=1,
|
() => this.frm.doc.ignore_pricing_rule=1,
|
||||||
() => me.ignore_pricing_rule(),
|
() => me.ignore_pricing_rule(),
|
||||||
() => this.frm.doc.ignore_pricing_rule=0,
|
() => this.frm.doc.ignore_pricing_rule=0,
|
||||||
() => me.apply_pricing_rule()
|
() => me.apply_pricing_rule()
|
||||||
]);
|
]);
|
||||||
|
} else {
|
||||||
|
frappe.run_serially([
|
||||||
|
() => this.frm.doc.ignore_pricing_rule=1,
|
||||||
|
() => me.ignore_pricing_rule()
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -860,6 +860,8 @@
|
|||||||
|
|
||||||
.invoice-fields {
|
.invoice-fields {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
height: 100%;
|
||||||
|
padding-right: var(--padding-sm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -531,6 +531,7 @@ def make_custom_fields(update=True):
|
|||||||
fieldtype='Link', options='Salary Component', insert_after='hra_section'),
|
fieldtype='Link', options='Salary Component', insert_after='hra_section'),
|
||||||
dict(fieldname='hra_component', label='HRA Component',
|
dict(fieldname='hra_component', label='HRA Component',
|
||||||
fieldtype='Link', options='Salary Component', insert_after='basic_component'),
|
fieldtype='Link', options='Salary Component', insert_after='basic_component'),
|
||||||
|
dict(fieldname='hra_column_break', fieldtype='Column Break', insert_after='hra_component'),
|
||||||
dict(fieldname='arrear_component', label='Arrear Component',
|
dict(fieldname='arrear_component', label='Arrear Component',
|
||||||
fieldtype='Link', options='Salary Component', insert_after='hra_component'),
|
fieldtype='Link', options='Salary Component', insert_after='hra_component'),
|
||||||
dict(fieldname='non_profit_section', label='Non Profit Settings',
|
dict(fieldname='non_profit_section', label='Non Profit Settings',
|
||||||
@ -539,6 +540,7 @@ def make_custom_fields(update=True):
|
|||||||
fieldtype='Data', insert_after='non_profit_section'),
|
fieldtype='Data', insert_after='non_profit_section'),
|
||||||
dict(fieldname='with_effect_from', label='80G With Effect From',
|
dict(fieldname='with_effect_from', label='80G With Effect From',
|
||||||
fieldtype='Date', insert_after='company_80g_number'),
|
fieldtype='Date', insert_after='company_80g_number'),
|
||||||
|
dict(fieldname='non_profit_column_break', fieldtype='Column Break', insert_after='with_effect_from'),
|
||||||
dict(fieldname='pan_details', label='PAN Number',
|
dict(fieldname='pan_details', label='PAN Number',
|
||||||
fieldtype='Data', insert_after='with_effect_from')
|
fieldtype='Data', insert_after='with_effect_from')
|
||||||
],
|
],
|
||||||
|
|||||||
@ -6,9 +6,8 @@ import frappe
|
|||||||
from frappe.utils import flt, cstr
|
from frappe.utils import flt, cstr
|
||||||
from erpnext.controllers.taxes_and_totals import get_itemised_tax
|
from erpnext.controllers.taxes_and_totals import get_itemised_tax
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.core.doctype.file.file import remove_file
|
from frappe.utils.file_manager import remove_file
|
||||||
from six import string_types
|
from six import string_types
|
||||||
from frappe.desk.form.load import get_attachments
|
|
||||||
from erpnext.regional.italy import state_codes
|
from erpnext.regional.italy import state_codes
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -46,6 +46,43 @@ frappe.ui.form.on("Company", {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
change_abbreviation(frm) {
|
||||||
|
var dialog = new frappe.ui.Dialog({
|
||||||
|
title: "Replace Abbr",
|
||||||
|
fields: [
|
||||||
|
{"fieldtype": "Data", "label": "New Abbreviation", "fieldname": "new_abbr",
|
||||||
|
"reqd": 1 },
|
||||||
|
{"fieldtype": "Button", "label": "Update", "fieldname": "update"},
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.fields_dict.update.$input.click(function() {
|
||||||
|
var args = dialog.get_values();
|
||||||
|
if (!args) return;
|
||||||
|
frappe.show_alert(__("Update in progress. It might take a while."));
|
||||||
|
return frappe.call({
|
||||||
|
method: "erpnext.setup.doctype.company.company.enqueue_replace_abbr",
|
||||||
|
args: {
|
||||||
|
"company": frm.doc.name,
|
||||||
|
"old": frm.doc.abbr,
|
||||||
|
"new": args.new_abbr
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if (r.exc) {
|
||||||
|
frappe.msgprint(__("There were errors."));
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
frm.set_value("abbr", args.new_abbr);
|
||||||
|
}
|
||||||
|
dialog.hide();
|
||||||
|
frm.refresh();
|
||||||
|
},
|
||||||
|
btn: this
|
||||||
|
});
|
||||||
|
});
|
||||||
|
dialog.show();
|
||||||
|
},
|
||||||
|
|
||||||
company_name: function(frm) {
|
company_name: function(frm) {
|
||||||
if(frm.doc.__islocal) {
|
if(frm.doc.__islocal) {
|
||||||
// add missing " " arg in split method
|
// add missing " " arg in split method
|
||||||
@ -127,6 +164,10 @@ frappe.ui.form.on("Company", {
|
|||||||
}, __('Manage'));
|
}, __('Manage'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frm.add_custom_button(__('Change Abbreviation'), () => {
|
||||||
|
frm.trigger('change_abbreviation');
|
||||||
|
}, __('Manage'));
|
||||||
}
|
}
|
||||||
|
|
||||||
erpnext.company.set_chart_of_accounts_options(frm.doc);
|
erpnext.company.set_chart_of_accounts_options(frm.doc);
|
||||||
@ -204,43 +245,6 @@ erpnext.company.set_chart_of_accounts_options = function(doc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.cscript.change_abbr = function() {
|
|
||||||
var dialog = new frappe.ui.Dialog({
|
|
||||||
title: "Replace Abbr",
|
|
||||||
fields: [
|
|
||||||
{"fieldtype": "Data", "label": "New Abbreviation", "fieldname": "new_abbr",
|
|
||||||
"reqd": 1 },
|
|
||||||
{"fieldtype": "Button", "label": "Update", "fieldname": "update"},
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
dialog.fields_dict.update.$input.click(function() {
|
|
||||||
var args = dialog.get_values();
|
|
||||||
if(!args) return;
|
|
||||||
frappe.show_alert(__("Update in progress. It might take a while."));
|
|
||||||
return frappe.call({
|
|
||||||
method: "erpnext.setup.doctype.company.company.enqueue_replace_abbr",
|
|
||||||
args: {
|
|
||||||
"company": cur_frm.doc.name,
|
|
||||||
"old": cur_frm.doc.abbr,
|
|
||||||
"new": args.new_abbr
|
|
||||||
},
|
|
||||||
callback: function(r) {
|
|
||||||
if(r.exc) {
|
|
||||||
frappe.msgprint(__("There were errors."));
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
cur_frm.set_value("abbr", args.new_abbr);
|
|
||||||
}
|
|
||||||
dialog.hide();
|
|
||||||
cur_frm.refresh();
|
|
||||||
},
|
|
||||||
btn: this
|
|
||||||
})
|
|
||||||
});
|
|
||||||
dialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
erpnext.company.setup_queries = function(frm) {
|
erpnext.company.setup_queries = function(frm) {
|
||||||
$.each([
|
$.each([
|
||||||
["default_bank_account", {"account_type": "Bank"}],
|
["default_bank_account", {"account_type": "Bank"}],
|
||||||
|
|||||||
@ -12,33 +12,48 @@
|
|||||||
"details",
|
"details",
|
||||||
"company_name",
|
"company_name",
|
||||||
"abbr",
|
"abbr",
|
||||||
"change_abbr",
|
"default_currency",
|
||||||
|
"country",
|
||||||
"is_group",
|
"is_group",
|
||||||
"cb0",
|
"cb0",
|
||||||
"domain",
|
|
||||||
"parent_company",
|
|
||||||
"charts_section",
|
|
||||||
"default_currency",
|
|
||||||
"default_letter_head",
|
"default_letter_head",
|
||||||
"default_holiday_list",
|
|
||||||
"default_finance_book",
|
|
||||||
"default_selling_terms",
|
|
||||||
"default_buying_terms",
|
|
||||||
"default_warehouse_for_sales_return",
|
|
||||||
"default_in_transit_warehouse",
|
|
||||||
"column_break_10",
|
|
||||||
"country",
|
|
||||||
"create_chart_of_accounts_based_on",
|
|
||||||
"chart_of_accounts",
|
|
||||||
"existing_company",
|
|
||||||
"tax_id",
|
"tax_id",
|
||||||
|
"domain",
|
||||||
"date_of_establishment",
|
"date_of_establishment",
|
||||||
|
"parent_company",
|
||||||
|
"company_info",
|
||||||
|
"company_logo",
|
||||||
|
"date_of_incorporation",
|
||||||
|
"phone_no",
|
||||||
|
"email",
|
||||||
|
"company_description",
|
||||||
|
"column_break1",
|
||||||
|
"date_of_commencement",
|
||||||
|
"fax",
|
||||||
|
"website",
|
||||||
|
"address_html",
|
||||||
|
"section_break_28",
|
||||||
|
"create_chart_of_accounts_based_on",
|
||||||
|
"existing_company",
|
||||||
|
"column_break_26",
|
||||||
|
"chart_of_accounts",
|
||||||
|
"charts_section",
|
||||||
"sales_settings",
|
"sales_settings",
|
||||||
"monthly_sales_target",
|
"default_buying_terms",
|
||||||
"sales_monthly_history",
|
"sales_monthly_history",
|
||||||
"column_break_goals",
|
"monthly_sales_target",
|
||||||
"transactions_annual_history",
|
|
||||||
"total_monthly_sales",
|
"total_monthly_sales",
|
||||||
|
"column_break_goals",
|
||||||
|
"default_selling_terms",
|
||||||
|
"default_warehouse_for_sales_return",
|
||||||
|
"credit_limit",
|
||||||
|
"transactions_annual_history",
|
||||||
|
"hr_settings_section",
|
||||||
|
"default_holiday_list",
|
||||||
|
"default_expense_claim_payable_account",
|
||||||
|
"column_break_10",
|
||||||
|
"default_employee_advance_account",
|
||||||
|
"default_payroll_payable_account",
|
||||||
"default_settings",
|
"default_settings",
|
||||||
"default_bank_account",
|
"default_bank_account",
|
||||||
"default_cash_account",
|
"default_cash_account",
|
||||||
@ -52,24 +67,20 @@
|
|||||||
"column_break0",
|
"column_break0",
|
||||||
"allow_account_creation_against_child_company",
|
"allow_account_creation_against_child_company",
|
||||||
"default_payable_account",
|
"default_payable_account",
|
||||||
"default_employee_advance_account",
|
|
||||||
"default_expense_account",
|
"default_expense_account",
|
||||||
"default_income_account",
|
"default_income_account",
|
||||||
"default_deferred_revenue_account",
|
"default_deferred_revenue_account",
|
||||||
"default_deferred_expense_account",
|
"default_deferred_expense_account",
|
||||||
"default_payroll_payable_account",
|
|
||||||
"default_expense_claim_payable_account",
|
|
||||||
"default_discount_account",
|
"default_discount_account",
|
||||||
"section_break_22",
|
|
||||||
"cost_center",
|
|
||||||
"column_break_26",
|
|
||||||
"credit_limit",
|
|
||||||
"payment_terms",
|
"payment_terms",
|
||||||
|
"cost_center",
|
||||||
|
"default_finance_book",
|
||||||
"auto_accounting_for_stock_settings",
|
"auto_accounting_for_stock_settings",
|
||||||
"enable_perpetual_inventory",
|
"enable_perpetual_inventory",
|
||||||
"enable_perpetual_inventory_for_non_stock_items",
|
"enable_perpetual_inventory_for_non_stock_items",
|
||||||
"default_inventory_account",
|
"default_inventory_account",
|
||||||
"stock_adjustment_account",
|
"stock_adjustment_account",
|
||||||
|
"default_in_transit_warehouse",
|
||||||
"column_break_32",
|
"column_break_32",
|
||||||
"stock_received_but_not_billed",
|
"stock_received_but_not_billed",
|
||||||
"service_received_but_not_billed",
|
"service_received_but_not_billed",
|
||||||
@ -79,25 +90,14 @@
|
|||||||
"depreciation_expense_account",
|
"depreciation_expense_account",
|
||||||
"series_for_depreciation_entry",
|
"series_for_depreciation_entry",
|
||||||
"expenses_included_in_asset_valuation",
|
"expenses_included_in_asset_valuation",
|
||||||
|
"repair_and_maintenance_account",
|
||||||
"column_break_40",
|
"column_break_40",
|
||||||
"disposal_account",
|
"disposal_account",
|
||||||
"depreciation_cost_center",
|
"depreciation_cost_center",
|
||||||
"capital_work_in_progress_account",
|
"capital_work_in_progress_account",
|
||||||
"repair_and_maintenance_account",
|
|
||||||
"asset_received_but_not_billed",
|
"asset_received_but_not_billed",
|
||||||
"budget_detail",
|
"budget_detail",
|
||||||
"exception_budget_approver_role",
|
"exception_budget_approver_role",
|
||||||
"company_info",
|
|
||||||
"company_logo",
|
|
||||||
"date_of_incorporation",
|
|
||||||
"address_html",
|
|
||||||
"date_of_commencement",
|
|
||||||
"phone_no",
|
|
||||||
"fax",
|
|
||||||
"email",
|
|
||||||
"website",
|
|
||||||
"column_break1",
|
|
||||||
"company_description",
|
|
||||||
"registration_info",
|
"registration_info",
|
||||||
"registration_details",
|
"registration_details",
|
||||||
"lft",
|
"lft",
|
||||||
@ -127,12 +127,6 @@
|
|||||||
"oldfieldtype": "Data",
|
"oldfieldtype": "Data",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"depends_on": "eval:!doc.__islocal && in_list(frappe.user_roles, \"System Manager\")",
|
|
||||||
"fieldname": "change_abbr",
|
|
||||||
"fieldtype": "Button",
|
|
||||||
"label": "Change Abbreviation"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"bold": 1,
|
"bold": 1,
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@ -176,10 +170,9 @@
|
|||||||
"label": "Company Description"
|
"label": "Company Description"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
|
||||||
"fieldname": "sales_settings",
|
"fieldname": "sales_settings",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Sales Settings"
|
"label": "Buying & Selling Settings"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "sales_monthly_history",
|
"fieldname": "sales_monthly_history",
|
||||||
@ -442,10 +435,6 @@
|
|||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Account"
|
"options": "Account"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "section_break_22",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"depends_on": "eval:!doc.__islocal",
|
"depends_on": "eval:!doc.__islocal",
|
||||||
"fieldname": "cost_center",
|
"fieldname": "cost_center",
|
||||||
@ -455,10 +444,6 @@
|
|||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Cost Center"
|
"options": "Cost Center"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "column_break_26",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"depends_on": "eval:!doc.__islocal",
|
"depends_on": "eval:!doc.__islocal",
|
||||||
"fieldname": "credit_limit",
|
"fieldname": "credit_limit",
|
||||||
@ -589,10 +574,10 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"description": "For reference only.",
|
"depends_on": "eval: doc.docstatus == 0 && doc.__islocal != 1",
|
||||||
"fieldname": "company_info",
|
"fieldname": "company_info",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Company Info"
|
"label": "Address & Contact"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "date_of_incorporation",
|
"fieldname": "date_of_incorporation",
|
||||||
@ -741,6 +726,20 @@
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Repair and Maintenance Account",
|
"label": "Repair and Maintenance Account",
|
||||||
"options": "Account"
|
"options": "Account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_28",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Chart of Accounts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "hr_settings_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "HR & Payroll Settings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_26",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-building",
|
"icon": "fa fa-building",
|
||||||
@ -748,7 +747,7 @@
|
|||||||
"image_field": "company_logo",
|
"image_field": "company_logo",
|
||||||
"is_tree": 1,
|
"is_tree": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-05-12 16:51:08.187233",
|
"modified": "2021-07-12 11:27:06.353860",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "Company",
|
"name": "Company",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user