Compare commits
149 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c0a9f420f | ||
|
|
f3882d2699 | ||
|
|
fe86debf5d | ||
|
|
7d977a243a | ||
|
|
43b508089e | ||
|
|
d5e52bc251 | ||
|
|
13a07c2029 | ||
|
|
9ef4f0dc30 | ||
|
|
aa8abfa5b3 | ||
|
|
ac9172f6df | ||
|
|
44b4e5eef3 | ||
|
|
ff183eedb9 | ||
|
|
184f6d42cc | ||
|
|
afceac620c | ||
|
|
2acbb11923 | ||
|
|
b33695138c | ||
|
|
8872842edf | ||
|
|
7791ed845f | ||
|
|
498cc1b7e1 | ||
|
|
170b0cc83c | ||
|
|
d5c4a5c802 | ||
|
|
a1099d28b8 | ||
|
|
7b9e8368ea | ||
|
|
f32547a414 | ||
|
|
17f6874450 | ||
|
|
55a8797919 | ||
|
|
401be3f49b | ||
|
|
a9ce406c48 | ||
|
|
0b1b8afc3c | ||
|
|
e040510545 | ||
|
|
efd7c3e22b | ||
|
|
8e881cc7b9 | ||
|
|
fc90758932 | ||
|
|
1ca7a27b2f | ||
|
|
3485d2467a | ||
|
|
6f33dfbc56 | ||
|
|
8d62af627a | ||
|
|
1c0ecede06 | ||
|
|
896c731a46 | ||
|
|
05790d1b38 | ||
|
|
5655ce936b | ||
|
|
361739ffb6 | ||
|
|
8fa2a04024 | ||
|
|
89326b366d | ||
|
|
6aaa7d7742 | ||
|
|
05ba967a45 | ||
|
|
d17bbdeb4d | ||
|
|
2f3a68b8d6 | ||
|
|
f69edb3fa3 | ||
|
|
06195de812 | ||
|
|
ad8218e5ac | ||
|
|
9bfef84545 | ||
|
|
81754954cb | ||
|
|
2907881dfb | ||
|
|
0799969063 | ||
|
|
c1b7104126 | ||
|
|
ee25cf7ead | ||
|
|
2f75b7b42e | ||
|
|
1915214518 | ||
|
|
770d04e633 | ||
|
|
022d87969d | ||
|
|
a1d7646e70 | ||
|
|
bd2a1c3553 | ||
|
|
16f3f378f6 | ||
|
|
1885207eca | ||
|
|
e0a636c081 | ||
|
|
ef4e41380b | ||
|
|
77ede941b0 | ||
|
|
7d5298997b | ||
|
|
1397159bc1 | ||
|
|
ec08a50af1 | ||
|
|
4eb196905b | ||
|
|
370e711f48 | ||
|
|
3ae5672e27 | ||
|
|
297fbcd388 | ||
|
|
b7a5502b97 | ||
|
|
7dcab89321 | ||
|
|
a162b3f0cd | ||
|
|
2f163ef360 | ||
|
|
cccc45edc5 | ||
|
|
7b9638c93a | ||
|
|
33fafb7728 | ||
|
|
2704a4a8fc | ||
|
|
55c328348f | ||
|
|
e86eaf543c | ||
|
|
163e3598c7 | ||
|
|
7229b64128 | ||
|
|
9501b38e8b | ||
|
|
09adc10543 | ||
|
|
219148d23d | ||
|
|
9ac2fc932d | ||
|
|
86da020dcd | ||
|
|
6c49fa20b5 | ||
|
|
9e64f07540 | ||
|
|
d5cebd7bb4 | ||
|
|
80de91776d | ||
|
|
cf87027422 | ||
|
|
661db8ba71 | ||
|
|
82be020ae9 | ||
|
|
6f1d012b65 | ||
|
|
112827ee86 | ||
|
|
e2b8ae56e1 | ||
|
|
a65c223428 | ||
|
|
d114aca20d | ||
|
|
5a431127c5 | ||
|
|
69ca382529 | ||
|
|
c9fc091289 | ||
|
|
e7e920b487 | ||
|
|
e8519938e0 | ||
|
|
10a48ea5e9 | ||
|
|
0b7b109c0b | ||
|
|
4f62c4cf2d | ||
|
|
b1391ca635 | ||
|
|
6f3d04caf7 | ||
|
|
c158ccd884 | ||
|
|
b498eb5f9e | ||
|
|
47863a3049 | ||
|
|
e1aee56e85 | ||
|
|
a7b0ffca1c | ||
|
|
74bf022273 | ||
|
|
c1a3e379d8 | ||
|
|
6870e45276 | ||
|
|
7652d5db93 | ||
|
|
1d0b18661e | ||
|
|
29a0b31ca6 | ||
|
|
773d93b628 | ||
|
|
626fcd5199 | ||
|
|
2c452a6881 | ||
|
|
d0a25f72c7 | ||
|
|
424bffc98b | ||
|
|
473ccc410b | ||
|
|
b81a7538b9 | ||
|
|
a3ffe530f0 | ||
|
|
f1d2fd2436 | ||
|
|
4b24683c27 | ||
|
|
2e31d7c7bf | ||
|
|
17adb970f1 | ||
|
|
f21f1af0c9 | ||
|
|
b3bc41131e | ||
|
|
f1ad32059f | ||
|
|
eba0d83541 | ||
|
|
7441a93a10 | ||
|
|
d63bfaa5f2 | ||
|
|
a82358bb98 | ||
|
|
0a6529a643 | ||
|
|
63552166be | ||
|
|
147ecab6b0 | ||
|
|
45f05d2c9b | ||
|
|
5874a76eac |
@@ -2,7 +2,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
__version__ = '7.0.49'
|
||||
__version__ = '7.0.63'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
||||
@@ -171,7 +171,7 @@ class Account(Document):
|
||||
|
||||
old_warehouse = cstr(frappe.db.get_value("Account", self.name, "warehouse"))
|
||||
if old_warehouse != cstr(self.warehouse):
|
||||
if old_warehouse:
|
||||
if old_warehouse and frappe.db.exists("Warehouse", old_warehouse):
|
||||
self.validate_warehouse(old_warehouse)
|
||||
if self.warehouse:
|
||||
self.validate_warehouse(self.warehouse)
|
||||
|
||||
@@ -48,5 +48,24 @@ frappe.treeview_settings["Account"] = {
|
||||
+ " " + dr_or_cr
|
||||
+ '</span>').insertBefore(node.$ul);
|
||||
}
|
||||
}
|
||||
},
|
||||
toolbar: [
|
||||
{
|
||||
condition: function(node) {
|
||||
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1
|
||||
},
|
||||
label: __("View Ledger"),
|
||||
click: function(node, btn) {
|
||||
frappe.route_options = {
|
||||
"account": node.label,
|
||||
"from_date": sys_defaults.year_start_date,
|
||||
"to_date": sys_defaults.year_end_date,
|
||||
"company": frappe.defaults.get_default('company') ? frappe.defaults.get_default('company'): ""
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
},
|
||||
btnClass: "hidden-xs"
|
||||
}
|
||||
],
|
||||
extend_toolbar: true
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"description": "If enabled, the system will post accounting entries for inventory automatically.",
|
||||
"fieldname": "auto_accounting_for_stock",
|
||||
@@ -41,6 +42,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",
|
||||
"fieldname": "acc_frozen_upto",
|
||||
"fieldtype": "Date",
|
||||
@@ -66,6 +68,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts",
|
||||
"fieldname": "frozen_accounts_modifier",
|
||||
"fieldtype": "Link",
|
||||
@@ -92,6 +95,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -116,6 +120,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Role that is allowed to submit transactions that exceed credit limits set.",
|
||||
"fieldname": "credit_controller",
|
||||
"fieldtype": "Link",
|
||||
@@ -142,6 +147,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "check_supplier_invoice_uniqueness",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@@ -162,6 +168,32 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "make_payment_via_journal_entry",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Make Payment via Journal Entry",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
@@ -175,8 +207,8 @@
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-07-14 14:32:06.056888",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2016-10-05 16:13:10.978208",
|
||||
"modified_by": "rohitw1991@gmail.com",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
"owner": "Administrator",
|
||||
@@ -191,6 +223,7 @@
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
@@ -249,14 +250,15 @@
|
||||
"hide_toolbar": 0,
|
||||
"icon": "icon-money",
|
||||
"idx": 1,
|
||||
"in_create": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 1,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2016-05-16 15:23:14.770933",
|
||||
"modified": "2016-10-18 14:22:00.207907",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Cost Center",
|
||||
@@ -368,6 +370,5 @@
|
||||
"read_only_onload": 0,
|
||||
"search_fields": "parent_cost_center, is_group",
|
||||
"sort_order": "ASC",
|
||||
"track_seen": 0,
|
||||
"version": 0
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -511,6 +511,18 @@ frappe.ui.form.on('Payment Entry', {
|
||||
});
|
||||
},
|
||||
|
||||
allocate_payment_amount: function(frm) {
|
||||
if(frm.doc.payment_type == 'Internal Transfer'){
|
||||
return
|
||||
}
|
||||
|
||||
if(frm.doc.references.length == 0){
|
||||
frm.events.get_outstanding_documents(frm);
|
||||
}
|
||||
|
||||
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
|
||||
},
|
||||
|
||||
allocate_party_amount_against_ref_docs: function(frm, paid_amount) {
|
||||
var total_positive_outstanding_including_order = 0;
|
||||
var total_negative_outstanding = 0;
|
||||
@@ -552,22 +564,24 @@ frappe.ui.form.on('Payment Entry', {
|
||||
}
|
||||
|
||||
$.each(frm.doc.references || [], function(i, row) {
|
||||
row.allocated_amount = 0
|
||||
row.allocated_amount = 0 //If allocate payment amount checkbox is unchecked, set zero to allocate amount
|
||||
if(frm.doc.allocate_payment_amount){
|
||||
if(row.outstanding_amount > 0 && allocated_positive_outstanding > 0) {
|
||||
if(row.outstanding_amount >= allocated_positive_outstanding)
|
||||
row.allocated_amount = allocated_positive_outstanding;
|
||||
else row.allocated_amount = row.outstanding_amount;
|
||||
|
||||
if(row.outstanding_amount > 0 && allocated_positive_outstanding > 0) {
|
||||
if(row.outstanding_amount >= allocated_positive_outstanding)
|
||||
row.allocated_amount = allocated_positive_outstanding;
|
||||
else row.allocated_amount = row.outstanding_amount;
|
||||
allocated_positive_outstanding -= flt(row.allocated_amount);
|
||||
} else if (row.outstanding_amount < 0 && allocated_negative_outstanding) {
|
||||
if(Math.abs(row.outstanding_amount) >= allocated_negative_outstanding)
|
||||
row.allocated_amount = -1*allocated_negative_outstanding;
|
||||
else row.allocated_amount = row.outstanding_amount;
|
||||
|
||||
allocated_positive_outstanding -= flt(row.allocated_amount);
|
||||
} else if (row.outstanding_amount < 0 && allocated_negative_outstanding) {
|
||||
if(Math.abs(row.outstanding_amount) >= allocated_negative_outstanding)
|
||||
row.allocated_amount = -1*allocated_negative_outstanding;
|
||||
else row.allocated_amount = row.outstanding_amount;
|
||||
|
||||
allocated_negative_outstanding -= Math.abs(flt(row.allocated_amount));
|
||||
allocated_negative_outstanding -= Math.abs(flt(row.allocated_amount));
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
frm.refresh_fields()
|
||||
frm.events.set_total_allocated_amount(frm);
|
||||
},
|
||||
|
||||
@@ -772,6 +772,34 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"depends_on": "eval:in_list(['Pay', 'Receive'], doc.payment_type)",
|
||||
"fieldname": "allocate_payment_amount",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Allocate Payment Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
@@ -1426,7 +1454,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2016-09-05 11:06:18.183458",
|
||||
"modified": "2016-09-28 18:20:47.625383",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Entry",
|
||||
|
||||
@@ -669,6 +669,7 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
||||
pe.paid_to_account_currency = party_account_currency if payment_type=="Pay" else bank.account_currency
|
||||
pe.paid_amount = paid_amount
|
||||
pe.received_amount = received_amount
|
||||
pe.allocate_payment_amount = 1
|
||||
|
||||
pe.append("references", {
|
||||
"reference_doctype": dt,
|
||||
|
||||
@@ -165,6 +165,13 @@ def get_pricing_rule_for_item(args):
|
||||
})
|
||||
else:
|
||||
item_details.discount_percentage = pricing_rule.discount_percentage
|
||||
elif args.get('pricing_rule'):
|
||||
if frappe.db.get_value('Pricing Rule', args.get('pricing_rule'), 'price_or_discount') == 'Discount Percentage':
|
||||
item_details.discount_percentage = 0.0
|
||||
|
||||
item_details.margin_rate_or_amount = 0.0
|
||||
item_details.margin_type = None
|
||||
|
||||
return item_details
|
||||
|
||||
def get_pricing_rules(args):
|
||||
|
||||
@@ -58,7 +58,7 @@ class PurchaseInvoice(BuyingController):
|
||||
self.check_for_closed_status()
|
||||
self.validate_with_previous_doc()
|
||||
self.validate_uom_is_integer("uom", "qty")
|
||||
self.set_expense_account()
|
||||
self.set_expense_account(for_validate=True)
|
||||
self.set_against_expense_account()
|
||||
self.validate_write_off_account()
|
||||
self.validate_multiple_billing("Purchase Receipt", "pr_detail", "amount", "items")
|
||||
@@ -71,7 +71,7 @@ class PurchaseInvoice(BuyingController):
|
||||
frappe.throw(_("Cash or Bank Account is mandatory for making payment entry"))
|
||||
|
||||
if flt(self.paid_amount) + flt(self.write_off_amount) \
|
||||
- flt(self.base_grand_total) > 1/(10**(self.precision("base_grand_total") + 1)):
|
||||
- flt(self.grand_total) > 1/(10**(self.precision("base_grand_total") + 1)):
|
||||
frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total"""))
|
||||
|
||||
def create_remarks(self):
|
||||
@@ -155,7 +155,7 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
super(PurchaseInvoice, self).validate_warehouse()
|
||||
|
||||
def set_expense_account(self):
|
||||
def set_expense_account(self, for_validate=False):
|
||||
auto_accounting_for_stock = cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
|
||||
|
||||
if auto_accounting_for_stock:
|
||||
@@ -181,7 +181,7 @@ class PurchaseInvoice(BuyingController):
|
||||
else:
|
||||
item.expense_account = stock_not_billed_account
|
||||
|
||||
elif not item.expense_account:
|
||||
elif not item.expense_account and for_validate:
|
||||
throw(_("Expense account is mandatory for item {0}").format(item.item_code or item.item_name))
|
||||
|
||||
def set_against_expense_account(self):
|
||||
@@ -372,7 +372,7 @@ class PurchaseInvoice(BuyingController):
|
||||
if flt(item.base_net_amount):
|
||||
account_currency = get_account_currency(item.expense_account)
|
||||
|
||||
if self.update_stock and self.auto_accounting_for_stock:
|
||||
if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items:
|
||||
val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
|
||||
|
||||
# warehouse account
|
||||
|
||||
@@ -1,31 +1,32 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'fieldname': 'purchase_invoice',
|
||||
'non_standard_fieldnames': {
|
||||
'Delivery Note': 'against_sales_invoice',
|
||||
'Journal Entry': 'reference_name',
|
||||
'Payment Entry': 'reference_name',
|
||||
'Payment Request': 'reference_name',
|
||||
'Landed Cost Voucher': 'receipt_document',
|
||||
'Purchase Invoice': 'return_against'
|
||||
},
|
||||
'internal_links': {
|
||||
'Purchase Order': ['items', 'sales_order'],
|
||||
'Purchase Receipt': ['items', 'delivery_note'],
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Payment'),
|
||||
'items': ['Payment Entry', 'Payment Request', 'Journal Entry']
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'purchase_invoice',
|
||||
'non_standard_fieldnames': {
|
||||
'Delivery Note': 'against_sales_invoice',
|
||||
'Journal Entry': 'reference_name',
|
||||
'Payment Entry': 'reference_name',
|
||||
'Payment Request': 'reference_name',
|
||||
'Landed Cost Voucher': 'receipt_document',
|
||||
'Purchase Invoice': 'return_against'
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Purchase Order', 'Purchase Receipt', 'Asset', 'Landed Cost Voucher']
|
||||
'internal_links': {
|
||||
'Purchase Order': ['items', 'sales_order'],
|
||||
'Purchase Receipt': ['items', 'delivery_note'],
|
||||
},
|
||||
{
|
||||
'label': _('Returns'),
|
||||
'items': ['Purchase Invoice']
|
||||
},
|
||||
]
|
||||
}
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Payment'),
|
||||
'items': ['Payment Entry', 'Payment Request', 'Journal Entry']
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Purchase Order', 'Purchase Receipt', 'Asset', 'Landed Cost Voucher']
|
||||
},
|
||||
{
|
||||
'label': _('Returns'),
|
||||
'items': ['Purchase Invoice']
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -15,6 +15,7 @@ def get_pos_data():
|
||||
doc = frappe.new_doc('Sales Invoice')
|
||||
doc.is_pos = 1;
|
||||
pos_profile = get_pos_profile(doc.company) or {}
|
||||
if not doc.company: doc.company = pos_profile.get('company')
|
||||
doc.update_stock = pos_profile.get('update_stock')
|
||||
|
||||
if pos_profile.get('name'):
|
||||
@@ -66,7 +67,7 @@ def update_pos_profile_data(doc, pos_profile, company_data):
|
||||
doc.naming_series = pos_profile.get('naming_series') or 'SINV-'
|
||||
doc.letter_head = pos_profile.get('letter_head') or company_data.default_letter_head
|
||||
doc.ignore_pricing_rule = pos_profile.get('ignore_pricing_rule') or 0
|
||||
doc.apply_discount_on = pos_profile.get('apply_discount_on') or ''
|
||||
doc.apply_discount_on = pos_profile.get('apply_discount_on') if pos_profile.get('apply_discount') else ''
|
||||
doc.customer_group = pos_profile.get('customer_group') or get_root('Customer Group')
|
||||
doc.territory = pos_profile.get('territory') or get_root('Territory')
|
||||
|
||||
@@ -242,6 +243,6 @@ def save_invoice(e, si_doc, name):
|
||||
|
||||
def make_scheduler_log(e, sales_invoice):
|
||||
scheduler_log = frappe.new_doc('Scheduler Log')
|
||||
scheduler_log.method = "erpnext.accounts.doctype.sales_invoice.pos.make_invoice"
|
||||
scheduler_log.error = e
|
||||
scheduler_log.sales_invoice = sales_invoice
|
||||
scheduler_log.save(ignore_permissions=True)
|
||||
@@ -1,30 +1,31 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'fieldname': 'sales_invoice',
|
||||
'non_standard_fieldnames': {
|
||||
'Delivery Note': 'against_sales_invoice',
|
||||
'Journal Entry': 'reference_name',
|
||||
'Payment Entry': 'reference_name',
|
||||
'Payment Request': 'reference_name',
|
||||
'Sales Invoice': 'return_against'
|
||||
},
|
||||
'internal_links': {
|
||||
'Sales Order': ['items', 'sales_order'],
|
||||
'Delivery Note': ['items', 'delivery_note'],
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Payment'),
|
||||
'items': ['Payment Entry', 'Payment Request', 'Journal Entry']
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'sales_invoice',
|
||||
'non_standard_fieldnames': {
|
||||
'Delivery Note': 'against_sales_invoice',
|
||||
'Journal Entry': 'reference_name',
|
||||
'Payment Entry': 'reference_name',
|
||||
'Payment Request': 'reference_name',
|
||||
'Sales Invoice': 'return_against'
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Timesheet', 'Delivery Note', 'Sales Order']
|
||||
'internal_links': {
|
||||
'Sales Order': ['items', 'sales_order'],
|
||||
'Delivery Note': ['items', 'delivery_note'],
|
||||
},
|
||||
{
|
||||
'label': _('Returns'),
|
||||
'items': ['Sales Invoice']
|
||||
},
|
||||
]
|
||||
}
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Payment'),
|
||||
'items': ['Payment Entry', 'Payment Request', 'Journal Entry']
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Timesheet', 'Delivery Note', 'Sales Order']
|
||||
},
|
||||
{
|
||||
'label': _('Returns'),
|
||||
'items': ['Sales Invoice']
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -168,8 +168,8 @@ def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
|
||||
|
||||
if not gl_entries:
|
||||
gl_entries = frappe.db.sql("""
|
||||
select account, posting_date, party_type, party, cost_center, fiscal_year,
|
||||
voucher_type, voucher_no, against_voucher_type, against_voucher, cost_center
|
||||
select account, posting_date, party_type, party, cost_center, fiscal_year,voucher_type,
|
||||
voucher_no, against_voucher_type, against_voucher, cost_center, company
|
||||
from `tabGL Entry`
|
||||
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no), as_dict=True)
|
||||
|
||||
|
||||
@@ -15,13 +15,11 @@ frappe.pages['pos'].refresh = function(wrapper) {
|
||||
window.onbeforeunload = function () {
|
||||
return wrapper.pos.beforeunload()
|
||||
}
|
||||
wrapper.pos.on_refresh_page()
|
||||
}
|
||||
|
||||
|
||||
erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
init: function(wrapper){
|
||||
this.load = true;
|
||||
this.page = wrapper.page;
|
||||
this.wrapper = $(wrapper).find('.page-content');
|
||||
this.set_indicator();
|
||||
@@ -31,17 +29,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
this.si_docs = this.get_doc_from_localstorage();
|
||||
},
|
||||
|
||||
on_refresh_page: function() {
|
||||
var me = this;
|
||||
if(this.load){
|
||||
this.load = false;
|
||||
}else if(this.connection_status){
|
||||
this.onload();
|
||||
}else{
|
||||
this.create_new();
|
||||
}
|
||||
},
|
||||
|
||||
beforeunload: function(e){
|
||||
if(this.connection_status == false && frappe.get_route()[0] == "pos"){
|
||||
e = e || window.event;
|
||||
@@ -111,6 +98,10 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
})
|
||||
});
|
||||
|
||||
this.page.add_menu_item(__("Sync Offline Invoices"), function(){
|
||||
me.sync_sales_invoice()
|
||||
});
|
||||
|
||||
this.page.add_menu_item(__("POS Profile"), function() {
|
||||
frappe.set_route('List', 'POS Profile');
|
||||
});
|
||||
@@ -355,11 +346,14 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
get_customers: function(key){
|
||||
var me = this;
|
||||
key = key.toLowerCase().trim()
|
||||
var re = new RegExp('%', 'g');
|
||||
var reg = new RegExp(key.replace(re, '\\w*\\s*[a-zA-Z0-9]*'))
|
||||
|
||||
if(key){
|
||||
return $.grep(this.customers, function(data) {
|
||||
if(data.name.toLowerCase().match(key)
|
||||
|| data.customer_name.toLowerCase().match(key)
|
||||
|| (data.customer_group && data.customer_group.toLowerCase().match(key))){
|
||||
if(reg.test(data.name.toLowerCase())
|
||||
|| reg.test(data.customer_name.toLowerCase())
|
||||
|| (data.customer_group && reg.test(data.customer_group.toLowerCase()))){
|
||||
return data
|
||||
}
|
||||
})
|
||||
@@ -383,7 +377,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
|
||||
if (this.items) {
|
||||
$.each(this.items, function(index, obj) {
|
||||
if(index < 16){
|
||||
if(index < 30){
|
||||
$(frappe.render_template("pos_item", {
|
||||
item_code: obj.name,
|
||||
item_price: format_currency(obj.price_list_rate, obj.currency),
|
||||
@@ -427,7 +421,9 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
})
|
||||
}
|
||||
|
||||
key = this.search.$input.val().toLowerCase();
|
||||
key = this.search.$input.val().toLowerCase();
|
||||
var re = new RegExp('%', 'g');
|
||||
var reg = new RegExp(key.replace(re, '[\\w*\\s*[a-zA-Z0-9]*]*'))
|
||||
search_status = true
|
||||
|
||||
if(key){
|
||||
@@ -443,8 +439,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
} else if(item.barcode == me.search.$input.val()) {
|
||||
search_status = false;
|
||||
return item.barcode == me.search.$input.val();
|
||||
} else if((item.item_code.toLowerCase().match(key)) ||
|
||||
(item.item_name.toLowerCase().match(key)) || (item.item_group.toLowerCase().match(key))) {
|
||||
} else if(reg.test(item.item_code.toLowerCase()) || reg.test(item.description.toLowerCase()) ||
|
||||
reg.test(item.item_name.toLowerCase()) || reg.test(item.item_group.toLowerCase()) ){
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,9 +53,10 @@ class ReceivablePayableReport(object):
|
||||
self.filters["range3"] = "90"
|
||||
|
||||
for label in ("0-{range1}".format(range1=self.filters["range1"]),
|
||||
"{range1}-{range2}".format(range1=self.filters["range1"]+1, range2=self.filters["range2"]),
|
||||
"{range2}-{range3}".format(range2=self.filters["range2"]+1, range3=self.filters["range3"]),
|
||||
"{range3}-{above}".format(range3=self.filters["range3"] + 1, above=_("Above"))):
|
||||
"{range1}-{range2}".format(range1=cint(self.filters["range1"])+ 1, range2=self.filters["range2"]),
|
||||
"{range2}-{range3}".format(range2=cint(self.filters["range2"])+ 1, range3=self.filters["range3"]),
|
||||
"{range3}-{above}".format(range3=cint(self.filters["range3"])+ 1, above=_("Above"))):
|
||||
frappe.errprint(label)
|
||||
columns.append({
|
||||
"label": label,
|
||||
"fieldtype": "Currency",
|
||||
@@ -93,9 +94,10 @@ class ReceivablePayableReport(object):
|
||||
data = []
|
||||
for gle in self.get_entries_till(self.filters.report_date, args.get("party_type")):
|
||||
if self.is_receivable_or_payable(gle, dr_or_cr, future_vouchers):
|
||||
outstanding_amount = self.get_outstanding_amount(gle, self.filters.report_date, dr_or_cr)
|
||||
outstanding_amount = flt(self.get_outstanding_amount(gle,
|
||||
self.filters.report_date, dr_or_cr), currency_precision)
|
||||
|
||||
if abs(outstanding_amount) > 0.1/10**currency_precision:
|
||||
|
||||
row = [gle.posting_date, gle.party]
|
||||
|
||||
# customer / supplier name
|
||||
@@ -218,14 +220,16 @@ class ReceivablePayableReport(object):
|
||||
conditions, values = self.prepare_conditions(party_type)
|
||||
|
||||
if self.filters.get(scrub(party_type)):
|
||||
select_fields = "debit_in_account_currency as debit, credit_in_account_currency as credit"
|
||||
select_fields = "sum(debit_in_account_currency) as debit, sum(credit_in_account_currency) as credit"
|
||||
else:
|
||||
select_fields = "debit, credit"
|
||||
select_fields = "sum(debit) as debit, sum(credit) as credit"
|
||||
|
||||
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party,
|
||||
voucher_type, voucher_no, against_voucher_type, against_voucher, account_currency, remarks, {0}
|
||||
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party,
|
||||
voucher_type, voucher_no, against_voucher_type, against_voucher,
|
||||
account_currency, remarks, {0}
|
||||
from `tabGL Entry`
|
||||
where docstatus < 2 and party_type=%s and (party is not null and party != '') {1}
|
||||
group by voucher_type, voucher_no, against_voucher_type, against_voucher, party
|
||||
order by posting_date, party"""
|
||||
.format(select_fields, conditions), values, as_dict=True)
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ def get_cost_center_target_details(filters):
|
||||
return frappe.db.sql("""
|
||||
select b.cost_center, b.monthly_distribution, ba.account, ba.budget_amount
|
||||
from `tabBudget` b, `tabBudget Account` ba
|
||||
where b.name=ba.parent and b.fiscal_year=%s and b.company=%s
|
||||
where b.name=ba.parent and b.docstatus = 1 and b.fiscal_year=%s and b.company=%s
|
||||
""", (filters.fiscal_year, filters.company), as_dict=True)
|
||||
|
||||
#Get target distribution details of accounts of cost center
|
||||
@@ -84,8 +84,9 @@ def get_actual_details(cost_center, fiscal_year):
|
||||
ac_details = frappe.db.sql("""select gl.account, gl.debit, gl.credit,
|
||||
MONTHNAME(gl.posting_date) as month_name, b.cost_center
|
||||
from `tabGL Entry` gl, `tabBudget Account` ba, `tabBudget` b
|
||||
where
|
||||
where
|
||||
b.name = ba.parent
|
||||
and b.docstatus = 1
|
||||
and ba.account=gl.account
|
||||
and gl.fiscal_year=%s
|
||||
and b.cost_center=%s
|
||||
|
||||
@@ -59,7 +59,6 @@ def execute(filters=None):
|
||||
company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
|
||||
|
||||
for cash_flow_account in cash_flow_accounts:
|
||||
|
||||
section_data = []
|
||||
data.append({
|
||||
"account_name": cash_flow_account['section_header'],
|
||||
@@ -82,7 +81,8 @@ def execute(filters=None):
|
||||
account_data = get_account_type_based_data(filters.company,
|
||||
account['account_type'], period_list, filters.accumulated_values)
|
||||
account_data.update({
|
||||
"account_name": account['label'],
|
||||
"account_name": account['label'],
|
||||
"account": account['label'],
|
||||
"indent": 1,
|
||||
"parent_account": cash_flow_account['section_header'],
|
||||
"currency": company_currency
|
||||
@@ -129,7 +129,7 @@ def get_account_type_based_data(company, account_type, period_list, accumulated_
|
||||
def add_total_row_account(out, data, label, period_list, currency):
|
||||
total_row = {
|
||||
"account_name": "'" + _("{0}").format(label) + "'",
|
||||
"account": None,
|
||||
"account": "'" + _("{0}").format(label) + "'",
|
||||
"currency": currency
|
||||
}
|
||||
for row in data:
|
||||
|
||||
@@ -34,7 +34,7 @@ def get_net_profit_loss(income, expense, period_list, company):
|
||||
total = 0
|
||||
net_profit_loss = {
|
||||
"account_name": "'" + _("Net Profit / Loss") + "'",
|
||||
"account": None,
|
||||
"account": "'" + _("Net Profit / Loss") + "'",
|
||||
"warn_if_negative": True,
|
||||
"currency": frappe.db.get_value("Company", company, "default_currency")
|
||||
}
|
||||
|
||||
@@ -302,6 +302,11 @@ def make_purchase_invoice(source_name, target_doc=None):
|
||||
target.amount = flt(obj.amount) - flt(obj.billed_amt)
|
||||
target.base_amount = target.amount * flt(source_parent.conversion_rate)
|
||||
target.qty = target.amount / flt(obj.rate) if (flt(obj.rate) and flt(obj.billed_amt)) else flt(obj.qty)
|
||||
|
||||
item = frappe.db.get_value("Item", target.item_code, ["item_group", "buying_cost_center"], as_dict=1)
|
||||
target.cost_center = frappe.db.get_value("Project", obj.project, "cost_center") \
|
||||
or item.buying_cost_center \
|
||||
or frappe.db.get_value("Item Group", item.item_group, "default_cost_center")
|
||||
|
||||
doc = get_mapped_doc("Purchase Order", source_name, {
|
||||
"Purchase Order": {
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'fieldname': 'purchase_order',
|
||||
'internal_links': {
|
||||
'Material Request': ['items', 'material_request'],
|
||||
'Supplier Quotation': ['items', 'supplier_quotation'],
|
||||
'Project': ['project'],
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Purchase Receipt', 'Purchase Invoice']
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'purchase_order',
|
||||
'internal_links': {
|
||||
'Material Request': ['items', 'material_request'],
|
||||
'Supplier Quotation': ['items', 'supplier_quotation'],
|
||||
'Project': ['project'],
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Material Request', 'Supplier Quotation', 'Project']
|
||||
},
|
||||
{
|
||||
'label': _('Sub-contracting'),
|
||||
'items': ['Stock Entry']
|
||||
},
|
||||
]
|
||||
}
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Purchase Receipt', 'Purchase Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Material Request', 'Supplier Quotation', 'Project']
|
||||
},
|
||||
{
|
||||
'label': _('Sub-contracting'),
|
||||
'items': ['Stock Entry']
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'docstatus': 1,
|
||||
'fieldname': 'request_for_quotation',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Supplier Quotation']
|
||||
},
|
||||
]
|
||||
}
|
||||
def get_data():
|
||||
return {
|
||||
'docstatus': 1,
|
||||
'fieldname': 'request_for_quotation',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Supplier Quotation']
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on transactions against this Supplier. See timeline below for details'),
|
||||
'fieldname': 'supplier',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Procurement'),
|
||||
'items': ['Request for Quotation', 'Supplier Quotation']
|
||||
},
|
||||
{
|
||||
'label': _('Orders'),
|
||||
'items': ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
|
||||
}
|
||||
]
|
||||
}
|
||||
def get_data():
|
||||
return {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on transactions against this Supplier. See timeline below for details'),
|
||||
'fieldname': 'supplier',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Procurement'),
|
||||
'items': ['Request for Quotation', 'Supplier Quotation']
|
||||
},
|
||||
{
|
||||
'label': _('Orders'),
|
||||
'items': ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,20 +1,21 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'fieldname': 'supplier_quotation',
|
||||
'internal_links': {
|
||||
'Material Request': ['items', 'material_request'],
|
||||
'Request for Quotation': ['items', 'request_for_quotation'],
|
||||
'Project': ['items', 'project'],
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Purchase Order']
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'supplier_quotation',
|
||||
'internal_links': {
|
||||
'Material Request': ['items', 'material_request'],
|
||||
'Request for Quotation': ['items', 'request_for_quotation'],
|
||||
'Project': ['items', 'project'],
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Material Request', 'Request for Quotation', 'Project']
|
||||
},
|
||||
]
|
||||
}
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Purchase Order']
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Material Request', 'Request for Quotation', 'Project']
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ class AccountsController(TransactionBase):
|
||||
|
||||
return self.__company_currency
|
||||
|
||||
def onload(self):
|
||||
self.get("__onload").make_payment_via_journal_entry = frappe.db.get_single_value('Accounts Settings', 'make_payment_via_journal_entry')
|
||||
|
||||
def validate(self):
|
||||
if self.get("_action") and self._action != "update_after_submit":
|
||||
self.set_missing_values(for_validate=True)
|
||||
@@ -144,7 +147,7 @@ class AccountsController(TransactionBase):
|
||||
self.conversion_rate = get_exchange_rate(self.currency,
|
||||
self.company_currency)
|
||||
|
||||
def set_missing_item_details(self):
|
||||
def set_missing_item_details(self, for_validate=False):
|
||||
"""set missing item values"""
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
|
||||
@@ -196,7 +199,7 @@ class AccountsController(TransactionBase):
|
||||
(1.0 - (flt(item.discount_percentage) / 100.0)), item.precision("rate"))
|
||||
|
||||
if self.doctype == "Purchase Invoice":
|
||||
self.set_expense_account()
|
||||
self.set_expense_account(for_validate)
|
||||
|
||||
def set_taxes(self):
|
||||
if not self.meta.get_field("taxes"):
|
||||
|
||||
@@ -62,7 +62,7 @@ class BuyingController(StockController):
|
||||
if getattr(self, "supplier", None):
|
||||
self.update_if_missing(get_party_details(self.supplier, party_type="Supplier", ignore_permissions=self.flags.ignore_permissions))
|
||||
|
||||
self.set_missing_item_details()
|
||||
self.set_missing_item_details(for_validate)
|
||||
|
||||
def set_supplier_from_item_default(self):
|
||||
if self.meta.get_field("supplier") and not self.supplier:
|
||||
|
||||
@@ -23,6 +23,7 @@ class SellingController(StockController):
|
||||
self.grand_total)
|
||||
|
||||
def onload(self):
|
||||
super(SellingController, self).onload()
|
||||
if self.doctype in ("Sales Order", "Delivery Note", "Sales Invoice"):
|
||||
for item in self.get("items"):
|
||||
item.update(get_bin_details(item.item_code,
|
||||
|
||||
@@ -301,12 +301,7 @@ class StatusUpdater(Document):
|
||||
ref_doc = frappe.get_doc(ref_dt, ref_dn)
|
||||
|
||||
ref_doc.db_set("per_billed", per_billed)
|
||||
|
||||
if frappe.get_meta(ref_dt).get_field("billing_status"):
|
||||
if per_billed < 0.001: billing_status = "Not Billed"
|
||||
elif per_billed >= 99.99: billing_status = "Fully Billed"
|
||||
else: billing_status = "Partly Billed"
|
||||
ref_doc.db_set('billing_status', billing_status)
|
||||
ref_doc.set_status(update=True)
|
||||
|
||||
def get_tolerance_for(item_code, item_tolerance={}, global_tolerance=None):
|
||||
"""
|
||||
|
||||
@@ -338,7 +338,7 @@ class calculate_taxes_and_totals(object):
|
||||
tax.item_wise_tax_detail = json.dumps(tax.item_wise_tax_detail, separators=(',', ':'))
|
||||
|
||||
def set_discount_amount(self):
|
||||
if not self.doc.discount_amount and self.doc.additional_discount_percentage:
|
||||
if self.doc.additional_discount_percentage:
|
||||
self.doc.discount_amount = flt(flt(self.doc.get(scrub(self.doc.apply_discount_on)))
|
||||
* self.doc.additional_discount_percentage / 100, self.doc.precision("discount_amount"))
|
||||
|
||||
|
||||
@@ -49,10 +49,10 @@ def get_data(filters, conditions):
|
||||
posting_date = 't1.posting_date'
|
||||
|
||||
if conditions["based_on_select"] in ["t1.project,", "t2.project,"]:
|
||||
cond = 'and '+ conditions["based_on_select"][:-1] +' IS Not NULL'
|
||||
cond = ' and '+ conditions["based_on_select"][:-1] +' IS Not NULL'
|
||||
|
||||
if conditions.get('trans') in ['Sales Order', 'Purchase Order']:
|
||||
cond += "and t1.status != 'Closed'"
|
||||
cond += " and t1.status != 'Closed'"
|
||||
|
||||
year_start_date, year_end_date = frappe.db.get_value("Fiscal Year",
|
||||
filters.get('fiscal_year'), ["year_start_date", "year_end_date"])
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'fieldname': 'prevdoc_docname',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Quotation']
|
||||
},
|
||||
]
|
||||
}
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'prevdoc_docname',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Quotation']
|
||||
},
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 82 KiB |
BIN
erpnext/docs/assets/img/buying/material-request-flowchart.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 47 KiB |
@@ -3,6 +3,7 @@ opening-accounts
|
||||
sales-invoice
|
||||
point-of-sale-pos-invoice
|
||||
purchase-invoice
|
||||
payments
|
||||
journal-entry
|
||||
payment-entry
|
||||
multi-currency-accounting
|
||||
|
||||
48
erpnext/docs/user/manual/en/accounts/payments.md
Normal file
@@ -0,0 +1,48 @@
|
||||
Payment can be made against following transactions.
|
||||
|
||||
1. Sales Invoice.
|
||||
2. Purchase Invoice.
|
||||
3. Sales Order (Advance Payment)
|
||||
4. Purchase Order (Advance Payment)
|
||||
|
||||
In ERPNext, there is two options through which user can capture the payment
|
||||
|
||||
1. Payment Entry(Default).
|
||||
2. Journal Entry.
|
||||
|
||||
## Payment Entry
|
||||
|
||||
####Step 1: Make Payment
|
||||
|
||||
On submitting a document against which Payment Entry can be made, you will find Make Payment button.
|
||||
|
||||
<img class="screenshot" alt="Making Payment" src="{{docs_base_url}}/assets/img/accounts/payment-entry-1.png">
|
||||
|
||||
####Step 2: Payment Entry
|
||||
|
||||
<img class="screenshot" alt="Making Payment" src="{{docs_base_url}}/assets/img/accounts/payment-entry-9.png">
|
||||
|
||||
For more details about payment entry [check here.](https://frappe.github.io/erpnext/user/manual/en/accounts/payment-entry)
|
||||
|
||||
## Journal Entry
|
||||
|
||||
To make paymant using journal entry, check below steps
|
||||
|
||||
####Step 1: Activate Payment via Journal Entry
|
||||
|
||||
Goto Accounts Settings > checked Make Payment via Journal Entry
|
||||
|
||||
<img class="screenshot" alt="Making Payment" src="{{docs_base_url}}/assets/img/accounts/account-settings.png">
|
||||
|
||||
####Step 2: Make Payment
|
||||
|
||||
On submitting a document against which Journal Entry can be made, you will find Make Payment button.
|
||||
|
||||
<img class="screenshot" alt="Making Payment" src="{{docs_base_url}}/assets/img/accounts/payment-entry-1.png">
|
||||
|
||||
####Step 3: Journal Entry
|
||||
|
||||
Save and submit the journal entry to record the payament against the invoice
|
||||
<img class="screenshot" alt="Making Payment" src="{{docs_base_url}}/assets/img/accounts/journal-entry.png">
|
||||
|
||||
For more details about journal entry [check here.](https://frappe.github.io/erpnext/user/manual/en/accounts/journal-entry)
|
||||
@@ -18,6 +18,11 @@ choose to start its fiscal year on October 1. That way, they know what their
|
||||
income will be for that year, and can adjust their expenses to maintain their
|
||||
desired profit margins.
|
||||
|
||||
To set the Fiscal Year as default, click on the 'Default' button.
|
||||
|
||||
In case you have multiple companies sharing the same Fiscal Year, you can add
|
||||
it into the grid as shown below.
|
||||
|
||||
<img class="screenshot" alt="Fiscal Year" src="{{docs_base_url}}/assets/img/accounts/fiscal-year.png">
|
||||
|
||||
{next}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
A Material Request is a simple document identifying a requirement of a set of
|
||||
Items (products or services) for a particular reason.
|
||||
|
||||

|
||||

|
||||
|
||||
To generate a Material Request manually go to:
|
||||
|
||||
@@ -25,6 +25,8 @@ A Material Request can be of type:
|
||||
* Material Issue - If the requested material is to be Issued.
|
||||
* Manufacture - If the requested material is to be Produced.
|
||||
|
||||
The User can also raise a [Request For Quotation]({{docs_base_url}}/user/manual/en/buying/request-for-quotation.html) against a Material Request. To create a Request For Quotation the user can click on 'Make'.
|
||||
|
||||
> Info: Material Request is not mandatory. It is ideal if you have centralized
|
||||
buying so that you can collect this information from various departments.
|
||||
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on the attendance of this Employee'),
|
||||
'fieldname': 'employee',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Leave and Attendance'),
|
||||
'items': ['Attendance', 'Leave Application', 'Leave Allocation']
|
||||
},
|
||||
{
|
||||
'label': _('Payroll'),
|
||||
'items': ['Salary Structure', 'Salary Slip', 'Timesheet']
|
||||
},
|
||||
{
|
||||
'label': _('Expense'),
|
||||
'items': ['Expense Claim']
|
||||
},
|
||||
{
|
||||
'label': _('Evaluation'),
|
||||
'items': ['Appraisal']
|
||||
}
|
||||
]
|
||||
}
|
||||
def get_data():
|
||||
return {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on the attendance of this Employee'),
|
||||
'fieldname': 'employee',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Leave and Attendance'),
|
||||
'items': ['Attendance', 'Leave Application', 'Leave Allocation']
|
||||
},
|
||||
{
|
||||
'label': _('Payroll'),
|
||||
'items': ['Salary Structure', 'Salary Slip', 'Timesheet']
|
||||
},
|
||||
{
|
||||
'label': _('Expense'),
|
||||
'items': ['Expense Claim']
|
||||
},
|
||||
{
|
||||
'label': _('Evaluation'),
|
||||
'items': ['Appraisal']
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -129,9 +129,6 @@ cur_frm.cscript.calculate_total = function(doc,cdt,cdn){
|
||||
doc.total_sanctioned_amount = 0;
|
||||
$.each((doc.expenses || []), function(i, d) {
|
||||
doc.total_claimed_amount += d.claim_amount;
|
||||
if(d.sanctioned_amount==null) {
|
||||
d.sanctioned_amount = d.claim_amount;
|
||||
}
|
||||
doc.total_sanctioned_amount += d.sanctioned_amount;
|
||||
});
|
||||
|
||||
@@ -144,17 +141,6 @@ cur_frm.cscript.calculate_total_amount = function(doc,cdt,cdn){
|
||||
cur_frm.cscript.calculate_total(doc,cdt,cdn);
|
||||
}
|
||||
|
||||
cur_frm.cscript.claim_amount = function(doc,cdt,cdn){
|
||||
cur_frm.cscript.calculate_total(doc,cdt,cdn);
|
||||
|
||||
var child = locals[cdt][cdn];
|
||||
refresh_field("sanctioned_amount", child.name, child.parentfield);
|
||||
}
|
||||
|
||||
cur_frm.cscript.sanctioned_amount = function(doc,cdt,cdn){
|
||||
cur_frm.cscript.calculate_total(doc,cdt,cdn);
|
||||
}
|
||||
|
||||
cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
|
||||
if(cint(frappe.boot.notification_settings && frappe.boot.notification_settings.expense_claim)) {
|
||||
cur_frm.email_doc(frappe.boot.notification_settings.expense_claim_message);
|
||||
@@ -172,6 +158,25 @@ erpnext.expense_claim = {
|
||||
}
|
||||
}
|
||||
|
||||
frappe.ui.form.on("Expense Claim Detail", {
|
||||
claim_amount: function(frm, cdt, cdn) {
|
||||
var child = locals[cdt][cdn];
|
||||
var doc = frm.doc;
|
||||
|
||||
if(!child.sanctioned_amount){
|
||||
frappe.model.set_value(cdt, cdn, 'sanctioned_amount', child.claim_amount)
|
||||
}
|
||||
|
||||
cur_frm.cscript.calculate_total(doc,cdt,cdn);
|
||||
},
|
||||
|
||||
sanctioned_amount: function(frm, cdt, cdn) {
|
||||
var doc = frm.doc;
|
||||
cur_frm.cscript.calculate_total(doc,cdt,cdn);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
frappe.ui.form.on("Expense Claim", "employee_name", function(frm) {
|
||||
erpnext.expense_claim.set_title(frm);
|
||||
});
|
||||
|
||||
@@ -97,12 +97,19 @@ class LeaveApplication(Document):
|
||||
.format(formatdate(future_allocation[0].from_date), future_allocation[0].name))
|
||||
|
||||
def validate_salary_processed_days(self):
|
||||
last_processed_pay_slip = frappe.db.sql("""select start_date, end_date from `tabSalary Slip`
|
||||
where docstatus != 2 and employee = %s and ((%s between start_date and end_date) or (%s between start_date and end_date)) order by modified desc limit 1""",(self.employee, self.to_date, self.from_date))
|
||||
if not frappe.db.get_value("Leave Type", self.leave_type, "is_lwp"):
|
||||
return
|
||||
|
||||
last_processed_pay_slip = frappe.db.sql("""
|
||||
select start_date, end_date from `tabSalary Slip`
|
||||
where docstatus != 2 and employee = %s
|
||||
and ((%s between start_date and end_date) or (%s between start_date and end_date))
|
||||
order by modified desc limit 1
|
||||
""",(self.employee, self.to_date, self.from_date))
|
||||
|
||||
if last_processed_pay_slip:
|
||||
frappe.throw(_("Salary already processed for period between {0} and {1}, Leave application period cannot be between this date range.").
|
||||
format(formatdate(last_processed_pay_slip[0][0]), formatdate(last_processed_pay_slip[0][1])))
|
||||
frappe.throw(_("Salary already processed for period between {0} and {1}, Leave application period cannot be between this date range.").format(formatdate(last_processed_pay_slip[0][0]),
|
||||
formatdate(last_processed_pay_slip[0][1])))
|
||||
|
||||
|
||||
def show_block_day_warning(self):
|
||||
|
||||
@@ -14,7 +14,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
for dt in ["Leave Application", "Leave Allocation", "Salary Slip"]:
|
||||
frappe.db.sql("delete from `tab%s`" % dt)
|
||||
|
||||
make_allocation_record(leave_type="_Test Leave Type LWP")
|
||||
# make_allocation_record(leave_type="_Test Leave Type")
|
||||
|
||||
frappe.db.set_value("Company", "_Test Company", "default_holiday_list", "_Test Holiday List")
|
||||
|
||||
|
||||
@@ -55,9 +55,11 @@ class ProductionOrder(Document):
|
||||
if not self.expected_delivery_date:
|
||||
self.expected_delivery_date = so[0].delivery_date
|
||||
|
||||
self.project = so[0].project
|
||||
if so[0].project:
|
||||
self.project = so[0].project
|
||||
|
||||
self.validate_production_order_against_so()
|
||||
if not self.material_request:
|
||||
self.validate_production_order_against_so()
|
||||
else:
|
||||
frappe.throw(_("Sales Order {0} is not valid").format(self.sales_order))
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_per
|
||||
from erpnext.manufacturing.doctype.production_order.production_order \
|
||||
import make_stock_entry, ItemHasVariantError
|
||||
from erpnext.stock.doctype.stock_entry import test_stock_entry
|
||||
from erpnext.stock.doctype.item.test_item import get_total_projected_qty
|
||||
from erpnext.stock.utils import get_bin
|
||||
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||
|
||||
class TestProductionOrder(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@@ -172,6 +174,28 @@ class TestProductionOrder(unittest.TestCase):
|
||||
self.assertEqual(self.bin1_at_start.projected_qty,
|
||||
cint(bin1_on_cancel.projected_qty))
|
||||
|
||||
def test_projected_qty_for_production_and_sales_order(self):
|
||||
before_production_order = get_bin(self.item, self.warehouse)
|
||||
before_production_order.update_reserved_qty_for_production()
|
||||
|
||||
self.pro_order = make_prod_order_test_record(item="_Test FG Item", qty=2,
|
||||
source_warehouse=self.warehouse)
|
||||
|
||||
after_production_order = get_bin(self.item, self.warehouse)
|
||||
|
||||
sales_order = make_sales_order(item = self.item, qty = 2)
|
||||
after_sales_order = get_bin(self.item, self.warehouse)
|
||||
|
||||
self.assertEqual(cint(before_production_order.reserved_qty_for_production) + 2,
|
||||
cint(after_sales_order.reserved_qty_for_production))
|
||||
self.assertEqual(cint(before_production_order.projected_qty),
|
||||
cint(after_sales_order.projected_qty) + 2)
|
||||
|
||||
total_projected_qty = get_total_projected_qty(self.item)
|
||||
|
||||
item_doc = frappe.get_doc('Item', self.item)
|
||||
self.assertEqual(total_projected_qty, item_doc.total_projected_qty)
|
||||
|
||||
def test_reserved_qty_for_production_on_stock_entry(self):
|
||||
test_stock_entry.make_stock_entry(item_code="_Test Item",
|
||||
target= self.warehouse, qty=100, basic_rate=100)
|
||||
|
||||
@@ -282,7 +282,7 @@ execute:frappe.reload_doc('projects', 'doctype', 'project_user')
|
||||
erpnext.patches.v7_0.convert_timelogbatch_to_timesheet
|
||||
erpnext.patches.v7_0.convert_timelog_to_timesheet
|
||||
erpnext.patches.v7_0.move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet
|
||||
erpnext.patches.v7_0.remove_doctypes_and_reports
|
||||
erpnext.patches.v7_0.remove_doctypes_and_reports #2016-10-29
|
||||
erpnext.patches.v7_0.update_maintenance_module_in_doctype
|
||||
erpnext.patches.v7_0.update_prevdoc_values_for_supplier_quotation_item
|
||||
erpnext.patches.v7_0.rename_advance_table_fields
|
||||
@@ -308,6 +308,7 @@ erpnext.patches.v7_0.update_refdoc_in_landed_cost_voucher
|
||||
erpnext.patches.v7_0.set_material_request_type_in_item
|
||||
erpnext.patches.v7_0.rename_examination_to_assessment
|
||||
erpnext.patches.v7_0.set_portal_settings
|
||||
erpnext.patches.v7_0.update_change_amount_account
|
||||
erpnext.patches.v7_0.repost_future_gle_for_purchase_invoice
|
||||
erpnext.patches.v7_0.fix_duplicate_icons
|
||||
erpnext.patches.v7_0.repost_gle_for_pos_sales_return
|
||||
@@ -315,4 +316,8 @@ erpnext.patches.v7_0.update_missing_employee_in_timesheet
|
||||
erpnext.patches.v7_0.update_status_for_timesheet
|
||||
erpnext.patches.v7_0.set_party_name_in_payment_entry
|
||||
execute:frappe.db.sql("update `tabTimesheet` ts, `tabEmployee` emp set ts.employee_name = emp.employee_name where emp.name = ts.employee and ts.employee_name is null and ts.employee is not null")
|
||||
execute:frappe.db.sql("delete from `tabTimesheet Detail` where NOT EXISTS (select name from `tabTimesheet` where name = `tabTimesheet Detail`.parent)")
|
||||
erpnext.patches.v7_0.update_mode_of_payment_type
|
||||
finally:erpnext.patches.v7_0.update_timesheet_communications
|
||||
erpnext.patches.v7_0.update_status_of_zero_amount_sales_order
|
||||
erpnext.patches.v7_0.repost_bin_qty_and_item_projected_qty
|
||||
|
||||
@@ -5,6 +5,22 @@ def execute():
|
||||
frappe.db.sql("""delete from `tabDocType`
|
||||
where name in('Time Log Batch', 'Time Log Batch Detail', 'Time Log')""")
|
||||
|
||||
frappe.db.sql("""delete from `tabDocField` where parent in ('Time Log', 'Time Log Batch')""")
|
||||
frappe.db.sql("""update `tabCustom Script` set dt = 'Timesheet' where dt = 'Time Log'""")
|
||||
|
||||
for data in frappe.db.sql(""" select label, fieldname from `tabCustom Field` where dt = 'Time Log'""", as_dict=1):
|
||||
custom_field = frappe.get_doc({
|
||||
'doctype': 'Custom Field',
|
||||
'label': data.label,
|
||||
'dt': 'Timesheet Detail',
|
||||
'fieldname': data.fieldname,
|
||||
'fieldtype': data.fieldtype or "Data"
|
||||
}).insert(ignore_permissions=True)
|
||||
|
||||
frappe.db.sql("""delete from `tabCustom Field` where dt = 'Time Log'""")
|
||||
frappe.reload_doc('projects', 'doctype', 'timesheet')
|
||||
frappe.reload_doc('projects', 'doctype', 'timesheet_detail')
|
||||
|
||||
report = "Daily Time Log Summary"
|
||||
if frappe.db.exists("Report", report):
|
||||
frappe.delete_doc('Report', report)
|
||||
frappe.delete_doc('Report', report)
|
||||
|
||||
@@ -78,9 +78,12 @@ def execute():
|
||||
|
||||
for doctype, cols in dt_cols_de.items():
|
||||
source_cols = "`" + "`, `".join(standard_cols_de + cols) + "`"
|
||||
|
||||
frappe.db.sql("""INSERT INTO `tabSalary Component` ({0}) SELECT {1} FROM `tab{2}`"""
|
||||
.format(target_cols, source_cols, doctype))
|
||||
try:
|
||||
frappe.db.sql("""INSERT INTO `tabSalary Component` ({0}) SELECT {1} FROM `tab{2}`"""
|
||||
.format(target_cols, source_cols, doctype))
|
||||
except Exception, e:
|
||||
if e.args[0]==1062:
|
||||
pass
|
||||
|
||||
update_customizations()
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from erpnext.stock.doctype.bin.bin import update_item_projected_qty
|
||||
|
||||
def execute():
|
||||
repost_bin_qty()
|
||||
repost_item_projected_qty()
|
||||
|
||||
def repost_bin_qty():
|
||||
for bin in frappe.db.sql(""" select name from `tabBin`
|
||||
where (actual_qty + ordered_qty + indented_qty + planned_qty- reserved_qty - reserved_qty_for_production) != projected_qty """, as_dict=1):
|
||||
bin_doc = frappe.get_doc('Bin', bin.name)
|
||||
bin_doc.set_projected_qty()
|
||||
bin_doc.db_set("projected_qty", bin_doc.projected_qty, update_modified = False)
|
||||
|
||||
def repost_item_projected_qty():
|
||||
for data in frappe.db.sql(""" select
|
||||
`tabBin`.item_code as item_code,
|
||||
sum(`tabBin`.projected_qty) as projected_qty,
|
||||
`tabItem`.total_projected_qty as total_projected_qty
|
||||
from
|
||||
`tabBin`, `tabItem`
|
||||
where `tabBin`.item_code = `tabItem`.name
|
||||
group by `tabBin`.item_code having projected_qty <> total_projected_qty """, as_dict=1):
|
||||
update_item_projected_qty(data.item_code)
|
||||
@@ -10,9 +10,11 @@ def execute():
|
||||
for dt in ("assessment", "announcement", "course", "fees"):
|
||||
frappe.reload_doc("schools", "doctype", dt)
|
||||
|
||||
frappe.reload_doc('website', 'doctype', 'portal_menu_item')
|
||||
|
||||
frappe.get_doc('Portal Settings').sync_menu()
|
||||
|
||||
if 'schools' in frappe.get_installed_apps():
|
||||
domainify.setup_domain('Education')
|
||||
else:
|
||||
domainify.setup_sidebar_items(domainify.get_domain('Manufacturing'))
|
||||
domainify.setup_sidebar_items(domainify.get_domain('Manufacturing'))
|
||||
|
||||
19
erpnext/patches/v7_0/update_change_amount_account.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
|
||||
|
||||
for company in frappe.db.sql("""select company from `tabSales Invoice`
|
||||
where change_amount <> 0 and account_for_change_amount is null group by company""", as_list = 1):
|
||||
cash_account = get_default_bank_cash_account(company[0], 'Cash').get('account')
|
||||
if not cash_account:
|
||||
bank_account = get_default_bank_cash_account(company[0], 'Bank').get('account')
|
||||
cash_account = bank_account
|
||||
|
||||
if cash_account:
|
||||
frappe.db.sql("""update `tabSales Invoice`
|
||||
set account_for_change_amount = %(cash_account)s where change_amount <> 0
|
||||
and company = %(company)s and account_for_change_amount is null""",
|
||||
{'cash_account': cash_account, 'company': company[0]})
|
||||
@@ -0,0 +1,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
for data in frappe.get_all('Sales Order', fields = ["name"], filters = [["docstatus", "=", "1"], ["grand_total", "=", "0"]]):
|
||||
sales_order = frappe.get_doc('Sales Order', data.name)
|
||||
sales_order.set_status(update=True, update_modified = False)
|
||||
27
erpnext/patches/v7_0/update_timesheet_communications.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
if frappe.db.table_exists("Time Log"):
|
||||
timesheet = frappe.db.sql("""SELECT ts.name AS name, tl.name AS timelogname,
|
||||
tl.modified AS modified, tl.modified_by AS modified_by, tl.creation AS creation, tl.owner AS owner
|
||||
FROM
|
||||
`tabTimesheet` ts, `tabTimesheet Detail` tsd, `tabTime Log` tl
|
||||
WHERE
|
||||
tsd.parent = ts.name AND tl.from_time = tsd.from_time AND tl.to_time = tsd.to_time
|
||||
AND tl.hours = tsd.hours AND tl.billing_rate = tsd.billing_rate AND tsd.idx=1
|
||||
AND tl.docstatus < 2""", as_dict=1)
|
||||
|
||||
for data in timesheet:
|
||||
frappe.db.sql(""" update `tabTimesheet` set creation = %(creation)s,
|
||||
owner = %(owner)s, modified = %(modified)s, modified_by = %(modified_by)s
|
||||
where name = %(name)s""", data)
|
||||
|
||||
frappe.db.sql("""
|
||||
update
|
||||
tabCommunication
|
||||
set
|
||||
reference_doctype = "Timesheet", reference_name = %(timesheet)s
|
||||
where
|
||||
reference_doctype = "Time Log" and reference_name = %(timelog)s
|
||||
""", {'timesheet': data.name, 'timelog': data.timelogname}, auto_commit=1)
|
||||
@@ -2,6 +2,14 @@
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Homepage', {
|
||||
setup: function(frm) {
|
||||
frm.fields_dict["products"].grid.get_field("item_code").get_query = function(){
|
||||
return {
|
||||
filters: {'show_in_website': 1}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
|
||||
},
|
||||
@@ -35,5 +43,12 @@ frappe.ui.form.on('Homepage Featured Product', {
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
view: function(frm, cdt, cdn){
|
||||
var child= locals[cdt][cdn]
|
||||
if(child.item_code && frm.doc.products_url){
|
||||
window.location.href = frm.doc.products_url + '/' + encodeURIComponent(child.item_code);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on the Time Sheets created against this project'),
|
||||
'fieldname': 'project',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Project'),
|
||||
'items': ['Task', 'Timesheet', 'Expense Claim', 'Issue']
|
||||
},
|
||||
{
|
||||
'label': _('Material'),
|
||||
'items': ['Material Request', 'BOM', 'Stock Entry']
|
||||
},
|
||||
{
|
||||
'label': _('Sales'),
|
||||
'items': ['Sales Order', 'Delivery Note', 'Sales Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Purchase'),
|
||||
'items': ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
|
||||
},
|
||||
]
|
||||
}
|
||||
def get_data():
|
||||
return {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on the Time Sheets created against this project'),
|
||||
'fieldname': 'project',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Project'),
|
||||
'items': ['Task', 'Timesheet', 'Expense Claim', 'Issue']
|
||||
},
|
||||
{
|
||||
'label': _('Material'),
|
||||
'items': ['Material Request', 'BOM', 'Stock Entry']
|
||||
},
|
||||
{
|
||||
'label': _('Sales'),
|
||||
'items': ['Sales Order', 'Delivery Note', 'Sales Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Purchase'),
|
||||
'items': ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ class Timesheet(Document):
|
||||
|
||||
def validate_dates(self):
|
||||
for data in self.time_logs:
|
||||
if time_diff_in_hours(data.to_time, data.from_time) < 0:
|
||||
if data.from_time and data.to_time and time_diff_in_hours(data.to_time, data.from_time) < 0:
|
||||
frappe.throw(_("To date cannot be before from date"))
|
||||
|
||||
def validate_time_logs(self):
|
||||
|
||||
@@ -15,21 +15,17 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
||||
|
||||
},
|
||||
apply_pricing_rule_on_item: function(item){
|
||||
if(!item.margin_type){
|
||||
item.margin_rate_or_amount = 0.0;
|
||||
}
|
||||
|
||||
if(item.margin_type == "Percentage"){
|
||||
item.total_margin = item.price_list_rate + item.price_list_rate * ( item.margin_rate_or_amount / 100);
|
||||
}else{
|
||||
item.total_margin = item.price_list_rate + item.margin_rate_or_amount;
|
||||
}
|
||||
|
||||
item.rate = flt(item.total_margin , 2);
|
||||
item.rate = flt(item.total_margin , precision("rate", item));
|
||||
|
||||
if(item.discount_percentage){
|
||||
discount_value = flt(item.total_margin) * flt(item.discount_percentage) / 100;
|
||||
item.rate = flt((item.total_margin) - (discount_value), precision('rate'));
|
||||
item.rate = flt((item.total_margin) - (discount_value), precision('rate', item));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -720,7 +720,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
"brand": d.brand,
|
||||
"qty": d.qty,
|
||||
"parenttype": d.parenttype,
|
||||
"parent": d.parent
|
||||
"parent": d.parent,
|
||||
"pricing_rule": d.pricing_rule
|
||||
});
|
||||
|
||||
// if doctype is Quotation Item / Sales Order Iten then add Margin Type and rate in item_list
|
||||
@@ -989,7 +990,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
|
||||
make_payment_entry: function() {
|
||||
return frappe.call({
|
||||
method: "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry",
|
||||
method: cur_frm.cscript.get_method_for_payment(),
|
||||
args: {
|
||||
"dt": cur_frm.doc.doctype,
|
||||
"dn": cur_frm.doc.name
|
||||
@@ -1000,5 +1001,18 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
// cur_frm.refresh_fields()
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
get_method_for_payment: function(){
|
||||
method = "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry"
|
||||
if(cur_frm.doc.__onload && cur_frm.doc.__onload.make_payment_via_journal_entry){
|
||||
if(in_list(['Sales Invoice', 'Purchase Invoice'], cur_frm.doc.doctype)){
|
||||
method = "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_against_invoice"
|
||||
}else {
|
||||
method= "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_against_order"
|
||||
}
|
||||
}
|
||||
|
||||
return method
|
||||
}
|
||||
});
|
||||
@@ -1,15 +1,16 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on the attendance of this Student'),
|
||||
'fieldname': 'student',
|
||||
'transactions': [
|
||||
{
|
||||
'items': ['Student Log', 'Student Group', 'Student Attendance']
|
||||
},
|
||||
{
|
||||
'items': ['Program Enrollment', 'Fees', 'Assessment', 'Guardian']
|
||||
}
|
||||
]
|
||||
}
|
||||
def get_data():
|
||||
return {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on the attendance of this Student'),
|
||||
'fieldname': 'student',
|
||||
'transactions': [
|
||||
{
|
||||
'items': ['Student Log', 'Student Group', 'Student Attendance']
|
||||
},
|
||||
{
|
||||
'items': ['Program Enrollment', 'Fees', 'Assessment', 'Guardian']
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,25 +1,26 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on transactions against this Customer. See timeline below for details'),
|
||||
'fieldname': 'customer',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Pre Sales'),
|
||||
'items': ['Opportunity', 'Quotation']
|
||||
},
|
||||
{
|
||||
'label': _('Orders'),
|
||||
'items': ['Sales Order', 'Delivery Note', 'Sales Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Support'),
|
||||
'items': ['Issue']
|
||||
},
|
||||
{
|
||||
'label': _('Projects'),
|
||||
'items': ['Project']
|
||||
}
|
||||
]
|
||||
}
|
||||
def get_data():
|
||||
return {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on transactions against this Customer. See timeline below for details'),
|
||||
'fieldname': 'customer',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Pre Sales'),
|
||||
'items': ['Opportunity', 'Quotation']
|
||||
},
|
||||
{
|
||||
'label': _('Orders'),
|
||||
'items': ['Sales Order', 'Delivery Note', 'Sales Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Support'),
|
||||
'items': ['Issue']
|
||||
},
|
||||
{
|
||||
'label': _('Projects'),
|
||||
'items': ['Project']
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'fieldname': 'prevdoc_docname',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Sales Order']
|
||||
},
|
||||
]
|
||||
}
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'prevdoc_docname',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Sales Order']
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -442,6 +442,11 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
|
||||
target.amount = flt(source.amount) - flt(source.billed_amt)
|
||||
target.base_amount = target.amount * flt(source_parent.conversion_rate)
|
||||
target.qty = target.amount / flt(source.rate) if (source.rate and source.billed_amt) else source.qty
|
||||
|
||||
item = frappe.db.get_value("Item", target.item_code, ["item_group", "selling_cost_center"], as_dict=1)
|
||||
target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center") \
|
||||
or item.selling_cost_center \
|
||||
or frappe.db.get_value("Item Group", item.item_group, "default_cost_center")
|
||||
|
||||
doclist = get_mapped_doc("Sales Order", source_name, {
|
||||
"Sales Order": {
|
||||
|
||||
@@ -1,33 +1,34 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'fieldname': 'sales_order',
|
||||
'non_standard_fieldnames': {
|
||||
'Delivery Note': 'against_sales_order',
|
||||
},
|
||||
'internal_links': {
|
||||
'Quotation': ['items', 'prevdoc_docname']
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Fulfillment'),
|
||||
'items': ['Sales Invoice', 'Delivery Note']
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'sales_order',
|
||||
'non_standard_fieldnames': {
|
||||
'Delivery Note': 'against_sales_order',
|
||||
},
|
||||
{
|
||||
'label': _('Purchasing'),
|
||||
'items': ['Material Request', 'Purchase Order']
|
||||
'internal_links': {
|
||||
'Quotation': ['items', 'prevdoc_docname']
|
||||
},
|
||||
{
|
||||
'label': _('Projects'),
|
||||
'items': ['Project']
|
||||
},
|
||||
{
|
||||
'label': _('Manufacturing'),
|
||||
'items': ['Production Order']
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Quotation']
|
||||
},
|
||||
]
|
||||
}
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Fulfillment'),
|
||||
'items': ['Sales Invoice', 'Delivery Note']
|
||||
},
|
||||
{
|
||||
'label': _('Purchasing'),
|
||||
'items': ['Material Request', 'Purchase Order']
|
||||
},
|
||||
{
|
||||
'label': _('Projects'),
|
||||
'items': ['Project']
|
||||
},
|
||||
{
|
||||
'label': _('Manufacturing'),
|
||||
'items': ['Production Order']
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Quotation']
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import frappe
|
||||
from frappe.utils import flt, add_days
|
||||
import frappe.permissions
|
||||
import unittest
|
||||
from erpnext.stock.doctype.item.test_item import get_total_projected_qty
|
||||
from erpnext.selling.doctype.sales_order.sales_order \
|
||||
import make_material_request, make_delivery_note, make_sales_invoice, WarehouseRequired
|
||||
|
||||
@@ -124,8 +125,16 @@ class TestSalesOrder(unittest.TestCase):
|
||||
dn = create_dn_against_so(so.name, 15)
|
||||
self.assertEqual(get_reserved_qty(), existing_reserved_qty)
|
||||
|
||||
total_projected_qty = get_total_projected_qty('_Test Item')
|
||||
item_doc_before_cancel = frappe.get_doc('Item', '_Test Item')
|
||||
self.assertEqual(total_projected_qty, item_doc_before_cancel.total_projected_qty)
|
||||
|
||||
dn.cancel()
|
||||
self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)
|
||||
|
||||
total_projected_qty = get_total_projected_qty('_Test Item')
|
||||
item_doc_after_cancel = frappe.get_doc('Item', '_Test Item')
|
||||
self.assertEqual(total_projected_qty, item_doc_after_cancel.total_projected_qty)
|
||||
|
||||
def test_reserved_qty_for_over_delivery_via_sales_invoice(self):
|
||||
# set over-delivery tolerance
|
||||
@@ -141,6 +150,10 @@ class TestSalesOrder(unittest.TestCase):
|
||||
si.get("items")[0].qty = 12
|
||||
si.insert()
|
||||
si.submit()
|
||||
|
||||
total_projected_qty = get_total_projected_qty('_Test Item')
|
||||
item_doc = frappe.get_doc('Item', '_Test Item')
|
||||
self.assertEqual(total_projected_qty, item_doc.total_projected_qty)
|
||||
|
||||
self.assertEqual(get_reserved_qty(), existing_reserved_qty)
|
||||
|
||||
@@ -150,6 +163,9 @@ class TestSalesOrder(unittest.TestCase):
|
||||
|
||||
si.cancel()
|
||||
self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)
|
||||
total_projected_qty = get_total_projected_qty('_Test Item')
|
||||
item_doc = frappe.get_doc('Item', '_Test Item')
|
||||
self.assertEqual(total_projected_qty, item_doc.total_projected_qty)
|
||||
|
||||
so.load_from_db()
|
||||
self.assertEqual(so.get("items")[0].delivered_qty, 0)
|
||||
@@ -178,6 +194,10 @@ class TestSalesOrder(unittest.TestCase):
|
||||
self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1)
|
||||
self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2)
|
||||
|
||||
total_projected_qty = get_total_projected_qty('_Test Item')
|
||||
item_doc = frappe.get_doc('Item', '_Test Item')
|
||||
self.assertEqual(total_projected_qty, item_doc.total_projected_qty)
|
||||
|
||||
# unclose so
|
||||
so.load_from_db()
|
||||
so.update_status('Draft')
|
||||
@@ -211,6 +231,10 @@ class TestSalesOrder(unittest.TestCase):
|
||||
|
||||
dn = create_dn_against_so(so.name, 15)
|
||||
|
||||
total_projected_qty = get_total_projected_qty('_Test Item')
|
||||
item_doc = frappe.get_doc('Item', '_Test Item')
|
||||
self.assertEqual(total_projected_qty, item_doc.total_projected_qty)
|
||||
|
||||
self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1)
|
||||
self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"),
|
||||
existing_reserved_qty_item2)
|
||||
@@ -427,6 +451,13 @@ class TestSalesOrder(unittest.TestCase):
|
||||
|
||||
self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty_for_dn_item)
|
||||
|
||||
def test_total_projected_qty_against_sales_order(self):
|
||||
so = make_sales_order(item = '_Test Item')
|
||||
total_projected_qty = get_total_projected_qty('_Test Item')
|
||||
|
||||
item_doc = frappe.get_doc('Item', '_Test Item')
|
||||
self.assertEqual(total_projected_qty, item_doc.total_projected_qty)
|
||||
|
||||
def test_reserved_qty_for_closing_so(self):
|
||||
bin = frappe.get_all("Bin", filters={"item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC"},
|
||||
fields=["reserved_qty"])
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"add_total_row": 1,
|
||||
"apply_user_permissions": 1,
|
||||
"creation": "2013-05-03 11:31:05",
|
||||
"disabled": 0,
|
||||
@@ -7,7 +7,7 @@
|
||||
"doctype": "Report",
|
||||
"idx": 1,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2016-01-28 04:22:49.476068",
|
||||
"modified": "2016-10-05 12:26:15.736596",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Person-wise Transaction Summary",
|
||||
|
||||
@@ -39,7 +39,7 @@ def get_columns(filters):
|
||||
_("Customer") + ":Link/Customer:140", _("Territory") + ":Link/Territory:100", _("Posting Date") + ":Date:100",
|
||||
_("Item Code") + ":Link/Item:120", _("Item Group") + ":Link/Item Group:120",
|
||||
_("Brand") + ":Link/Brand:120", _("Qty") + ":Float:100", _("Amount") + ":Currency:120",
|
||||
_("Sales Person") + ":Link/Sales Person:140", _("Contribution %") + ":Float:110",
|
||||
_("Sales Person") + ":Link/Sales Person:140", _("Contribution %") + "::110",
|
||||
_("Contribution Amount") + ":Currency:140"]
|
||||
|
||||
def get_entries(filters):
|
||||
|
||||
@@ -18,7 +18,6 @@ def delete_company_transactions(company_name):
|
||||
frappe.PermissionError)
|
||||
|
||||
delete_bins(company_name)
|
||||
delete_time_sheets(company_name)
|
||||
delete_lead_addresses(company_name)
|
||||
|
||||
for doctype in frappe.db.sql_list("""select parent from
|
||||
@@ -70,14 +69,6 @@ def delete_bins(company_name):
|
||||
frappe.db.sql("""delete from tabBin where warehouse in
|
||||
(select name from tabWarehouse where company=%s)""", company_name)
|
||||
|
||||
def delete_time_sheets(company_name):
|
||||
# Delete Time Logs as it is linked to Production Order / Project / Task, which are linked to company
|
||||
frappe.db.sql("""
|
||||
delete from `tabTimesheet`
|
||||
where
|
||||
company=%(company)s
|
||||
""", {"company": company_name})
|
||||
|
||||
def delete_lead_addresses(company_name):
|
||||
"""Delete addresses to which leads are linked"""
|
||||
for lead in frappe.get_all("Lead", filters={"company": company_name}):
|
||||
|
||||
@@ -9,7 +9,9 @@ frappe.ui.form.on("Notification Control", {
|
||||
frm.set_value("custom_message", frm.doc[frm.events.get_fieldname(frm)]);
|
||||
},
|
||||
set_message: function(frm) {
|
||||
frm.set_value(frm.events.get_fieldname(frm), frm.doc.custom_message);
|
||||
if(frm.doc.select_transaction && frm.doc.select_transaction !== "") {
|
||||
frm.set_value(frm.events.get_fieldname(frm), frm.doc.custom_message);
|
||||
}
|
||||
frm.save();
|
||||
},
|
||||
get_fieldname: function(frm) {
|
||||
|
||||
@@ -12,9 +12,3 @@ cur_frm.cscript.refresh = function(doc,dt,dn){
|
||||
erpnext.utils.render_address_and_contact(cur_frm);
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['targets'].grid.get_field("item_group").get_query = function(doc, dt, dn) {
|
||||
return{
|
||||
filters:{ 'is_group': 0 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,18 +14,18 @@ class Bin(Document):
|
||||
self.stock_uom = frappe.db.get_value('Item', self.item_code, 'stock_uom')
|
||||
|
||||
self.validate_mandatory()
|
||||
|
||||
self.projected_qty = flt(self.actual_qty) + flt(self.ordered_qty) + \
|
||||
flt(self.indented_qty) + flt(self.planned_qty) - flt(self.reserved_qty)
|
||||
|
||||
self.set_projected_qty()
|
||||
self.block_transactions_against_group_warehouse()
|
||||
|
||||
def on_update(self):
|
||||
update_item_projected_qty(self.item_code)
|
||||
|
||||
def validate_mandatory(self):
|
||||
qf = ['actual_qty', 'reserved_qty', 'ordered_qty', 'indented_qty']
|
||||
for f in qf:
|
||||
if (not getattr(self, f, None)) or (not self.get(f)):
|
||||
self.set(f, 0.0)
|
||||
|
||||
|
||||
def block_transactions_against_group_warehouse(self):
|
||||
from erpnext.stock.utils import is_group_warehouse
|
||||
is_group_warehouse(self.warehouse)
|
||||
@@ -72,9 +72,7 @@ class Bin(Document):
|
||||
self.indented_qty = flt(self.indented_qty) + flt(args.get("indented_qty"))
|
||||
self.planned_qty = flt(self.planned_qty) + flt(args.get("planned_qty"))
|
||||
|
||||
self.set_projected_qty()
|
||||
self.save()
|
||||
update_item_projected_qty(self.item_code)
|
||||
|
||||
def set_projected_qty(self):
|
||||
self.projected_qty = (flt(self.actual_qty) + flt(self.ordered_qty)
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'fieldname': 'delivery_note_no',
|
||||
'non_standard_fieldnames': {
|
||||
'Sales Invoice': 'delivery_note',
|
||||
'Packing Slip': 'delivery_note',
|
||||
},
|
||||
'internal_links': {
|
||||
'Sales Order': ['items', 'against_sales_order'],
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Sales Invoice', 'Packing Slip']
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'delivery_note_no',
|
||||
'non_standard_fieldnames': {
|
||||
'Sales Invoice': 'delivery_note',
|
||||
'Packing Slip': 'delivery_note',
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Sales Order', 'Quality Inspection']
|
||||
'internal_links': {
|
||||
'Sales Order': ['items', 'against_sales_order'],
|
||||
},
|
||||
{
|
||||
'label': _('Returns'),
|
||||
'items': ['Stock Entry']
|
||||
},
|
||||
]
|
||||
}
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Sales Invoice', 'Packing Slip']
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Sales Order', 'Quality Inspection']
|
||||
},
|
||||
{
|
||||
'label': _('Returns'),
|
||||
'items': ['Stock Entry']
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -567,7 +567,7 @@ class Item(WebsiteGenerator):
|
||||
existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
|
||||
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
|
||||
|
||||
for warehouse in frappe.db.sql("select name from `tabWarehouse`"):
|
||||
for warehouse in frappe.db.sql("select name from `tabWarehouse` where is_group = 0"):
|
||||
repost_stock(new_name, warehouse[0])
|
||||
|
||||
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock)
|
||||
|
||||
@@ -1,45 +1,46 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on stock movement. See {0} for details')\
|
||||
.format('<a href="#query-report/Stock Ledger">' + _('Stock Ledger') + '</a>'),
|
||||
'fieldname': 'item_code',
|
||||
'non_standard_fieldnames': {
|
||||
'Production Order': 'production_item',
|
||||
'Product Bundle': 'new_item_code',
|
||||
'BOM': 'item',
|
||||
'Batch': 'item'
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Groups'),
|
||||
'items': ['BOM', 'Product Bundle']
|
||||
def get_data():
|
||||
return {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on stock movement. See {0} for details')\
|
||||
.format('<a href="#query-report/Stock Ledger">' + _('Stock Ledger') + '</a>'),
|
||||
'fieldname': 'item_code',
|
||||
'non_standard_fieldnames': {
|
||||
'Production Order': 'production_item',
|
||||
'Product Bundle': 'new_item_code',
|
||||
'BOM': 'item',
|
||||
'Batch': 'item'
|
||||
},
|
||||
{
|
||||
'label': _('Pricing'),
|
||||
'items': ['Item Price', 'Pricing Rule']
|
||||
},
|
||||
{
|
||||
'label': _('Sell'),
|
||||
'items': ['Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Buy'),
|
||||
'items': ['Material Request', 'Supplier Quotation', 'Request for Quotation',
|
||||
'Purchase Order', 'Purchase Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Traceability'),
|
||||
'items': ['Serial No', 'Batch']
|
||||
},
|
||||
{
|
||||
'label': _('Move'),
|
||||
'items': ['Stock Entry']
|
||||
},
|
||||
{
|
||||
'label': _('Manufacture'),
|
||||
'items': ['Production Order']
|
||||
}
|
||||
]
|
||||
}
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Groups'),
|
||||
'items': ['BOM', 'Product Bundle']
|
||||
},
|
||||
{
|
||||
'label': _('Pricing'),
|
||||
'items': ['Item Price', 'Pricing Rule']
|
||||
},
|
||||
{
|
||||
'label': _('Sell'),
|
||||
'items': ['Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Buy'),
|
||||
'items': ['Material Request', 'Supplier Quotation', 'Request for Quotation',
|
||||
'Purchase Order', 'Purchase Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Traceability'),
|
||||
'items': ['Serial No', 'Batch']
|
||||
},
|
||||
{
|
||||
'label': _('Move'),
|
||||
'items': ['Stock Entry']
|
||||
},
|
||||
{
|
||||
'label': _('Manufacture'),
|
||||
'items': ['Production Order']
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -177,4 +177,10 @@ def make_item_variant():
|
||||
variant.item_name = "_Test Variant Item-S"
|
||||
variant.save()
|
||||
|
||||
def get_total_projected_qty(item):
|
||||
total_qty = frappe.db.sql(""" select sum(projected_qty) as projected_qty from tabBin
|
||||
where item_code = %(item)s""", {'item': item}, as_dict=1)
|
||||
|
||||
return total_qty[0].projected_qty if total_qty else 0.0
|
||||
|
||||
test_records = frappe.get_test_records('Item')
|
||||
|
||||
@@ -75,7 +75,7 @@ class MaterialRequest(BuyingController):
|
||||
pc_obj = frappe.get_doc('Purchase Common')
|
||||
pc_obj.validate_for_items(self)
|
||||
|
||||
self.set_title()
|
||||
# self.set_title()
|
||||
|
||||
|
||||
# self.validate_qty_against_so()
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'fieldname': 'material_request',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Request for Quotation', 'Supplier Quotation', 'Purchase Order']
|
||||
},
|
||||
]
|
||||
}
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'material_request',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Request for Quotation', 'Supplier Quotation', 'Purchase Order']
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -1,28 +1,29 @@
|
||||
from frappe import _
|
||||
|
||||
data = {
|
||||
'fieldname': 'purchase_receipt_no',
|
||||
'non_standard_fieldnames': {
|
||||
'Purchase Invoice': 'purchase_receipt',
|
||||
'Landed Cost Voucher': 'receipt_document'
|
||||
},
|
||||
'internal_links': {
|
||||
'Purchase Order': ['items', 'purchase_order'],
|
||||
'Project': ['items', 'project'],
|
||||
'Quality Inspection': ['items', 'qa_no'],
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Purchase Invoice', 'Landed Cost Voucher']
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'purchase_receipt_no',
|
||||
'non_standard_fieldnames': {
|
||||
'Purchase Invoice': 'purchase_receipt',
|
||||
'Landed Cost Voucher': 'receipt_document'
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Purchase Order', 'Quality Inspection', 'Project']
|
||||
'internal_links': {
|
||||
'Purchase Order': ['items', 'purchase_order'],
|
||||
'Project': ['items', 'project'],
|
||||
'Quality Inspection': ['items', 'qa_no'],
|
||||
},
|
||||
{
|
||||
'label': _('Returns'),
|
||||
'items': ['Stock Entry']
|
||||
},
|
||||
]
|
||||
}
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Purchase Invoice', 'Landed Cost Voucher']
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Purchase Order', 'Quality Inspection', 'Project']
|
||||
},
|
||||
{
|
||||
'label': _('Returns'),
|
||||
'items': ['Stock Entry']
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -356,6 +356,7 @@ cur_frm.fields_dict['production_order'].get_query = function(doc) {
|
||||
}
|
||||
|
||||
cur_frm.cscript.purpose = function(doc, cdt, cdn) {
|
||||
cur_frm.fields_dict.items.grid.refresh();
|
||||
cur_frm.cscript.toggle_related_fields(doc);
|
||||
}
|
||||
|
||||
|
||||
@@ -328,10 +328,11 @@ def get_pos_profile_item_details(company, args, pos_profile=None):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_pos_profile(company):
|
||||
condition = "and company = '%s'"%(company) if company else ''
|
||||
pos_profile = frappe.db.sql("""select * from `tabPOS Profile` where user = %s
|
||||
and company = %s""", (frappe.session['user'], company), as_dict=1)
|
||||
{cond}""".format(cond=condition), (frappe.session['user']), as_dict=1)
|
||||
|
||||
if not pos_profile:
|
||||
if not pos_profile and company:
|
||||
pos_profile = frappe.db.sql("""select * from `tabPOS Profile`
|
||||
where ifnull(user,'') = '' and company = %s""", company, as_dict=1)
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@ def reset_serial_no_status_and_warehouse(serial_nos=None):
|
||||
pass
|
||||
|
||||
def repost_all_stock_vouchers():
|
||||
warehouses_with_account = frappe.db.sql_list("""select master_name from tabAccount
|
||||
warehouses_with_account = frappe.db.sql_list("""select warehouse from tabAccount
|
||||
where ifnull(account_type, '') = 'Stock' and (warehouse is not null and warehouse != '')
|
||||
and is_group=0""")
|
||||
|
||||
@@ -244,7 +244,7 @@ def repost_all_stock_vouchers():
|
||||
i = 0
|
||||
for voucher_type, voucher_no in vouchers:
|
||||
i+=1
|
||||
print i, "/", len(vouchers)
|
||||
print i, "/", len(vouchers), voucher_type, voucher_no
|
||||
try:
|
||||
for dt in ["Stock Ledger Entry", "GL Entry"]:
|
||||
frappe.db.sql("""delete from `tab%s` where voucher_type=%s and voucher_no=%s"""%
|
||||
|
||||
@@ -37,7 +37,7 @@ $.extend(cur_frm.cscript, new erpnext.support.WarrantyClaim({frm: cur_frm}));
|
||||
|
||||
cur_frm.cscript.onload = function(doc,cdt,cdn){
|
||||
if(!doc.status)
|
||||
set_multiple(dt,dn,{status:'Open'});
|
||||
set_multiple(cdt,cdn,{status:'Open'});
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['customer_address'].get_query = function(doc, cdt, cdn) {
|
||||
|
||||
@@ -19,7 +19,7 @@ class WarrantyClaim(TransactionBase):
|
||||
if session['user'] != 'Guest' and not self.customer:
|
||||
frappe.throw(_("Customer is required"))
|
||||
|
||||
if self.status=="Closed" and \
|
||||
if self.status=="Closed" and not self.resolution_date and \
|
||||
frappe.db.get_value("Warranty Claim", self.name, "status")!="Closed":
|
||||
self.resolution_date = now_datetime()
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<p>{{_("Please click on the following link to set your new password")}}:</p>
|
||||
<p><a href="{{ update_password_link }}">{{ update_password_link }}</a></p>
|
||||
{% else %}
|
||||
<p>{{_("Request for quotation can be access by clicking following link")}}:</p>
|
||||
<p>{{_("The request for quotation can be accessed by clicking on the following link")}}:</p>
|
||||
<p><a href="{{ rfq_link }}">Submit your Quotation</a></p>
|
||||
{% endif %}
|
||||
<p>{{_("Thank you")}},<br>
|
||||
{{ user_fullname }}</p>
|
||||
{{ user_fullname }}</p>
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
{%- set compact_fields = doc.flags.compact_item_fields -%}
|
||||
|
||||
{% if doc.in_format_data("image") and doc.get("image") and not doc.is_print_hide("image")-%}
|
||||
<div class="pull-left" style="width: 20%; margin-right: 10px;">
|
||||
<div class="square-image" style="background-image: url('{{ doc.image }}')">
|
||||
</div>
|
||||
<div class="pull-left" style="max-width: 40%; margin-right: 10px;">
|
||||
<img class="print-item-image" src="{{ doc.image }}" alt="">
|
||||
</div>
|
||||
{%- endif %}
|
||||
|
||||
|
||||
@@ -407,7 +407,7 @@ DocType: Employee,Single,Unique
|
||||
DocType: Account,Cost of Goods Sold,Coût des marchandises vendues
|
||||
DocType: Purchase Invoice,Yearly,Annuel
|
||||
apps/erpnext/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +229,Please enter Cost Center,S'il vous plaît entrer Centre de coûts
|
||||
DocType: Journal Entry Account,Sales Order,Bon de commande
|
||||
DocType: Journal Entry Account,Sales Order,commande client
|
||||
apps/erpnext/erpnext/accounts/report/gross_profit/gross_profit.py +67,Avg. Selling Rate,Moy. Taux de vente
|
||||
DocType: Examination,Examiner Name,Nom de l'examinateur
|
||||
apps/erpnext/erpnext/utilities/transaction_base.py +149,Quantity cannot be a fraction in row {0},La quantité ne peut pas être une fraction à la ligne {0}
|
||||
@@ -991,7 +991,7 @@ apps/erpnext/erpnext/patches/v4_0/create_price_list_if_missing.py +18,Standard B
|
||||
DocType: GL Entry,Against,Contre
|
||||
DocType: Item,Default Selling Cost Center,Coût des marchandises vendues
|
||||
DocType: Sales Partner,Implementation Partner,Partenaire de mise en œuvre
|
||||
apps/erpnext/erpnext/controllers/selling_controller.py +231,Sales Order {0} is {1},Bon de commande {0} est {1}
|
||||
apps/erpnext/erpnext/controllers/selling_controller.py +231,Sales Order {0} is {1},commande client {0} est {1}
|
||||
DocType: Opportunity,Contact Info,Information de contact
|
||||
apps/erpnext/erpnext/config/stock.py +299,Making Stock Entries,Faire des entrées stock
|
||||
DocType: Packing Slip,Net Weight UOM,Unité de mesure Poids Net
|
||||
@@ -1137,7 +1137,7 @@ DocType: Item,Lead Time in days,Délai en jours
|
||||
,Accounts Payable Summary,Le résumé des comptes à payer
|
||||
apps/erpnext/erpnext/accounts/doctype/gl_entry/gl_entry.py +196,Not authorized to edit frozen Account {0},N'êtes pas autorisé à modifier le compte gelé {0}
|
||||
DocType: Journal Entry,Get Outstanding Invoices,Obtenez les factures impayées
|
||||
apps/erpnext/erpnext/manufacturing/doctype/production_order/production_order.py +62,Sales Order {0} is not valid,Bon de commande {0} invalide
|
||||
apps/erpnext/erpnext/manufacturing/doctype/production_order/production_order.py +62,Sales Order {0} is not valid,commande client {0} invalide
|
||||
apps/erpnext/erpnext/setup/doctype/company/company.py +182,"Sorry, companies cannot be merged","Désolé , les entreprises ne peuvent pas être fusionnés"
|
||||
apps/erpnext/erpnext/stock/doctype/material_request/material_request.py +139,"The total Issue / Transfer quantity {0} in Material Request {1} \
|
||||
cannot be greater than requested quantity {2} for Item {3}",La quantité Problème / transfert total {0} dans Material Request {1} \ ne peut pas être supérieure à la quantité demandée {2} pour le poste {3}
|
||||
@@ -1590,7 +1590,7 @@ DocType: Authorization Control,Authorization Control,Contrôle d'autorisatio
|
||||
apps/erpnext/erpnext/controllers/buying_controller.py +300,Row #{0}: Rejected Warehouse is mandatory against rejected Item {1},Row # {0}: Entrepôt Rejeté est obligatoire contre Item rejeté {1}
|
||||
apps/erpnext/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +678,Payment,Paiement
|
||||
DocType: Production Order Operation,Actual Time and Cost,Temps réel et coût
|
||||
apps/erpnext/erpnext/stock/doctype/material_request/material_request.py +54,Material Request of maximum {0} can be made for Item {1} against Sales Order {2},Demande de Matériel d'un maximum de {0} peut être faite pour l'article {1} par rapport au bon de commande {2}
|
||||
apps/erpnext/erpnext/stock/doctype/material_request/material_request.py +54,Material Request of maximum {0} can be made for Item {1} against Sales Order {2},Demande de Matériel d'un maximum de {0} peut être faite pour l'article {1} par rapport au commande client {2}
|
||||
DocType: Employee,Salutation,Titre
|
||||
DocType: Pricing Rule,Brand,Marque
|
||||
DocType: Course,Course Abbreviation,Abréviation de cours
|
||||
@@ -1863,7 +1863,7 @@ apps/erpnext/erpnext/public/js/setup_wizard.js +52,"e.g. ""Build tools for build
|
||||
DocType: Quality Inspection,In Process,En cours
|
||||
DocType: Authorization Rule,Itemwise Discount,Remise (par Article)
|
||||
apps/erpnext/erpnext/config/accounts.py +63,Tree of financial accounts.,Arbre des comptes financiers.
|
||||
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +334,{0} against Sales Order {1},{0} contre le bon de commande de vente {1}
|
||||
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +334,{0} against Sales Order {1},{0} contre le commande client de vente {1}
|
||||
DocType: Account,Fixed Asset,Actifs immobilisés
|
||||
apps/erpnext/erpnext/config/stock.py +304,Serialized Inventory,Inventaire sérialisé
|
||||
DocType: Activity Type,Default Billing Rate,Prix facturation par défaut
|
||||
@@ -2153,7 +2153,7 @@ DocType: Homepage,Homepage,Page d'accueil
|
||||
DocType: Purchase Receipt Item,Recd Quantity,Quantité reçue
|
||||
apps/erpnext/erpnext/schools/doctype/program_enrollment/program_enrollment.py +54,Fee Records Created - {0},Records Fee Créé - {0}
|
||||
DocType: Asset Category Account,Asset Category Account,Catégorie d'actif compte
|
||||
apps/erpnext/erpnext/manufacturing/doctype/production_order/production_order.py +103,Cannot produce more Item {0} than Sales Order quantity {1},Ne peut pas produire plus d'article {0} que de la qté du bon de commande {1}
|
||||
apps/erpnext/erpnext/manufacturing/doctype/production_order/production_order.py +103,Cannot produce more Item {0} than Sales Order quantity {1},Ne peut pas produire plus d'article {0} que de la qté du commande client {1}
|
||||
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +504,Stock Entry {0} is not submitted,Entrée stock {0} est pas soumis
|
||||
DocType: Payment Reconciliation,Bank / Cash Account,Banque et liquidités
|
||||
DocType: Tax Rule,Billing City,Ville de facturation
|
||||
@@ -2499,7 +2499,7 @@ apps/erpnext/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
|
||||
DocType: Program Enrollment Tool,Get Students,Obtenez étudiants
|
||||
DocType: Serial No,Under Warranty,Sous garantie
|
||||
apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +447,[Error],[Erreur]
|
||||
DocType: Sales Order,In Words will be visible once you save the Sales Order.,En Toutes Lettres. Sera visible une fois que vous enregistrerez le bon de commande.
|
||||
DocType: Sales Order,In Words will be visible once you save the Sales Order.,En Toutes Lettres. Sera visible une fois que vous enregistrerez le commande client.
|
||||
,Employee Birthday,Anniversaire de l'employé
|
||||
apps/erpnext/erpnext/controllers/status_updater.py +175,Limit Crossed,Limite Crossed
|
||||
apps/erpnext/erpnext/setup/setup_wizard/industry_type.py +55,Venture Capital,Capital Risque
|
||||
@@ -2734,7 +2734,7 @@ apps/erpnext/erpnext/setup/doctype/item_group/item_group.py +59,"An item exists
|
||||
apps/erpnext/erpnext/accounts/page/pos/pos.js +1171,Please select customer,S'il vous plaît sélectionner client
|
||||
DocType: C-Form,I,je
|
||||
DocType: Company,Asset Depreciation Cost Center,Asset Centre Amortissements
|
||||
DocType: Sales Order Item,Sales Order Date,Date du bon de Commande
|
||||
DocType: Sales Order Item,Sales Order Date,Date du commande client
|
||||
DocType: Sales Invoice Item,Delivered Qty,Qté livrée
|
||||
apps/erpnext/erpnext/stock/doctype/warehouse/warehouse.py +86,Warehouse {0}: Company is mandatory,Entrepôt {0}: Société est obligatoire
|
||||
,Payment Period Based On Invoice Date,Période de paiement basé sur Date de la facture
|
||||
@@ -3421,7 +3421,7 @@ DocType: Task,Total Expense Claim (via Expense Claim),Frais totaux (via Note de
|
||||
apps/erpnext/erpnext/accounts/report/sales_register/sales_register.py +69,Customer Id,Client Id
|
||||
apps/erpnext/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js +176,Mark Absent,Marquer absent
|
||||
DocType: Journal Entry Account,Exchange Rate,Taux de change
|
||||
apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +461,Sales Order {0} is not submitted,Bon de commande {0} n'a pas été transmis
|
||||
apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +461,Sales Order {0} is not submitted,commande client {0} n'a pas été transmis
|
||||
DocType: Homepage,Tag Line,Tag ligne
|
||||
apps/erpnext/erpnext/buying/doctype/purchase_order/purchase_order.js +804,Add items from,Ajouter des articles de
|
||||
apps/erpnext/erpnext/stock/doctype/warehouse/warehouse.py +97,Warehouse {0}: Parent account {1} does not bolong to the company {2},Entrepôt {0}: le Compte Parent {1} n'appartient pas à la société {2}
|
||||
|
||||
|