solved conflicts
This commit is contained in:
commit
d6d78bb08e
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"autoname": "hash",
|
"autoname": "hash",
|
||||||
"creation": "2013-05-22 12:43:10",
|
"creation": "2013-05-22 12:43:10",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
@ -507,7 +508,8 @@
|
|||||||
"depends_on": "enable_deferred_expense",
|
"depends_on": "enable_deferred_expense",
|
||||||
"fieldname": "service_stop_date",
|
"fieldname": "service_stop_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Service Stop Date"
|
"label": "Service Stop Date",
|
||||||
|
"no_copy": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@ -523,13 +525,15 @@
|
|||||||
"depends_on": "enable_deferred_expense",
|
"depends_on": "enable_deferred_expense",
|
||||||
"fieldname": "service_start_date",
|
"fieldname": "service_start_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Service Start Date"
|
"label": "Service Start Date",
|
||||||
|
"no_copy": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "enable_deferred_expense",
|
"depends_on": "enable_deferred_expense",
|
||||||
"fieldname": "service_end_date",
|
"fieldname": "service_end_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Service End Date"
|
"label": "Service End Date",
|
||||||
|
"no_copy": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "reference",
|
"fieldname": "reference",
|
||||||
@ -766,7 +770,8 @@
|
|||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-11-21 16:27:52.043744",
|
"links": [],
|
||||||
|
"modified": "2019-12-04 12:23:17.046413",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Invoice Item",
|
"name": "Purchase Invoice Item",
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"autoname": "hash",
|
"autoname": "hash",
|
||||||
"creation": "2013-06-04 11:02:19",
|
"creation": "2013-06-04 11:02:19",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
@ -484,7 +485,8 @@
|
|||||||
"depends_on": "enable_deferred_revenue",
|
"depends_on": "enable_deferred_revenue",
|
||||||
"fieldname": "service_stop_date",
|
"fieldname": "service_stop_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Service Stop Date"
|
"label": "Service Stop Date",
|
||||||
|
"no_copy": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@ -500,13 +502,15 @@
|
|||||||
"depends_on": "enable_deferred_revenue",
|
"depends_on": "enable_deferred_revenue",
|
||||||
"fieldname": "service_start_date",
|
"fieldname": "service_start_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Service Start Date"
|
"label": "Service Start Date",
|
||||||
|
"no_copy": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "enable_deferred_revenue",
|
"depends_on": "enable_deferred_revenue",
|
||||||
"fieldname": "service_end_date",
|
"fieldname": "service_end_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Service End Date"
|
"label": "Service End Date",
|
||||||
|
"no_copy": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
@ -783,7 +787,8 @@
|
|||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-07-16 16:36:46.527606",
|
"links": [],
|
||||||
|
"modified": "2019-12-04 12:22:38.517710",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice Item",
|
"name": "Sales Invoice Item",
|
||||||
|
@ -88,6 +88,11 @@ frappe.query_reports["Accounts Payable Summary"] = {
|
|||||||
"label": __("Supplier Group"),
|
"label": __("Supplier Group"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Supplier Group"
|
"options": "Supplier Group"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"based_on_payment_terms",
|
||||||
|
"label": __("Based On Payment Terms"),
|
||||||
|
"fieldtype": "Check",
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ class ReceivablePayableReport(object):
|
|||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
self.get_gl_entries()
|
self.get_gl_entries()
|
||||||
|
self.get_sales_invoices_or_customers_based_on_sales_person()
|
||||||
self.voucher_balance = OrderedDict()
|
self.voucher_balance = OrderedDict()
|
||||||
self.init_voucher_balance() # invoiced, paid, credit_note, outstanding
|
self.init_voucher_balance() # invoiced, paid, credit_note, outstanding
|
||||||
|
|
||||||
@ -103,12 +104,18 @@ class ReceivablePayableReport(object):
|
|||||||
|
|
||||||
def get_invoices(self, gle):
|
def get_invoices(self, gle):
|
||||||
if gle.voucher_type in ('Sales Invoice', 'Purchase Invoice'):
|
if gle.voucher_type in ('Sales Invoice', 'Purchase Invoice'):
|
||||||
self.invoices.add(gle.voucher_no)
|
if self.filters.get("sales_person"):
|
||||||
|
if gle.voucher_no in self.sales_person_records.get("Sales Invoice", []) \
|
||||||
|
or gle.party in self.sales_person_records.get("Customer", []):
|
||||||
|
self.invoices.add(gle.voucher_no)
|
||||||
|
else:
|
||||||
|
self.invoices.add(gle.voucher_no)
|
||||||
|
|
||||||
def update_voucher_balance(self, gle):
|
def update_voucher_balance(self, gle):
|
||||||
# get the row where this balance needs to be updated
|
# get the row where this balance needs to be updated
|
||||||
# if its a payment, it will return the linked invoice or will be considered as advance
|
# if its a payment, it will return the linked invoice or will be considered as advance
|
||||||
row = self.get_voucher_balance(gle)
|
row = self.get_voucher_balance(gle)
|
||||||
|
if not row: return
|
||||||
# gle_balance will be the total "debit - credit" for receivable type reports and
|
# gle_balance will be the total "debit - credit" for receivable type reports and
|
||||||
# and vice-versa for payable type reports
|
# and vice-versa for payable type reports
|
||||||
gle_balance = self.get_gle_balance(gle)
|
gle_balance = self.get_gle_balance(gle)
|
||||||
@ -129,8 +136,13 @@ class ReceivablePayableReport(object):
|
|||||||
row.paid -= gle_balance
|
row.paid -= gle_balance
|
||||||
|
|
||||||
def get_voucher_balance(self, gle):
|
def get_voucher_balance(self, gle):
|
||||||
voucher_balance = None
|
if self.filters.get("sales_person"):
|
||||||
|
against_voucher = gle.against_voucher or gle.voucher_no
|
||||||
|
if not (gle.party in self.sales_person_records.get("Customer", []) or \
|
||||||
|
against_voucher in self.sales_person_records.get("Sales Invoice", [])):
|
||||||
|
return
|
||||||
|
|
||||||
|
voucher_balance = None
|
||||||
if gle.against_voucher:
|
if gle.against_voucher:
|
||||||
# find invoice
|
# find invoice
|
||||||
against_voucher = gle.against_voucher
|
against_voucher = gle.against_voucher
|
||||||
@ -512,6 +524,22 @@ class ReceivablePayableReport(object):
|
|||||||
order by posting_date, party"""
|
order by posting_date, party"""
|
||||||
.format(select_fields, conditions), values, as_dict=True)
|
.format(select_fields, conditions), values, as_dict=True)
|
||||||
|
|
||||||
|
def get_sales_invoices_or_customers_based_on_sales_person(self):
|
||||||
|
if self.filters.get("sales_person"):
|
||||||
|
lft, rgt = frappe.db.get_value("Sales Person",
|
||||||
|
self.filters.get("sales_person"), ["lft", "rgt"])
|
||||||
|
|
||||||
|
records = frappe.db.sql("""
|
||||||
|
select distinct parent, parenttype
|
||||||
|
from `tabSales Team` steam
|
||||||
|
where parenttype in ('Customer', 'Sales Invoice')
|
||||||
|
and exists(select name from `tabSales Person` where lft >= %s and rgt <= %s and name = steam.sales_person)
|
||||||
|
""", (lft, rgt), as_dict=1)
|
||||||
|
|
||||||
|
self.sales_person_records = frappe._dict()
|
||||||
|
for d in records:
|
||||||
|
self.sales_person_records.setdefault(d.parenttype, set()).add(d.parent)
|
||||||
|
|
||||||
def prepare_conditions(self):
|
def prepare_conditions(self):
|
||||||
conditions = [""]
|
conditions = [""]
|
||||||
values = [self.party_type, self.filters.report_date]
|
values = [self.party_type, self.filters.report_date]
|
||||||
@ -564,16 +592,6 @@ class ReceivablePayableReport(object):
|
|||||||
conditions.append("party in (select name from tabCustomer where default_sales_partner=%s)")
|
conditions.append("party in (select name from tabCustomer where default_sales_partner=%s)")
|
||||||
values.append(self.filters.get("sales_partner"))
|
values.append(self.filters.get("sales_partner"))
|
||||||
|
|
||||||
if self.filters.get("sales_person"):
|
|
||||||
lft, rgt = frappe.db.get_value("Sales Person",
|
|
||||||
self.filters.get("sales_person"), ["lft", "rgt"])
|
|
||||||
|
|
||||||
conditions.append("""exists(select name from `tabSales Team` steam where
|
|
||||||
steam.sales_person in (select name from `tabSales Person` where lft >= {0} and rgt <= {1})
|
|
||||||
and ((steam.parent = voucher_no and steam.parenttype = voucher_type)
|
|
||||||
or (steam.parent = against_voucher and steam.parenttype = against_voucher_type)
|
|
||||||
or (steam.parent = party and steam.parenttype = 'Customer')))""".format(lft, rgt))
|
|
||||||
|
|
||||||
def add_supplier_filters(self, conditions, values):
|
def add_supplier_filters(self, conditions, values):
|
||||||
if self.filters.get("supplier_group"):
|
if self.filters.get("supplier_group"):
|
||||||
conditions.append("""party in (select name from tabSupplier
|
conditions.append("""party in (select name from tabSupplier
|
||||||
|
@ -106,6 +106,11 @@ frappe.query_reports["Accounts Receivable Summary"] = {
|
|||||||
"label": __("Sales Person"),
|
"label": __("Sales Person"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Sales Person"
|
"options": "Sales Person"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"based_on_payment_terms",
|
||||||
|
"label": __("Based On Payment Terms"),
|
||||||
|
"fieldtype": "Check",
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -26,5 +26,11 @@ frappe.query_reports["Fixed Asset Register"] = {
|
|||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
options: "Finance Book"
|
options: "Finance Book"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fieldname:"date",
|
||||||
|
label: __("Date"),
|
||||||
|
fieldtype: "Date",
|
||||||
|
default: frappe.datetime.get_today()
|
||||||
|
},
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import cstr
|
from frappe.utils import cstr, today, flt
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
filters = frappe._dict(filters or {})
|
filters = frappe._dict(filters or {})
|
||||||
@ -86,8 +86,8 @@ def get_columns(filters):
|
|||||||
"width": 90
|
"width": 90
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": _("Current Value"),
|
"label": _("Asset Value"),
|
||||||
"fieldname": "current_value",
|
"fieldname": "asset_value",
|
||||||
"options": "Currency",
|
"options": "Currency",
|
||||||
"width": 90
|
"width": 90
|
||||||
},
|
},
|
||||||
@ -114,7 +114,7 @@ def get_data(filters):
|
|||||||
data = []
|
data = []
|
||||||
|
|
||||||
conditions = get_conditions(filters)
|
conditions = get_conditions(filters)
|
||||||
current_value_map = get_finance_book_value_map(filters.finance_book)
|
depreciation_amount_map = get_finance_book_value_map(filters.date, filters.finance_book)
|
||||||
pr_supplier_map = get_purchase_receipt_supplier_map()
|
pr_supplier_map = get_purchase_receipt_supplier_map()
|
||||||
pi_supplier_map = get_purchase_invoice_supplier_map()
|
pi_supplier_map = get_purchase_invoice_supplier_map()
|
||||||
|
|
||||||
@ -125,7 +125,9 @@ def get_data(filters):
|
|||||||
"available_for_use_date", "status", "purchase_invoice"])
|
"available_for_use_date", "status", "purchase_invoice"])
|
||||||
|
|
||||||
for asset in assets_record:
|
for asset in assets_record:
|
||||||
if current_value_map.get(asset.name) is not None:
|
asset_value = asset.gross_purchase_amount - flt(asset.opening_accumulated_depreciation) \
|
||||||
|
- flt(depreciation_amount_map.get(asset.name))
|
||||||
|
if asset_value:
|
||||||
row = {
|
row = {
|
||||||
"asset_id": asset.name,
|
"asset_id": asset.name,
|
||||||
"asset_name": asset.asset_name,
|
"asset_name": asset.asset_name,
|
||||||
@ -138,19 +140,24 @@ def get_data(filters):
|
|||||||
"location": asset.location,
|
"location": asset.location,
|
||||||
"asset_category": asset.asset_category,
|
"asset_category": asset.asset_category,
|
||||||
"purchase_date": asset.purchase_date,
|
"purchase_date": asset.purchase_date,
|
||||||
"current_value": current_value_map.get(asset.name)
|
"asset_value": asset_value
|
||||||
}
|
}
|
||||||
data.append(row)
|
data.append(row)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def get_finance_book_value_map(finance_book=''):
|
def get_finance_book_value_map(date, finance_book=''):
|
||||||
|
if not date:
|
||||||
|
date = today()
|
||||||
return frappe._dict(frappe.db.sql(''' Select
|
return frappe._dict(frappe.db.sql(''' Select
|
||||||
parent, value_after_depreciation
|
parent, SUM(depreciation_amount)
|
||||||
FROM `tabAsset Finance Book`
|
FROM `tabDepreciation Schedule`
|
||||||
WHERE
|
WHERE
|
||||||
parentfield='finance_books'
|
parentfield='schedules'
|
||||||
AND ifnull(finance_book, '')=%s''', cstr(finance_book)))
|
AND schedule_date<=%s
|
||||||
|
AND journal_entry IS NOT NULL
|
||||||
|
AND ifnull(finance_book, '')=%s
|
||||||
|
GROUP BY parent''', (date, cstr(finance_book))))
|
||||||
|
|
||||||
def get_purchase_receipt_supplier_map():
|
def get_purchase_receipt_supplier_map():
|
||||||
return frappe._dict(frappe.db.sql(''' Select
|
return frappe._dict(frappe.db.sql(''' Select
|
||||||
|
@ -17,6 +17,8 @@ from erpnext.stock.doctype.material_request.material_request import make_purchas
|
|||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||||
from erpnext.controllers.accounts_controller import update_child_qty_rate
|
from erpnext.controllers.accounts_controller import update_child_qty_rate
|
||||||
from erpnext.controllers.status_updater import OverAllowanceError
|
from erpnext.controllers.status_updater import OverAllowanceError
|
||||||
|
from erpnext.manufacturing.doctype.blanket_order.test_blanket_order import make_blanket_order
|
||||||
|
|
||||||
|
|
||||||
class TestPurchaseOrder(unittest.TestCase):
|
class TestPurchaseOrder(unittest.TestCase):
|
||||||
def test_make_purchase_receipt(self):
|
def test_make_purchase_receipt(self):
|
||||||
@ -620,6 +622,27 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
po.save()
|
po.save()
|
||||||
self.assertEqual(po.schedule_date, add_days(nowdate(), 2))
|
self.assertEqual(po.schedule_date, add_days(nowdate(), 2))
|
||||||
|
|
||||||
|
|
||||||
|
def test_po_optional_blanket_order(self):
|
||||||
|
"""
|
||||||
|
Expected result: Blanket order Ordered Quantity should only be affected on Purchase Order with against_blanket_order = 1.
|
||||||
|
Second Purchase Order should not add on to Blanket Orders Ordered Quantity.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bo = make_blanket_order(blanket_order_type = "Purchasing", quantity = 10, rate = 10)
|
||||||
|
|
||||||
|
po = create_purchase_order(item_code= "_Test Item", qty = 5, against_blanket_order = 1)
|
||||||
|
po_doc = frappe.get_doc('Purchase Order', po.get('name'))
|
||||||
|
# To test if the PO has a Blanket Order
|
||||||
|
self.assertTrue(po_doc.items[0].blanket_order)
|
||||||
|
|
||||||
|
po = create_purchase_order(item_code= "_Test Item", qty = 5, against_blanket_order = 0)
|
||||||
|
po_doc = frappe.get_doc('Purchase Order', po.get('name'))
|
||||||
|
# To test if the PO does NOT have a Blanket Order
|
||||||
|
self.assertEqual(po_doc.items[0].blanket_order, None)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def make_pr_against_po(po, received_qty=0):
|
def make_pr_against_po(po, received_qty=0):
|
||||||
pr = make_purchase_receipt(po)
|
pr = make_purchase_receipt(po)
|
||||||
@ -693,7 +716,8 @@ def create_purchase_order(**args):
|
|||||||
"qty": args.qty or 10,
|
"qty": args.qty or 10,
|
||||||
"rate": args.rate or 500,
|
"rate": args.rate or 500,
|
||||||
"schedule_date": add_days(nowdate(), 1),
|
"schedule_date": add_days(nowdate(), 1),
|
||||||
"include_exploded_items": args.get('include_exploded_items', 1)
|
"include_exploded_items": args.get('include_exploded_items', 1),
|
||||||
|
"against_blanket_order": args.against_blanket_order
|
||||||
})
|
})
|
||||||
if not args.do_not_save:
|
if not args.do_not_save:
|
||||||
po.insert()
|
po.insert()
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
"base_amount",
|
"base_amount",
|
||||||
"pricing_rules",
|
"pricing_rules",
|
||||||
"is_free_item",
|
"is_free_item",
|
||||||
"is_fixed_asset",
|
|
||||||
"section_break_29",
|
"section_break_29",
|
||||||
"net_rate",
|
"net_rate",
|
||||||
"net_amount",
|
"net_amount",
|
||||||
@ -67,6 +66,7 @@
|
|||||||
"supplier_quotation",
|
"supplier_quotation",
|
||||||
"supplier_quotation_item",
|
"supplier_quotation_item",
|
||||||
"col_break5",
|
"col_break5",
|
||||||
|
"against_blanket_order",
|
||||||
"blanket_order",
|
"blanket_order",
|
||||||
"blanket_order_rate",
|
"blanket_order_rate",
|
||||||
"item_group",
|
"item_group",
|
||||||
@ -511,6 +511,7 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "eval:doc.against_blanket_order",
|
||||||
"fieldname": "blanket_order",
|
"fieldname": "blanket_order",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Blanket Order",
|
"label": "Blanket Order",
|
||||||
@ -518,6 +519,7 @@
|
|||||||
"options": "Blanket Order"
|
"options": "Blanket Order"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "eval:doc.against_blanket_order",
|
||||||
"fieldname": "blanket_order_rate",
|
"fieldname": "blanket_order_rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Blanket Order Rate",
|
"label": "Blanket Order Rate",
|
||||||
@ -703,16 +705,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"fetch_from": "item_code.is_fixed_asset",
|
"fieldname": "against_blanket_order",
|
||||||
"fieldname": "is_fixed_asset",
|
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Is Fixed Asset",
|
"label": "Against Blanket Order"
|
||||||
"read_only": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-11-07 17:19:12.090355",
|
"modified": "2019-11-19 14:10:52.865006",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order Item",
|
"name": "Purchase Order Item",
|
||||||
|
@ -61,7 +61,6 @@ class AccountsController(TransactionBase):
|
|||||||
_('{0} is blocked so this transaction cannot proceed'.format(supplier_name)), raise_exception=1)
|
_('{0} is blocked so this transaction cannot proceed'.format(supplier_name)), raise_exception=1)
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
|
||||||
if not self.get('is_return'):
|
if not self.get('is_return'):
|
||||||
self.validate_qty_is_not_zero()
|
self.validate_qty_is_not_zero()
|
||||||
|
|
||||||
@ -100,11 +99,23 @@ class AccountsController(TransactionBase):
|
|||||||
|
|
||||||
if self.is_return:
|
if self.is_return:
|
||||||
self.validate_qty()
|
self.validate_qty()
|
||||||
|
else:
|
||||||
|
self.validate_deferred_start_and_end_date()
|
||||||
|
|
||||||
validate_regional(self)
|
validate_regional(self)
|
||||||
if self.doctype != 'Material Request':
|
if self.doctype != 'Material Request':
|
||||||
apply_pricing_rule_on_transaction(self)
|
apply_pricing_rule_on_transaction(self)
|
||||||
|
|
||||||
|
def validate_deferred_start_and_end_date(self):
|
||||||
|
for d in self.items:
|
||||||
|
if d.get("enable_deferred_revenue") or d.get("enable_deferred_expense"):
|
||||||
|
if not (d.service_start_date and d.service_end_date):
|
||||||
|
frappe.throw(_("Row #{0}: Service Start and End Date is required for deferred accounting").format(d.idx))
|
||||||
|
elif getdate(d.service_start_date) > getdate(d.service_end_date):
|
||||||
|
frappe.throw(_("Row #{0}: Service Start Date cannot be greater than Service End Date").format(d.idx))
|
||||||
|
elif getdate(self.posting_date) > getdate(d.service_end_date):
|
||||||
|
frappe.throw(_("Row #{0}: Service End Date cannot be before Invoice Posting Date").format(d.idx))
|
||||||
|
|
||||||
def validate_invoice_documents_schedule(self):
|
def validate_invoice_documents_schedule(self):
|
||||||
self.validate_payment_schedule_dates()
|
self.validate_payment_schedule_dates()
|
||||||
self.set_due_date()
|
self.set_due_date()
|
||||||
|
@ -130,10 +130,10 @@ class Opportunity(TransactionBase):
|
|||||||
|
|
||||||
def has_lost_quotation(self):
|
def has_lost_quotation(self):
|
||||||
lost_quotation = frappe.db.sql("""
|
lost_quotation = frappe.db.sql("""
|
||||||
select q.name
|
select name
|
||||||
from `tabQuotation` q, `tabQuotation Item` qi
|
from `tabQuotation`
|
||||||
where q.name = qi.parent and q.docstatus=1
|
where docstatus=1
|
||||||
and qi.prevdoc_docname =%s and q.status = 'Lost'
|
and opportunity =%s and status = 'Lost'
|
||||||
""", self.name)
|
""", self.name)
|
||||||
if lost_quotation:
|
if lost_quotation:
|
||||||
if self.has_active_quotation():
|
if self.has_active_quotation():
|
||||||
|
@ -153,7 +153,7 @@ class Employee(NestedSet):
|
|||||||
throw(_("Date Of Retirement must be greater than Date of Joining"))
|
throw(_("Date Of Retirement must be greater than Date of Joining"))
|
||||||
|
|
||||||
elif self.relieving_date and self.date_of_joining and (getdate(self.relieving_date) < getdate(self.date_of_joining)):
|
elif self.relieving_date and self.date_of_joining and (getdate(self.relieving_date) < getdate(self.date_of_joining)):
|
||||||
throw(_("Relieving Date must be greater than Date of Joining"))
|
throw(_("Relieving Date must be greater than or equal to Date of Joining"))
|
||||||
|
|
||||||
elif self.contract_end_date and self.date_of_joining and (getdate(self.contract_end_date) <= getdate(self.date_of_joining)):
|
elif self.contract_end_date and self.date_of_joining and (getdate(self.contract_end_date) <= getdate(self.date_of_joining)):
|
||||||
throw(_("Contract End Date must be greater than Date of Joining"))
|
throw(_("Contract End Date must be greater than Date of Joining"))
|
||||||
|
@ -44,6 +44,8 @@ def make_sales_order(source_name):
|
|||||||
target.item_name = item.get("item_name")
|
target.item_name = item.get("item_name")
|
||||||
target.description = item.get("description")
|
target.description = item.get("description")
|
||||||
target.uom = item.get("stock_uom")
|
target.uom = item.get("stock_uom")
|
||||||
|
target.against_blanket_order = 1
|
||||||
|
target.blanket_order = source_name
|
||||||
|
|
||||||
target_doc = get_mapped_doc("Blanket Order", source_name, {
|
target_doc = get_mapped_doc("Blanket Order", source_name, {
|
||||||
"Blanket Order": {
|
"Blanket Order": {
|
||||||
@ -71,6 +73,8 @@ def make_purchase_order(source_name):
|
|||||||
target.description = item.get("description")
|
target.description = item.get("description")
|
||||||
target.uom = item.get("stock_uom")
|
target.uom = item.get("stock_uom")
|
||||||
target.warehouse = item.get("default_warehouse")
|
target.warehouse = item.get("default_warehouse")
|
||||||
|
target.against_blanket_order = 1
|
||||||
|
target.blanket_order = source_name
|
||||||
|
|
||||||
target_doc = get_mapped_doc("Blanket Order", source_name, {
|
target_doc = get_mapped_doc("Blanket Order", source_name, {
|
||||||
"Blanket Order": {
|
"Blanket Order": {
|
||||||
|
@ -62,12 +62,12 @@ def execute():
|
|||||||
]
|
]
|
||||||
|
|
||||||
for dt in doctypes:
|
for dt in doctypes:
|
||||||
for d in frappe.db.sql("""select name, parent, item_code, item_tax_rate from `tab{0} Item`
|
for d in frappe.db.sql("""select name, parenttype, parent, item_code, item_tax_rate from `tab{0} Item`
|
||||||
where ifnull(item_tax_rate, '') not in ('', '{{}}')
|
where ifnull(item_tax_rate, '') not in ('', '{{}}')
|
||||||
and item_tax_template is NULL""".format(dt), as_dict=1):
|
and item_tax_template is NULL""".format(dt), as_dict=1):
|
||||||
item_tax_map = json.loads(d.item_tax_rate)
|
item_tax_map = json.loads(d.item_tax_rate)
|
||||||
item_tax_template_name = get_item_tax_template(item_tax_templates,
|
item_tax_template_name = get_item_tax_template(item_tax_templates,
|
||||||
item_tax_map, d.item_code, d.parent)
|
item_tax_map, d.item_code, d.parenttype, d.parent)
|
||||||
frappe.db.set_value(dt + " Item", d.name, "item_tax_template", item_tax_template_name)
|
frappe.db.set_value(dt + " Item", d.name, "item_tax_template", item_tax_template_name)
|
||||||
|
|
||||||
frappe.db.auto_commit_on_many_writes = False
|
frappe.db.auto_commit_on_many_writes = False
|
||||||
@ -77,7 +77,7 @@ def execute():
|
|||||||
settings.determine_address_tax_category_from = "Billing Address"
|
settings.determine_address_tax_category_from = "Billing Address"
|
||||||
settings.save()
|
settings.save()
|
||||||
|
|
||||||
def get_item_tax_template(item_tax_templates, item_tax_map, item_code, parent=None):
|
def get_item_tax_template(item_tax_templates, item_tax_map, item_code, parenttype=None, parent=None):
|
||||||
# search for previously created item tax template by comparing tax maps
|
# search for previously created item tax template by comparing tax maps
|
||||||
for template, item_tax_template_map in iteritems(item_tax_templates):
|
for template, item_tax_template_map in iteritems(item_tax_templates):
|
||||||
if item_tax_map == item_tax_template_map:
|
if item_tax_map == item_tax_template_map:
|
||||||
@ -88,23 +88,44 @@ def get_item_tax_template(item_tax_templates, item_tax_map, item_code, parent=No
|
|||||||
item_tax_template.title = make_autoname("Item Tax Template-.####")
|
item_tax_template.title = make_autoname("Item Tax Template-.####")
|
||||||
|
|
||||||
for tax_type, tax_rate in iteritems(item_tax_map):
|
for tax_type, tax_rate in iteritems(item_tax_map):
|
||||||
if not frappe.db.exists("Account", tax_type):
|
account_details = frappe.db.get_value("Account", tax_type, ['name', 'account_type'], as_dict=1)
|
||||||
|
if account_details:
|
||||||
|
if account_details.account_type not in ('Tax', 'Chargeable', 'Income Account', 'Expense Account', 'Expenses Included In Valuation'):
|
||||||
|
frappe.db.set_value('Account', account_details.name, 'account_type', 'Chargeable')
|
||||||
|
else:
|
||||||
parts = tax_type.strip().split(" - ")
|
parts = tax_type.strip().split(" - ")
|
||||||
account_name = " - ".join(parts[:-1])
|
account_name = " - ".join(parts[:-1])
|
||||||
company = frappe.db.get_value("Company", filters={"abbr": parts[-1]})
|
company = get_company(parts[-1], parenttype, parent)
|
||||||
parent_account = frappe.db.get_value("Account",
|
parent_account = frappe.db.get_value("Account",
|
||||||
filters={"account_type": "Tax", "root_type": "Liability", "is_group": 0, "company": company}, fieldname="parent_account")
|
filters={"account_type": "Tax", "root_type": "Liability", "is_group": 0, "company": company}, fieldname="parent_account")
|
||||||
|
filters = {
|
||||||
frappe.get_doc({
|
|
||||||
"doctype": "Account",
|
|
||||||
"account_name": account_name,
|
"account_name": account_name,
|
||||||
"company": company,
|
"company": company,
|
||||||
"account_type": "Tax",
|
"account_type": "Tax",
|
||||||
"parent_account": parent_account
|
"parent_account": parent_account
|
||||||
}).insert()
|
}
|
||||||
|
tax_type = frappe.db.get_value("Account", filters)
|
||||||
|
if not tax_type:
|
||||||
|
account = frappe.new_doc("Account")
|
||||||
|
account.update(filters)
|
||||||
|
account.insert()
|
||||||
|
tax_type = account.name
|
||||||
|
|
||||||
item_tax_template.append("taxes", {"tax_type": tax_type, "tax_rate": tax_rate})
|
item_tax_template.append("taxes", {"tax_type": tax_type, "tax_rate": tax_rate})
|
||||||
item_tax_templates.setdefault(item_tax_template.title, {})
|
item_tax_templates.setdefault(item_tax_template.title, {})
|
||||||
item_tax_templates[item_tax_template.title][tax_type] = tax_rate
|
item_tax_templates[item_tax_template.title][tax_type] = tax_rate
|
||||||
item_tax_template.save()
|
item_tax_template.save()
|
||||||
return item_tax_template.name
|
return item_tax_template.name
|
||||||
|
|
||||||
|
def get_company(company_abbr, parenttype=None, parent=None):
|
||||||
|
if parenttype and parent:
|
||||||
|
company = frappe.get_cached_value(parenttype, parent, 'company')
|
||||||
|
else:
|
||||||
|
company = frappe.db.get_value("Company", filters={"abbr": company_abbr})
|
||||||
|
|
||||||
|
if not company:
|
||||||
|
companies = frappe.get_all('Company')
|
||||||
|
if len(companies) == 1:
|
||||||
|
company = companies[0].name
|
||||||
|
|
||||||
|
return company
|
||||||
|
@ -1716,6 +1716,14 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
against_blanket_order: function(doc, cdt, cdn) {
|
||||||
|
var item = locals[cdt][cdn];
|
||||||
|
if(!item.against_blanket_order) {
|
||||||
|
frappe.model.set_value(this.frm.doctype + " Item", item.name, "blanket_order", null);
|
||||||
|
frappe.model.set_value(this.frm.doctype + " Item", item.name, "blanket_order_rate", 0.00);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
blanket_order: function(doc, cdt, cdn) {
|
blanket_order: function(doc, cdt, cdn) {
|
||||||
var me = this;
|
var me = this;
|
||||||
var item = locals[cdt][cdn];
|
var item = locals[cdt][cdn];
|
||||||
|
@ -12,6 +12,7 @@ from erpnext.selling.doctype.sales_order.sales_order import make_work_orders
|
|||||||
from erpnext.controllers.accounts_controller import update_child_qty_rate
|
from erpnext.controllers.accounts_controller import update_child_qty_rate
|
||||||
import json
|
import json
|
||||||
from erpnext.selling.doctype.sales_order.sales_order import make_raw_material_request
|
from erpnext.selling.doctype.sales_order.sales_order import make_raw_material_request
|
||||||
|
from erpnext.manufacturing.doctype.blanket_order.test_blanket_order import make_blanket_order
|
||||||
|
|
||||||
class TestSalesOrder(unittest.TestCase):
|
class TestSalesOrder(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@ -819,6 +820,25 @@ class TestSalesOrder(unittest.TestCase):
|
|||||||
mr_doc = frappe.get_doc('Material Request',mr.get('name'))
|
mr_doc = frappe.get_doc('Material Request',mr.get('name'))
|
||||||
self.assertEqual(mr_doc.items[0].sales_order, so.name)
|
self.assertEqual(mr_doc.items[0].sales_order, so.name)
|
||||||
|
|
||||||
|
def test_so_optional_blanket_order(self):
|
||||||
|
"""
|
||||||
|
Expected result: Blanket order Ordered Quantity should only be affected on Sales Order with against_blanket_order = 1.
|
||||||
|
Second Sales Order should not add on to Blanket Orders Ordered Quantity.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bo = make_blanket_order(blanket_order_type = "Selling", quantity = 10, rate = 10)
|
||||||
|
|
||||||
|
so = make_sales_order(item_code= "_Test Item", qty = 5, against_blanket_order = 1)
|
||||||
|
so_doc = frappe.get_doc('Sales Order', so.get('name'))
|
||||||
|
# To test if the SO has a Blanket Order
|
||||||
|
self.assertTrue(so_doc.items[0].blanket_order)
|
||||||
|
|
||||||
|
so = make_sales_order(item_code= "_Test Item", qty = 5, against_blanket_order = 0)
|
||||||
|
so_doc = frappe.get_doc('Sales Order', so.get('name'))
|
||||||
|
# To test if the SO does NOT have a Blanket Order
|
||||||
|
self.assertEqual(so_doc.items[0].blanket_order, None)
|
||||||
|
|
||||||
|
|
||||||
def make_sales_order(**args):
|
def make_sales_order(**args):
|
||||||
so = frappe.new_doc("Sales Order")
|
so = frappe.new_doc("Sales Order")
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
@ -845,7 +865,8 @@ def make_sales_order(**args):
|
|||||||
"warehouse": args.warehouse,
|
"warehouse": args.warehouse,
|
||||||
"qty": args.qty or 10,
|
"qty": args.qty or 10,
|
||||||
"uom": args.uom or None,
|
"uom": args.uom or None,
|
||||||
"rate": args.rate or 100
|
"rate": args.rate or 100,
|
||||||
|
"against_blanket_order": args.against_blanket_order
|
||||||
})
|
})
|
||||||
|
|
||||||
so.delivery_date = add_days(so.transaction_date, 10)
|
so.delivery_date = add_days(so.transaction_date, 10)
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
"target_warehouse",
|
"target_warehouse",
|
||||||
"prevdoc_docname",
|
"prevdoc_docname",
|
||||||
"col_break4",
|
"col_break4",
|
||||||
|
"against_blanket_order",
|
||||||
"blanket_order",
|
"blanket_order",
|
||||||
"blanket_order_rate",
|
"blanket_order_rate",
|
||||||
"planning_section",
|
"planning_section",
|
||||||
@ -574,6 +575,7 @@
|
|||||||
"report_hide": 1
|
"report_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "eval:doc.against_blanket_order",
|
||||||
"fieldname": "blanket_order",
|
"fieldname": "blanket_order",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Blanket Order",
|
"label": "Blanket Order",
|
||||||
@ -581,6 +583,7 @@
|
|||||||
"options": "Blanket Order"
|
"options": "Blanket Order"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "eval:doc.against_blanket_order",
|
||||||
"fieldname": "blanket_order_rate",
|
"fieldname": "blanket_order_rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Blanket Order Rate",
|
"label": "Blanket Order Rate",
|
||||||
@ -741,11 +744,17 @@
|
|||||||
"fieldname": "image_section",
|
"fieldname": "image_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Image"
|
"label": "Image"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "against_blanket_order",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Against Blanket Order"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-10-10 08:46:26.244823",
|
"modified": "2019-11-19 14:19:29.491945",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Order Item",
|
"name": "Sales Order Item",
|
||||||
|
@ -213,7 +213,8 @@ def get_basic_details(args, item, overwrite_warehouse=True):
|
|||||||
project: "",
|
project: "",
|
||||||
qty: "",
|
qty: "",
|
||||||
stock_qty: "",
|
stock_qty: "",
|
||||||
conversion_factor: ""
|
conversion_factor: "",
|
||||||
|
against_blanket_order: 0/1
|
||||||
}
|
}
|
||||||
:param item: `item_code` of Item object
|
:param item: `item_code` of Item object
|
||||||
:return: frappe._dict
|
:return: frappe._dict
|
||||||
@ -302,7 +303,8 @@ def get_basic_details(args, item, overwrite_warehouse=True):
|
|||||||
"weight_per_unit":item.weight_per_unit,
|
"weight_per_unit":item.weight_per_unit,
|
||||||
"weight_uom":item.weight_uom,
|
"weight_uom":item.weight_uom,
|
||||||
"last_purchase_rate": item.last_purchase_rate if args.get("doctype") in ["Purchase Order"] else 0,
|
"last_purchase_rate": item.last_purchase_rate if args.get("doctype") in ["Purchase Order"] else 0,
|
||||||
"transaction_date": args.get("transaction_date")
|
"transaction_date": args.get("transaction_date"),
|
||||||
|
"against_blanket_order": args.get("against_blanket_order")
|
||||||
})
|
})
|
||||||
|
|
||||||
if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
|
if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
|
||||||
@ -996,9 +998,10 @@ def get_serial_no(args, serial_nos=None, sales_order=None):
|
|||||||
|
|
||||||
|
|
||||||
def update_party_blanket_order(args, out):
|
def update_party_blanket_order(args, out):
|
||||||
blanket_order_details = get_blanket_order_details(args)
|
if out["against_blanket_order"]:
|
||||||
if blanket_order_details:
|
blanket_order_details = get_blanket_order_details(args)
|
||||||
out.update(blanket_order_details)
|
if blanket_order_details:
|
||||||
|
out.update(blanket_order_details)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_blanket_order_details(args):
|
def get_blanket_order_details(args):
|
||||||
|
Loading…
Reference in New Issue
Block a user