Compare commits

..

105 Commits

Author SHA1 Message Date
Nabin Hait
b8a7926464 Merge branch 'hotfix' 2016-11-23 14:53:42 +05:30
Nabin Hait
7f540af7a6 bumped to version 7.1.18 2016-11-23 15:23:42 +06:00
Nabin Hait
b18ad55e2b minor fixes 2016-11-23 14:51:30 +05:30
Nabin Hait
b439afb5e5 Merge pull request #7045 from saurabh6790/root_type_fix_and_other
[fix] Root type fix
2016-11-23 14:46:05 +05:30
Nabin Hait
cf895c220c Update account_tree.js 2016-11-23 14:44:07 +05:30
Saurabh
9342f650e0 [fix] remove root type selection while created new node and hooks call to initialize payment gateway 2016-11-23 14:06:14 +05:30
Nabin Hait
b91aed807a Merge pull request #7042 from RobertSchouten/naming_series
[fix] naming series only show non disabled role doctypes
2016-11-23 13:26:19 +05:30
robert schouten
085706bcbf [fix] naming series only show non disabled role doctypes 2016-11-23 13:57:21 +08:00
Rushabh Mehta
8685225644 Merge branch 'hotfix' 2016-11-22 23:18:28 +05:30
Rushabh Mehta
6557e37d5c bumped to version 7.1.17 2016-11-22 23:48:28 +06:00
Rushabh Mehta
698c040d21 [hot] fix quotation (#7039) 2016-11-22 23:16:40 +05:30
Nabin Hait
c381327e6e Merge pull request #7032 from rohitwaghchaure/patch_issue
fix patch
2016-11-22 13:51:51 +05:30
Rohit Waghchaure
334f032780 fix patch 2016-11-22 13:30:13 +05:30
Nabin Hait
ee874a2a36 Update student_admission.py 2016-11-22 12:42:24 +05:30
Nabin Hait
8132be288f Merge branch 'hotfix' 2016-11-21 19:10:05 +05:30
Nabin Hait
d75d3a927d bumped to version 7.1.16 2016-11-21 19:40:05 +06:00
Nabin Hait
651d8e996b Merge pull request #7020 from nabinhait/balance_sheet_fix
Provisional Loss related fix in Balance Sheet. Fixed #6918
2016-11-21 19:06:42 +05:30
Nabin Hait
d01d74cafd Merge pull request #7019 from nabinhait/fix_10014
Default warehouse is mandatory only for stock item in POS. Fixed #6893
2016-11-21 19:06:30 +05:30
Nabin Hait
9789b50ae5 Merge pull request #7018 from nabinhait/fix_10013
Set project from Sales Order while creating Material Request from PPT, fixed #6731
2016-11-21 19:06:14 +05:30
Nabin Hait
5224a04628 Merge pull request #7016 from nabinhait/fix_10012
Set WIP warehouse in Pro Order based on Manufacturing Settings. Fixed #6636
2016-11-21 19:05:50 +05:30
Nabin Hait
bdab3103e3 Merge pull request #7015 from nabinhait/fix_10011
Multiple fixes
2016-11-21 19:05:34 +05:30
Nabin Hait
376e8945f7 Merge pull request #7014 from rohitwaghchaure/rename_autoname_field
patch for rename autoname field
2016-11-21 19:04:44 +05:30
Nabin Hait
3d5ef804b2 Provisional Loss related fix in Balance Sheet. Fixed #6918 2016-11-21 18:53:05 +05:30
Nabin Hait
977eff911f Default warehouse is mandatory only for stock item in POS. Fixed #6893 2016-11-21 18:29:16 +05:30
Nabin Hait
9b797974b5 Set project from Sales Order while creating Material Request from PPT, fixed #6731 2016-11-21 18:15:50 +05:30
Nabin Hait
075e33245e Set WIP warehouse in Pro Order based on Manufacturing Settings. Fixed #6636 2016-11-21 18:09:55 +05:30
Nabin Hait
fd23fa7c0b Prifitability report link added to accounts module page 2016-11-21 16:59:03 +05:30
Nabin Hait
542bf8f7d4 Party filter and total row for opening and closing in trial balance for party report 2016-11-21 16:58:50 +05:30
Rohit Waghchaure
4810d1fa2d patch for rename autoname field 2016-11-21 16:52:50 +05:30
Nabin Hait
8d161ef2e1 Merge pull request #6899 from shreyasp/docs-update
Updated Docs for Purchase Order and Supplier Quotation
2016-11-21 15:28:27 +05:30
Nabin Hait
e60d51b74c Merge pull request #6969 from rohitwaghchaure/pos_syncing_issue_and_enhancement
User can able to add multiple item group, customer group in the POS profile.
2016-11-21 15:27:41 +05:30
Nabin Hait
b30e184f6b Merge pull request #7003 from KanchanChauhan/workstation-fix
[Fix]Workstation holiday list
2016-11-21 14:51:24 +05:30
Nabin Hait
0900407c18 Merge pull request #7010 from rmehta/duplicate-icon-patch-fix
[patch] reload desktop icon #6826
2016-11-21 14:50:36 +05:30
Nabin Hait
c16b373969 Merge pull request #6994 from nabinhait/manual_depreciation
Manual Depreciation Schedule for Asset
2016-11-21 14:49:58 +05:30
Rushabh Mehta
e9fc31168d [patch] reload desktop icon #6826 2016-11-21 14:29:31 +05:30
Kanchan Chauhan
d33c44e3a5 [Fix]Workstation holiday list 2016-11-21 11:23:01 +05:30
Rohit Waghchaure
a27c417e48 fix master data sync performance issue 2016-11-20 23:41:13 +05:30
Nabin Hait
cbd26e3b2c Manual Depreciation Schedule for Asset 2016-11-18 17:19:45 +05:30
Rohit Waghchaure
2a81960e0b test cases 2016-11-18 15:33:11 +05:30
Rohit Waghchaure
801029e055 Added item groups, customer groups in the POS profile. 2016-11-18 15:32:48 +05:30
Nabin Hait
c29c5210f9 Merge pull request #6972 from RobertSchouten/bankstatement
[fix] update bank recon statement printing for payment entries
2016-11-18 12:50:40 +05:30
Nabin Hait
a3a59ea895 Merge pull request #6973 from RobertSchouten/bankrecon
[fix] layout for bank reconciliation
2016-11-18 12:49:16 +05:30
Nabin Hait
684d44385f Merge pull request #6991 from rohitwaghchaure/delivery_note_issue
[Fix] Delivery note, show paking items in order, show serial no of the respective item in the dropdown of packing item
2016-11-18 12:45:31 +05:30
Nabin Hait
eae077e05d Merge pull request #6989 from RobertSchouten/financialprint
[fix] financial printing and add to profitability
2016-11-18 12:44:50 +05:30
Rohit Waghchaure
e887e92dd4 Minor fix in delivery note, show paking items in order, show serial no of the respective item in the dropdown of packing item 2016-11-18 12:16:22 +05:30
robert schouten
0a1f3e4058 [fix] financial printing and add to profitability 2016-11-18 10:54:01 +08:00
Nabin Hait
05d0cd9574 Merge pull request #6982 from rohitwaghchaure/pos_is_pos_default_issue
[Fix] Onload pull pos profile data for IS POS invoice
2016-11-17 18:29:22 +05:30
Rohit Waghchaure
2ef7c7ae5c [Fix] Onload pull pos profile data for IS POS invoice 2016-11-17 17:29:10 +05:30
Nabin Hait
d79cca3ba7 Merge branch 'hotfix' 2016-11-17 16:41:51 +05:30
Nabin Hait
f83302836c bumped to version 7.1.15 2016-11-17 17:11:51 +06:00
Nabin Hait
bd99a7cb5d Merge pull request #6980 from shreyasp/setup-wizard-domain
[Fix] Updated 'FR' translation to prevent setup wizard failure
2016-11-17 16:07:43 +05:30
Nabin Hait
29570d1ecb Merge branch 'hotfix' 2016-11-17 15:54:07 +05:30
Nabin Hait
f2b7ec919a bumped to version 7.1.14 2016-11-17 16:24:07 +06:00
Nabin Hait
f76aab6021 Merge pull request #6976 from saurabh6790/advance_payment_entry_cancellation_fix
[fix] on advance payment entry cancellation delink invoice and pyamen…
2016-11-17 15:41:31 +05:30
robert schouten
2b63e14089 dh drop guest from student attendance so disabling acedemic user disables all school doctypes (#6974) 2016-11-17 15:23:38 +05:30
Saurabh
1d210968de [fix] on advance payment entry cancellation delink invoice and pyament entry references 2016-11-17 15:21:46 +05:30
shreyas
0c93445be0 [Fix] Updated 'FR' translation to prevent setup wizard failure 2016-11-17 14:31:32 +05:30
Nabin Hait
7fc05d6432 Update update_missing_salary_component_type.py 2016-11-17 12:16:52 +05:30
robert schouten
a943535520 [fix] update bank recon statement printing for payment entries 2016-11-17 14:33:28 +08:00
robert schouten
60fb1b8643 [fix] layout for bank reconciliation 2016-11-17 14:30:47 +08:00
Nabin Hait
aa68058910 Updated modified_datetime in production planning tool 2016-11-16 17:41:08 +05:30
Nabin Hait
8dd859920f Merge pull request #6960 from KanchanChauhan/thumbnail-in-shoppingcart
[Fix]Product thumbnail in Shopping Cart
2016-11-16 17:34:17 +05:30
Nabin Hait
7f6b99aca4 Merge pull request #6962 from KanchanChauhan/payroll-fixes
[Fix] Filters to get employee in Payroll
2016-11-16 17:34:00 +05:30
Nabin Hait
01dc2e412d Merge pull request #6964 from mbauskar/hotfix
[minor] fixes in validate selling price
2016-11-16 17:32:11 +05:30
mbauskar
e9747a8a6e [minor] fixes in validate selling price 2016-11-16 17:19:47 +05:30
Kanchan Chauhan
7652b857c8 [Fix] Filters to get employee in Payroll 2016-11-16 15:29:01 +05:30
Kanchan Chauhan
98f499a43e [Fix]Product thumbnail in Shopping Cart 2016-11-16 15:17:55 +05:30
Nabin Hait
535462fc20 Merge pull request #6947 from saurabh6790/delink_jv_from_advance
[fix] delink jv from advance table
2016-11-16 14:22:03 +05:30
Nabin Hait
e346a499c7 Merge pull request #6956 from rohitwaghchaure/payment_entry_issue
[Fix] Payment entry, exchange rate is not set properly
2016-11-16 14:15:52 +05:30
Saurabh
8adbfa8a09 [test-case] test cases for delinking advance payments 2016-11-16 13:43:01 +05:30
Saurabh
866c295989 [fix] on jv cancel remove linkings from advance table of Sales/Purchase Invoice 2016-11-16 13:43:01 +05:30
Nabin Hait
67bceef1cb Merge branch 'hotfix' 2016-11-16 12:55:59 +05:30
Nabin Hait
38bfcaa203 bumped to version 7.1.13 2016-11-16 13:25:59 +06:00
Nabin Hait
00e841d744 update missing salary component abbr 2016-11-16 12:55:17 +05:30
Rohit Waghchaure
9b18ed4ffe [Fix] Payment entry, exchange rate is not set properly 2016-11-16 12:24:40 +05:30
Rushabh Mehta
d65d67e0a7 Merge branch 'hotfix' 2016-11-16 11:26:42 +05:30
Rushabh Mehta
a78bac61cc bumped to version 7.1.12 2016-11-16 11:56:42 +06:00
rohitwaghchaure
48cb3d89b6 [Fix] Opening balance calculation issue for balance sheet (#6945) 2016-11-16 11:18:49 +05:30
Rushabh Mehta
8dfbe7c748 [fix] patch missing salary component type based on existing salary slips (#6955) 2016-11-16 11:18:20 +05:30
Shreyas Patil
99a3593a0d [Fix] Make from_date and to_date for stock balance query report as mandatory fields (#6948) 2016-11-16 11:16:44 +05:30
rohitwaghchaure
7be942db54 [Fix] Status updater for sales order in purchase order (#6944) 2016-11-16 11:14:32 +05:30
Rushabh Mehta
24f658d633 [fix] [minor] accounts receivable not translated (#6943) 2016-11-16 11:13:46 +05:30
Rushabh Mehta
d51e1587d5 [fix] contact us page should create a opportunity by default (#6939) 2016-11-16 11:13:31 +05:30
rohitwaghchaure
b3ba7f01ef [Fix] PO status not changed as material return created against them (#6869) 2016-11-16 11:10:10 +05:30
Rushabh Mehta
e0ab64d6cc [minor] reload user for patch 2016-11-15 16:43:37 +05:30
Nabin Hait
952b1cb9a7 Merge pull request #6933 from rohitwaghchaure/remove_no_copy
disable no copy for po number, po date on sales order
2016-11-14 17:47:57 +05:30
Rohit Waghchaure
6f27f580e1 disable no copy for po number, po date on sales order 2016-11-14 16:08:18 +05:30
Rushabh Mehta
440650d4a2 [fix] view shopping cart dropdown (#6928) 2016-11-14 13:13:53 +05:30
Nabin Hait
6261745366 Merge branch 'hotfix' 2016-11-14 12:42:26 +05:30
Nabin Hait
d209f21e76 bumped to version 7.1.11 2016-11-14 13:12:25 +06:00
Nabin Hait
da4689461a Merge pull request #6926 from nabinhait/hotfix
Multiple fixes
2016-11-14 12:37:11 +05:30
Nabin Hait
a5a733630f [fix] Opportunity loading issue 2016-11-14 12:32:16 +05:30
Nabin Hait
0075c7e659 Purchase Order and Receipt links in Purchase Invoice dashboard 2016-11-14 12:32:16 +05:30
Nabin Hait
7017dc029a Editable grid columns for payment entry 2016-11-14 12:32:16 +05:30
Nabin Hait
f98835036b Merge pull request #6900 from rohitwaghchaure/account_receivable_summary_report_issue
[Report] Company not found in the filter for making auto email report
2016-11-14 12:00:48 +05:30
Nabin Hait
47c8d5fd56 Merge pull request #6924 from nabinhait/hotfix
Fixed multiple minor issues
2016-11-14 11:59:46 +05:30
Nabin Hait
6209f2f75b Merge pull request #6925 from rmehta/setup-wizard-fix
[fix] ignore duplicate names for program, academic term, academic year, course, instructor
2016-11-14 11:59:26 +05:30
Rushabh Mehta
463808ef9e [fix] ignore duplicate names for program, academic term, academic year, course, instructor 2016-11-14 11:21:11 +05:30
Nabin Hait
256a3fef95 Fixed multiple minor issues 2016-11-14 11:10:50 +05:30
Rohit Waghchaure
387c2846aa [Report] Company not found in the filter for making auto email report 2016-11-10 19:13:20 +05:30
shreyas
2cb294c8b4 [Docs] Updated docs for supplier quotation and purchase order 2016-11-10 18:14:33 +05:30
Nabin Hait
598a0c918d [fix] fixed student dashboard issue (#6897) 2016-11-10 17:25:37 +05:30
Nabin Hait
176577b549 Merge branch 'hotfix' 2016-11-10 11:25:33 +05:30
Nabin Hait
27c1f85836 bumped to version 7.1.10 2016-11-10 11:55:33 +06:00
Nabin Hait
84ecaac27d Update set_base_amount_in_invoice_payment_table.py 2016-11-10 11:24:22 +05:30
98 changed files with 1445 additions and 482 deletions

View File

@@ -2,7 +2,7 @@
from __future__ import unicode_literals
import frappe
__version__ = '7.1.9'
__version__ = '7.1.18'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -27,7 +27,8 @@ frappe.treeview_settings["Account"] = {
{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'),
description: __('Further accounts can be made under Groups, but entries can be made against non-Groups')},
{fieldtype:'Select', fieldname:'root_type', label:__('Root Type'),
options: ['Asset', 'Liability', 'Equity', 'Income', 'Expense'].join('\n')},
options: ['Asset', 'Liability', 'Equity', 'Income', 'Expense'].join('\n'),
depends_on: 'eval:doc.is_group && !doc.parent_account'},
{fieldtype:'Select', fieldname:'account_type', label:__('Account Type'),
options: ['', 'Bank', 'Cash', 'Stock', 'Tax', 'Chargeable', 'Fixed Asset'].join('\n'),
description: __("Optional. This setting will be used to filter in various transactions.")
@@ -79,4 +80,4 @@ frappe.treeview_settings["Account"] = {
}
],
extend_toolbar: true
}
}

View File

@@ -28,6 +28,7 @@ frappe.ui.form.on('Asset', {
refresh: function(frm) {
frappe.ui.form.trigger("Asset", "is_existing_asset");
frm.toggle_display("next_depreciation_date", frm.doc.docstatus < 1);
frm.events.make_schedules_editable(frm);
if (frm.doc.docstatus==1) {
if (frm.doc.status=='Submitted' && !frm.doc.is_existing_asset && !frm.doc.purchase_invoice) {
@@ -141,6 +142,22 @@ frappe.ui.form.on('Asset', {
frm.toggle_enable("supplier", frm.doc.is_existing_asset);
frm.toggle_reqd("next_depreciation_date", !frm.doc.is_existing_asset);
},
opening_accumulated_depreciation: function(frm) {
erpnext.asset.set_accululated_depreciation(frm);
},
depreciation_method: function(frm) {
frm.events.make_schedules_editable(frm);
},
make_schedules_editable: function(frm) {
var is_editable = frm.doc.depreciation_method==="Manual" ? true : false;
frm.toggle_enable("schedules", is_editable);
frm.fields_dict["schedules"].grid.toggle_enable("schedule_date", is_editable);
frm.fields_dict["schedules"].grid.toggle_enable("depreciation_amount", is_editable);
}
});
frappe.ui.form.on('Depreciation Schedule', {
@@ -159,9 +176,25 @@ frappe.ui.form.on('Depreciation Schedule', {
}
})
}
},
depreciation_amount: function(frm, cdt, cdn) {
erpnext.asset.set_accululated_depreciation(frm);
}
})
erpnext.asset.set_accululated_depreciation = function(frm) {
if(frm.doc.depreciation_method != "Manual") return;
accumulated_depreciation = flt(frm.doc.opening_accumulated_depreciation);
$.each(frm.doc.schedules || [], function(i, row) {
accumulated_depreciation += flt(row.depreciation_amount);
frappe.model.set_value(row.doctype, row.name,
"accumulated_depreciation_amount", accumulated_depreciation);
})
}
erpnext.asset.make_purchase_invoice = function(frm) {
frappe.call({
args: {

View File

@@ -516,7 +516,7 @@
"columns": 0,
"fieldname": "value_after_depreciation",
"fieldtype": "Currency",
"hidden": 0,
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
@@ -580,7 +580,7 @@
"label": "Depreciation Method",
"length": 0,
"no_copy": 0,
"options": "\nStraight Line\nDouble Declining Balance",
"options": "\nStraight Line\nDouble Declining Balance\nManual",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -750,7 +750,7 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -797,7 +797,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-11-03 14:58:53.710357",
"modified": "2016-11-18 15:59:19.774500",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Asset",

View File

@@ -18,6 +18,7 @@ class Asset(Document):
self.set_missing_values()
self.validate_asset_values()
self.make_depreciation_schedule()
self.set_accumulated_depreciation()
self.validate_expected_value_after_useful_life()
# Validate depreciation related accounts
get_depreciation_accounts(self)
@@ -48,7 +49,7 @@ class Asset(Document):
for field, value in item_details.items():
if not self.get(field):
self.set(field, value)
self.value_after_depreciation = (flt(self.gross_purchase_amount) -
flt(self.opening_accumulated_depreciation))
@@ -87,9 +88,10 @@ class Asset(Document):
frappe.throw(_("Please set Next Depreciation Date"))
def make_depreciation_schedule(self):
self.schedules = []
if self.depreciation_method != 'Manual':
self.schedules = []
if not self.get("schedules") and self.next_depreciation_date:
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
value_after_depreciation = flt(self.value_after_depreciation)
number_of_pending_depreciations = cint(self.total_number_of_depreciations) - \
@@ -100,18 +102,21 @@ class Asset(Document):
n * cint(self.frequency_of_depreciation))
depreciation_amount = self.get_depreciation_amount(value_after_depreciation)
accumulated_depreciation += flt(depreciation_amount)
value_after_depreciation -= flt(depreciation_amount)
self.append("schedules", {
"schedule_date": schedule_date,
"depreciation_amount": depreciation_amount,
"accumulated_depreciation_amount": accumulated_depreciation
"depreciation_amount": depreciation_amount
})
def set_accumulated_depreciation(self):
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
for d in self.get("schedules"):
accumulated_depreciation += flt(d.depreciation_amount)
d.accumulated_depreciation_amount = accumulated_depreciation
def get_depreciation_amount(self, depreciable_value):
if self.depreciation_method == "Straight Line":
if self.depreciation_method in ("Straight Line", "Manual"):
depreciation_amount = (flt(self.value_after_depreciation) -
flt(self.expected_value_after_useful_life)) / (cint(self.total_number_of_depreciations) -
cint(self.number_of_depreciations_booked))
@@ -126,16 +131,15 @@ class Asset(Document):
return depreciation_amount
def validate_expected_value_after_useful_life(self):
if self.depreciation_method == "Double Declining Balance":
accumulated_depreciation_after_full_schedule = \
max([d.accumulated_depreciation_amount for d in self.get("schedules")])
asset_value_after_full_schedule = (flt(self.gross_purchase_amount) -
flt(accumulated_depreciation_after_full_schedule))
if self.expected_value_after_useful_life < asset_value_after_full_schedule:
frappe.throw(_("Expected value after useful life must be greater than or equal to {0}")
.format(asset_value_after_full_schedule))
accumulated_depreciation_after_full_schedule = \
max([d.accumulated_depreciation_amount for d in self.get("schedules")])
asset_value_after_full_schedule = (flt(self.gross_purchase_amount) -
flt(accumulated_depreciation_after_full_schedule))
if self.expected_value_after_useful_life < asset_value_after_full_schedule:
frappe.throw(_("Expected value after useful life must be greater than or equal to {0}")
.format(asset_value_after_full_schedule))
def validate_cancellation(self):
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):

View File

@@ -119,6 +119,30 @@ class TestAsset(unittest.TestCase):
for d in asset.get("schedules")]
self.assertEqual(schedules, expected_schedules)
def test_schedule_for_manual_method(self):
asset = frappe.get_doc("Asset", "Macbook Pro 1")
asset.depreciation_method = "Manual"
asset.schedules = []
for schedule_date, amount in [["2020-12-31", 40000], ["2021-06-30", 30000], ["2021-10-31", 20000]]:
asset.append("schedules", {
"schedule_date": schedule_date,
"depreciation_amount": amount
})
asset.save()
self.assertEqual(asset.status, "Draft")
expected_schedules = [
["2020-12-31", 40000, 40000],
["2021-06-30", 30000, 70000],
["2021-10-31", 20000, 90000]
]
schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
for d in asset.get("schedules")]
self.assertEqual(schedules, expected_schedules)
def test_depreciation(self):
asset = frappe.get_doc("Asset", "Macbook Pro 1")

View File

@@ -46,6 +46,12 @@ frappe.ui.form.on("Bank Reconciliation", {
callback: function(r, rt) {
frm.refresh_field("payment_entries");
frm.refresh_fields();
$(frm.fields_dict.payment_entries.wrapper).find("[data-fieldname=amount]").each(function(i,v){
if (i !=0){
$(v).addClass("text-right")
}
})
}
});
}

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt, getdate, nowdate
from frappe.utils import flt, getdate, nowdate, fmt_money
from frappe import msgprint, _
from frappe.model.document import Document
@@ -26,8 +26,8 @@ class BankReconciliation(Document):
select
"Journal Entry" as payment_document, t1.name as payment_entry,
t1.cheque_no as cheque_number, t1.cheque_date,
abs(t2.debit_in_account_currency - t2.credit_in_account_currency) as amount,
t1.posting_date, t2.against_account, t1.clearance_date
t2.debit_in_account_currency as debit, t2.credit_in_account_currency as credit,
t1.posting_date, t2.against_account, t1.clearance_date, t2.account_currency
from
`tabJournal Entry` t1, `tabJournal Entry Account` t2
where
@@ -36,21 +36,23 @@ class BankReconciliation(Document):
and ifnull(t1.is_opening, 'No') = 'No' {0}
order by t1.posting_date ASC, t1.name DESC
""".format(condition), (self.bank_account, self.from_date, self.to_date), as_dict=1)
payment_entries = frappe.db.sql("""
select
"Payment Entry" as payment_document, name as payment_entry,
reference_no as cheque_number, reference_date as cheque_date,
if(paid_from=%s, paid_amount, received_amount) as amount,
posting_date, party as against_account, clearance_date
if(paid_from=%(account)s, paid_amount, "") as credit,
if(paid_from=%(account)s, "", received_amount) as debit,
posting_date, ifnull(party,if(paid_from=%(account)s,paid_to,paid_from)) as against_account, clearance_date,
if(paid_to=%(account)s, paid_to_account_currency, paid_from_account_currency) as account_currency
from `tabPayment Entry`
where
(paid_from=%s or paid_to=%s) and docstatus=1
and posting_date >= %s and posting_date <= %s {0}
(paid_from=%(account)s or paid_to=%(account)s) and docstatus=1
and posting_date >= %(from)s and posting_date <= %(to)s {0}
order by
posting_date ASC, name DESC
""".format(condition),
(self.bank_account, self.bank_account, self.bank_account, self.from_date, self.to_date), as_dict=1)
{"account":self.bank_account, "from":self.from_date, "to":self.to_date}, as_dict=1)
entries = sorted(list(payment_entries)+list(journal_entries),
key=lambda k: k['posting_date'] or getdate(nowdate()))
@@ -60,6 +62,11 @@ class BankReconciliation(Document):
for d in entries:
row = self.append('payment_entries', {})
d.amount = fmt_money(d.debit if d.debit else d.credit, 2, d.account_currency) + " " + (_("Dr") if d.debit else _("Cr"))
d.pop("credit")
d.pop("debit")
d.pop("account_currency")
row.update(d)
self.total_amount += flt(d.amount)

View File

@@ -40,14 +40,14 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"columns": 1,
"fieldname": "payment_entry",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_list_view": 1,
"label": "Payment Entry",
"length": 0,
"no_copy": 0,
@@ -69,7 +69,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 3,
"columns": 2,
"fieldname": "against_account",
"fieldtype": "Data",
"hidden": 0,
@@ -99,7 +99,7 @@
"collapsible": 0,
"columns": 2,
"fieldname": "amount",
"fieldtype": "Currency",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -110,7 +110,7 @@
"no_copy": 0,
"oldfieldname": "debit",
"oldfieldtype": "Currency",
"options": "account_currency",
"options": "",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
@@ -151,7 +151,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"columns": 2,
"fieldname": "posting_date",
"fieldtype": "Date",
"hidden": 0,
@@ -178,7 +178,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 3,
"columns": 1,
"fieldname": "cheque_number",
"fieldtype": "Data",
"hidden": 0,
@@ -267,7 +267,7 @@
"istable": 1,
"max_attachments": 0,
"menu_index": 0,
"modified": "2016-08-26 01:51:36.123941",
"modified": "2016-11-17 11:39:00.308624",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Reconciliation Detail",

View File

@@ -10,11 +10,13 @@
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "schedule_date",
"fieldtype": "Date",
"hidden": 0,
@@ -29,7 +31,8 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -40,6 +43,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "depreciation_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -55,7 +59,8 @@
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -66,6 +71,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
@@ -80,6 +86,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -90,6 +97,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "accumulated_depreciation_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -106,8 +114,9 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -116,6 +125,8 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.docstatus==1",
"fieldname": "journal_entry",
"fieldtype": "Link",
"hidden": 0,
@@ -132,6 +143,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -142,7 +154,8 @@
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:(!doc.journal_entry && doc.schedule_date <= get_today())",
"columns": 0,
"depends_on": "eval:(doc.docstatus==1 && !doc.journal_entry && doc.schedule_date <= get_today())",
"fieldname": "make_depreciation_entry",
"fieldtype": "Button",
"hidden": 0,
@@ -158,6 +171,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -175,7 +189,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-07-11 03:27:59.603924",
"modified": "2016-11-18 16:42:19.543657",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Depreciation Schedule",

View File

@@ -64,11 +64,20 @@ class JournalEntry(AccountsController):
from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries
from erpnext.hr.doctype.salary_slip.salary_slip import unlink_ref_doc_from_salary_slip
unlink_ref_doc_from_payment_entries(self.doctype, self.name)
unlink_ref_doc_from_salary_slip(self.name)
unlink_ref_doc_from_salary_slip(self.name)
self.make_gl_entries(1)
self.update_advance_paid()
self.update_expense_claim()
self.unlink_advance_entry_reference()
def unlink_advance_entry_reference(self):
for d in self.get("accounts"):
if d.is_advance and d.reference_type in ("Sales Invoice", "Purchase Invoice"):
doc = frappe.get_doc(d.reference_type, d.reference_name)
doc.delink_advance_entries(self.name)
d.reference_type = ''
d.reference_name = ''
d.db_update()
def validate_party(self):
for d in self.get("accounts"):

View File

@@ -9,11 +9,14 @@
"description": "**Monthly Distribution** helps you distribute the Budget/Target across months if you have seasonality in your business.",
"docstatus": 0,
"doctype": "DocType",
"editable_grid": 0,
"engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Name of the Monthly Distribution",
"fieldname": "distribution_id",
"fieldtype": "Data",
@@ -31,6 +34,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -41,6 +45,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "fiscal_year",
"fieldtype": "Link",
"hidden": 0,
@@ -58,6 +63,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1,
@@ -68,6 +74,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "percentages",
"fieldtype": "Table",
"hidden": 0,
@@ -85,6 +92,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -96,13 +104,14 @@
"hide_toolbar": 0,
"icon": "icon-bar-chart",
"idx": 1,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-05-16 16:35:20.349194",
"modified": "2016-11-21 14:54:35.998761",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Monthly Distribution",
@@ -119,6 +128,7 @@
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
@@ -139,6 +149,7 @@
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 2,
"print": 0,
"read": 1,
@@ -150,7 +161,7 @@
"write": 0
}
],
"quick_entry": 1,
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",

View File

@@ -406,7 +406,10 @@ frappe.ui.form.on('Payment Entry', {
if(!frm.doc.paid_amount && frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
frm.set_value("paid_amount", frm.doc.received_amount);
frm.set_value("source_exchange_rate", frm.doc.target_exchange_rate);
if(frm.doc.target_exchange_rate) {
frm.set_value("source_exchange_rate", frm.doc.target_exchange_rate);
}
frm.set_value("base_paid_amount", frm.doc.base_received_amount);
}
@@ -426,7 +429,10 @@ frappe.ui.form.on('Payment Entry', {
(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) {
frm.set_value("received_amount", frm.doc.paid_amount);
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
if(frm.doc.source_exchange_rate) {
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
}
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
}

View File

@@ -60,7 +60,14 @@ class PaymentEntry(AccountsController):
self.setup_party_account_field()
self.make_gl_entries(cancel=1)
self.update_advance_paid()
self.delink_advance_entry_references()
def delink_advance_entry_references(self):
for reference in self.references:
if reference.reference_doctype in ("Sales Invoice", "Purchase Invoice"):
doc = frappe.get_doc(reference.reference_doctype, reference.reference_name)
doc.delink_advance_entries(self.name)
def set_missing_values(self):
if self.payment_type == "Internal Transfer":
for field in ("party", "party_balance", "total_allocated_amount",

View File

@@ -31,6 +31,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -58,6 +59,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -84,6 +86,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -109,6 +112,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -119,7 +123,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"columns": 2,
"fieldname": "total_amount",
"fieldtype": "Float",
"hidden": 0,
@@ -135,6 +139,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -145,7 +150,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 3,
"columns": 2,
"fieldname": "outstanding_amount",
"fieldtype": "Float",
"hidden": 0,
@@ -161,6 +166,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -171,7 +177,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 3,
"columns": 2,
"fieldname": "allocated_amount",
"fieldtype": "Float",
"hidden": 0,
@@ -187,6 +193,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -213,6 +220,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -230,7 +238,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-08-26 01:59:04.697274",
"modified": "2016-11-14 12:28:51.822341",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry Reference",

View File

@@ -0,0 +1,66 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2016-11-16 15:27:16.413449",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "customer_group",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Customer Group",
"length": 0,
"no_copy": 0,
"options": "Customer Group",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-11-16 15:27:25.730507",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Customer Group",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_seen": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class POSCustomerGroup(Document):
pass

View File

@@ -0,0 +1,66 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2016-11-16 15:26:47.706713",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_group",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Item Group",
"length": 0,
"no_copy": 0,
"options": "Item Group",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-11-16 15:27:32.263630",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Item Group",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_seen": 0
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class POSItemGroup(Document):
pass

View File

@@ -26,6 +26,30 @@ frappe.ui.form.on("POS Profile", "onload", function(frm) {
});
});
frappe.ui.form.on("POS Profile", {
setup: function(frm) {
frm.trigger("get_query_for_groups")
},
get_query_for_groups: function(frm) {
frm.fields_dict['item_groups'].grid.get_field('item_group').get_query = function(frm, cdt, cdn) {
return{
filters: {
'is_group': 0
}
}
}
frm.fields_dict['customer_groups'].grid.get_field('customer_group').get_query = function(frm, cdt, cdn) {
return{
filters: {
'is_group': 0
}
}
}
}
})
// Income Account
// --------------------------------
cur_frm.fields_dict['income_account'].get_query = function(doc,cdt,cdn) {

View File

@@ -375,6 +375,114 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_14",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_groups",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Item Groups",
"length": 0,
"no_copy": 0,
"options": "POS Item Group",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_16",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "customer_groups",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Customer Groups",
"length": 0,
"no_copy": 0,
"options": "POS Customer Group",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -543,34 +651,6 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "customer_group",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Customer Group",
"length": 0,
"no_copy": 0,
"options": "Customer Group",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -951,8 +1031,8 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-11-03 15:53:33.820428",
"modified_by": "Administrator",
"modified": "2016-11-17 00:20:51.377850",
"modified_by": "rohit@erpnext.com",
"module": "Accounts",
"name": "POS Profile",
"owner": "Administrator",

View File

@@ -13,6 +13,7 @@ class POSProfile(Document):
def validate(self):
self.check_for_duplicate()
self.validate_all_link_fields()
self.validate_duplicate_groups()
def check_for_duplicate(self):
res = frappe.db.sql("""select name, user from `tabPOS Profile`
@@ -37,6 +38,16 @@ class POSProfile(Document):
"company": self.company, "name": link_dn}):
frappe.throw(_("{0} does not belong to Company {1}").format(link_dn, self.company))
def validate_duplicate_groups(self):
item_groups = [d.item_group for d in self.item_groups]
customer_groups = [d.customer_group for d in self.customer_groups]
if len(item_groups) != len(set(item_groups)):
frappe.throw(_("Duplicate item group found in the item group table"), title = "Duplicate Item Group")
if len(customer_groups) != len(set(customer_groups)):
frappe.throw(_("Duplicate customer group found in the cutomer group table"), title = "Duplicate Customer Group")
def before_save(self):
set_account_for_mode_of_payment(self)

View File

@@ -5,8 +5,47 @@ from __future__ import unicode_literals
import frappe
import unittest
# test_records = frappe.get_test_records('POS Profile')
from erpnext.stock.get_item_details import get_pos_profile
from erpnext.accounts.doctype.sales_invoice.pos import get_items_list, get_customers_list
class TestPOSProfile(unittest.TestCase):
pass
def test_pos_profile(self):
make_pos_profile()
pos_profile = get_pos_profile("_Test Company") or {}
if pos_profile:
doc = frappe.get_doc("POS Profile", pos_profile.get("name"))
doc.append('item_groups', {'item_group': '_Test Item Group'})
doc.append('customer_groups', {'customer_group': '_Test Customer Group'})
doc.save()
items = get_items_list(doc)
customers = get_customers_list(doc)
products_count = frappe.db.sql(""" select count(name) from tabItem where item_group = '_Test Item Group'""", as_list=1)
customers_count = frappe.db.sql(""" select count(name) from tabCustomer where customer_group = '_Test Customer Group'""")
self.assertEquals(len(items), products_count[0][0])
self.assertEquals(len(customers), customers_count[0][0])
frappe.db.sql("delete from `tabPOS Profile`")
def make_pos_profile():
pos_profile = frappe.get_doc({
"company": "_Test Company",
"cost_center": "_Test Cost Center - _TC",
"currency": "INR",
"doctype": "POS Profile",
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"income_account": "Sales - _TC",
"name": "_Test POS Profile",
"naming_series": "_T-POS Profile-",
"selling_price_list": "_Test Price List",
"territory": "_Test Territory",
"warehouse": "_Test Warehouse - _TC",
"write_off_account": "_Test Write Off - _TC",
"write_off_cost_center": "_Test Write Off Cost Center - _TC"
})
if not frappe.db.exists("POS Profile", "_Test POS Profile"):
pos_profile.insert()

View File

@@ -4,7 +4,6 @@ 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',
@@ -12,8 +11,8 @@ def get_data():
'Purchase Invoice': 'return_against'
},
'internal_links': {
'Purchase Order': ['items', 'sales_order'],
'Purchase Receipt': ['items', 'delivery_note'],
'Purchase Order': ['items', 'purchase_order'],
'Purchase Receipt': ['items', 'purchase_receipt'],
},
'transactions': [
{

View File

@@ -437,6 +437,85 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEquals(frappe.db.get_value("Serial No", pi.get("items")[0].rejected_serial_no,
"warehouse"), pi.get("items")[0].rejected_warehouse)
def test_outstanding_amount_after_advance_jv_cancelation(self):
from erpnext.accounts.doctype.journal_entry.test_journal_entry \
import test_records as jv_test_records
jv = frappe.copy_doc(jv_test_records[1])
jv.insert()
jv.submit()
pi = frappe.copy_doc(test_records[0])
pi.append("advances", {
"reference_type": "Journal Entry",
"reference_name": jv.name,
"reference_row": jv.get("accounts")[0].name,
"advance_amount": 400,
"allocated_amount": 300,
"remarks": jv.remark
})
pi.insert()
pi.submit()
pi.load_from_db()
#check outstanding after advance allocation
self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance))
#added to avoid Document has been modified exception
jv = frappe.get_doc("Journal Entry", jv.name)
jv.cancel()
pi.load_from_db()
#check outstanding after advance cancellation
self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance))
def test_outstanding_amount_after_advance_payment_entry_cancelation(self):
pe = frappe.get_doc({
"doctype": "Payment Entry",
"payment_type": "Pay",
"party_type": "Supplier",
"party": "_Test Supplier",
"company": "_Test Company",
"paid_from_account_currency": "INR",
"paid_to_account_currency": "INR",
"source_exchange_rate": 1,
"target_exchange_rate": 1,
"reference_no": "1",
"reference_date": nowdate(),
"received_amount": 300,
"paid_amount": 300,
"paid_from": "_Test Cash - _TC",
"paid_to": "_Test Payable - _TC"
})
pe.insert()
pe.submit()
pi = frappe.copy_doc(test_records[0])
pi.is_pos = 0
pi.append("advances", {
"doctype": "Purchase Invoice Advance",
"reference_type": "Payment Entry",
"reference_name": pe.name,
"advance_amount": 300,
"allocated_amount": 300,
"remarks": pe.remarks
})
pi.insert()
pi.submit()
pi.load_from_db()
#check outstanding after advance allocation
self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance))
#added to avoid Document has been modified exception
pe = frappe.get_doc("Payment Entry", pe.name)
pe.cancel()
pi.load_from_db()
#check outstanding after advance cancellation
self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance))
def unlink_payment_on_cancel_of_invoice(enable=1):
accounts_settings = frappe.get_doc("Accounts Settings")

View File

@@ -30,10 +30,16 @@ def get_pos_data():
return {
'doc': doc,
'default_customer': pos_profile.get('customer'),
'items': get_items(doc, pos_profile),
'customers': get_customers(pos_profile, doc, company_data.default_currency),
'pricing_rules': get_pricing_rules(doc),
'items': get_items_list(pos_profile),
'customers': get_customers_list(pos_profile),
'serial_no_data': get_serial_no_data(pos_profile, doc.company),
'batch_no_data': get_batch_no_data(),
'tax_data': get_item_tax_data(),
'price_list_data': get_price_list_data(doc.selling_price_list),
'bin_data': get_bin_data(pos_profile),
'pricing_rules': get_pricing_rule_data(doc),
'print_template': print_template,
'pos_profile': pos_profile,
'meta': {
'invoice': frappe.get_meta('Sales Invoice'),
'items': frappe.get_meta('Sales Invoice Item'),
@@ -104,63 +110,117 @@ def update_tax_table(doc):
for tax in taxes:
doc.append('taxes', tax)
def get_items(doc, pos_profile):
item_list = []
for item in frappe.get_all("Item", fields=["*"], filters={'disabled': 0, 'has_variants': 0, 'is_sales_item': 1}):
item_doc = frappe.get_doc('Item', item.name)
if item_doc.taxes:
item.taxes = json.dumps(dict(([d.tax_type, d.tax_rate] for d in
item_doc.get("taxes"))))
def get_items_list(pos_profile):
cond = "1=1"
item_groups = []
if pos_profile.get('item_groups'):
# Get items based on the item groups defined in the POS profile
item.price_list_rate = frappe.db.get_value('Item Price', {'item_code': item.name,
'price_list': doc.selling_price_list}, 'price_list_rate') or 0
item.default_warehouse = pos_profile.get('warehouse') or \
get_item_warehouse_for_company(doc.company, item.default_warehouse) or None
item.expense_account = pos_profile.get('expense_account') or item.expense_account
item.income_account = pos_profile.get('income_account') or item_doc.income_account
item.cost_center = pos_profile.get('cost_center') or item_doc.selling_cost_center
item.actual_qty = frappe.db.get_value('Bin', {'item_code': item.name,
'warehouse': item.default_warehouse}, 'actual_qty') or 0
item.serial_nos = get_serial_nos(item, pos_profile, doc.company)
item.batch_nos = frappe.db.sql_list("""select name from `tabBatch` where ifnull(expiry_date, '4000-10-10') > curdate()
and item = %(item_code)s""", {'item_code': item.item_code})
cond = "item_group in (%s)"%(', '.join(['%s']*len(pos_profile.get('item_groups'))))
item_groups = [d.item_group for d in pos_profile.get('item_groups')]
item_list.append(item)
return frappe.db.sql("""
select
name, item_code, item_name, description, item_group, expense_account, has_batch_no,
has_serial_no, expense_account, selling_cost_center, stock_uom, image,
default_warehouse, is_stock_item
from
tabItem
where
disabled = 0 and has_variants = 0 and is_sales_item = 1 and {cond}
""".format(cond=cond), tuple(item_groups), as_dict=1)
return item_list
def get_customers_list(pos_profile):
cond = "1=1"
customer_groups = []
if pos_profile.get('customer_groups'):
# Get customers based on the customer groups defined in the POS profile
def get_item_warehouse_for_company(company, warehouse):
if frappe.db.get_value('Warehouse', warehouse, 'company') != company:
warehouse = None
return warehouse
cond = "customer_group in (%s)"%(', '.join(['%s']*len(pos_profile.get('customer_groups'))))
customer_groups = [d.customer_group for d in pos_profile.get('customer_groups')]
return frappe.db.sql(""" select name, customer_name, customer_group,
territory from tabCustomer where disabled = 0
and {cond}""".format(cond=cond), tuple(customer_groups), as_dict=1) or {}
def get_serial_no_data(pos_profile, company):
# get itemwise serial no data
# example {'Nokia Lumia 1020': {'SN0001': 'Pune'}}
# where Nokia Lumia 1020 is item code, SN0001 is serial no and Pune is warehouse
def get_serial_nos(item, pos_profile, company):
cond = "1=1"
if pos_profile.get('update_stock') and pos_profile.get('warehouse'):
cond = "warehouse = '{0}'".format(pos_profile.get('warehouse'))
serial_nos = frappe.db.sql("""select name, warehouse from `tabSerial No` where {0}
and item_code = %(item_code)s and company = %(company)s
""".format(cond), {'item_code': item.item_code, 'company': company}, as_dict=1)
serial_nos = frappe.db.sql("""select name, warehouse, item_code from `tabSerial No` where {0}
and company = %(company)s """.format(cond), {'company': company}, as_dict=1)
serial_no_list = {}
for serial_no in serial_nos:
serial_no_list[serial_no.name] = serial_no.warehouse
itemwise_serial_no = {}
for sn in serial_nos:
if sn.item_code not in itemwise_serial_no:
itemwise_serial_no.setdefault(sn.item_code, {})
itemwise_serial_no[sn.item_code][sn.name] = sn.warehouse
return serial_no_list
return itemwise_serial_no
def get_customers(pos_profile, doc, company_currency):
filters = {'disabled': 0}
customer_list = []
customers = frappe.get_all("Customer", fields=["*"], filters = filters)
def get_batch_no_data():
# get itemwise batch no data
# exmaple: {'LED-GRE': [Batch001, Batch002]}
# where LED-GRE is item code, SN0001 is serial no and Pune is warehouse
for customer in customers:
customer_currency = get_party_account_currency('Customer', customer.name, doc.company) or doc.currency
if customer_currency == doc.currency or customer_currency == company_currency:
customer_list.append(customer)
return customer_list
itemwise_batch = {}
batches = frappe.db.sql("""select name, item from `tabBatch`
where ifnull(expiry_date, '4000-10-10') >= curdate()""", as_dict=1)
def get_pricing_rules(doc):
for batch in batches:
if batch.item not in itemwise_batch:
itemwise_batch.setdefault(batch.item, [])
itemwise_batch[batch.item].append(batch.name)
return itemwise_batch
def get_item_tax_data():
# get default tax of an item
# example: {'Consulting Services': {'Excise 12 - TS': '12.000'}}
itemwise_tax = {}
taxes = frappe.db.sql(""" select parent, tax_type, tax_rate from `tabItem Tax`""", as_dict=1)
for tax in taxes:
if tax.parent not in itemwise_tax:
itemwise_tax.setdefault(tax.parent, {})
itemwise_tax[tax.parent][tax.tax_type] = tax.tax_rate
return itemwise_tax
def get_price_list_data(selling_price_list):
itemwise_price_list = {}
price_lists = frappe.db.sql("""Select ifnull(price_list_rate, 0) as price_list_rate,
item_code from `tabItem Price` ip where price_list = %(price_list)s""",
{'price_list': selling_price_list}, as_dict=1)
for item in price_lists:
itemwise_price_list[item.item_code] = item.price_list_rate
return itemwise_price_list
def get_bin_data(pos_profile):
itemwise_bin_data = {}
cond = "1=1"
if pos_profile.get('warehouse'):
cond = "warehouse = '{0}'".format(pos_profile.get('warehouse'))
bin_data = frappe.db.sql(""" select item_code, warehouse, actual_qty from `tabBin`
where actual_qty > 0 and {cond}""".format(cond=cond), as_dict=1)
for bins in bin_data:
if bins.item_code not in itemwise_bin_data:
itemwise_bin_data.setdefault(bins.item_code, {})
itemwise_bin_data[bins.item_code][bins.warehouse] = bins.actual_qty
return itemwise_bin_data
def get_pricing_rule_data(doc):
pricing_rules = ""
if doc.ignore_pricing_rule == 0:
pricing_rules = frappe.db.sql(""" Select * from `tabPricing Rule` where docstatus < 2

View File

@@ -20,6 +20,13 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
erpnext.queries.setup_queries(this.frm, "Warehouse", function() {
return erpnext.queries.warehouse(me.frm.doc);
});
if(this.frm.doc.__islocal && this.frm.doc.is_pos) {
//Load pos profile data on the invoice if the default value of Is POS is 1
me.frm.script_manager.trigger("is_pos");
me.frm.refresh_fields();
}
},
refresh: function(doc, dt, dn) {

View File

@@ -7,6 +7,7 @@ import unittest, copy
from frappe.utils import nowdate, add_days, flt, nowdate
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError
@@ -467,7 +468,7 @@ class TestSalesInvoice(unittest.TestCase):
def test_pos_gl_entry_with_perpetual_inventory(self):
set_perpetual_inventory()
self.make_pos_profile()
make_pos_profile()
self._insert_purchase_receipt()
pos = copy.deepcopy(test_records[1])
@@ -486,7 +487,7 @@ class TestSalesInvoice(unittest.TestCase):
def test_pos_change_amount(self):
set_perpetual_inventory()
self.make_pos_profile()
make_pos_profile()
self._insert_purchase_receipt()
pos = copy.deepcopy(test_records[1])
@@ -508,7 +509,7 @@ class TestSalesInvoice(unittest.TestCase):
set_perpetual_inventory()
self.make_pos_profile()
make_pos_profile()
self._insert_purchase_receipt()
pos = copy.deepcopy(test_records[1])
@@ -572,26 +573,6 @@ class TestSalesInvoice(unittest.TestCase):
frappe.db.sql("delete from `tabPOS Profile`")
def make_pos_profile(self):
pos_profile = frappe.get_doc({
"company": "_Test Company",
"cost_center": "_Test Cost Center - _TC",
"currency": "INR",
"doctype": "POS Profile",
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"income_account": "Sales - _TC",
"name": "_Test POS Profile",
"naming_series": "_T-POS Profile-",
"selling_price_list": "_Test Price List",
"territory": "_Test Territory",
"warehouse": "_Test Warehouse - _TC",
"write_off_account": "_Test Write Off - _TC",
"write_off_cost_center": "_Test Write Off Cost Center - _TC"
})
if not frappe.db.exists("POS Profile", "_Test POS Profile"):
pos_profile.insert()
def test_sales_invoice_gl_entry_with_perpetual_inventory_no_item_code(self):
set_perpetual_inventory()
@@ -980,6 +961,86 @@ class TestSalesInvoice(unittest.TestCase):
pe.submit()
self.assertEquals(frappe.db.get_value('Customer', customer.name, 'status'), 'Active')
def test_outstanding_amount_after_advance_jv_cancelation(self):
from erpnext.accounts.doctype.journal_entry.test_journal_entry \
import test_records as jv_test_records
jv = frappe.copy_doc(jv_test_records[0])
jv.insert()
jv.submit()
si = frappe.copy_doc(test_records[0])
si.append("advances", {
"doctype": "Sales Invoice Advance",
"reference_type": "Journal Entry",
"reference_name": jv.name,
"reference_row": jv.get("accounts")[0].name,
"advance_amount": 400,
"allocated_amount": 300,
"remarks": jv.remark
})
si.insert()
si.submit()
si.load_from_db()
#check outstanding after advance allocation
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount")))
#added to avoid Document has been modified exception
jv = frappe.get_doc("Journal Entry", jv.name)
jv.cancel()
si.load_from_db()
#check outstanding after advance cancellation
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount")))
def test_outstanding_amount_after_advance_payment_entry_cancelation(self):
pe = frappe.get_doc({
"doctype": "Payment Entry",
"payment_type": "Receive",
"party_type": "Customer",
"party": "_Test Customer",
"company": "_Test Company",
"paid_from_account_currency": "INR",
"paid_to_account_currency": "INR",
"source_exchange_rate": 1,
"target_exchange_rate": 1,
"reference_no": "1",
"reference_date": nowdate(),
"received_amount": 300,
"paid_amount": 300,
"paid_from": "_Test Receivable - _TC",
"paid_to": "_Test Cash - _TC"
})
pe.insert()
pe.submit()
si = frappe.copy_doc(test_records[0])
si.is_pos = 0
si.append("advances", {
"doctype": "Sales Invoice Advance",
"reference_type": "Payment Entry",
"reference_name": pe.name,
"advance_amount": 300,
"allocated_amount": 300,
"remarks": pe.remarks
})
si.insert()
si.submit()
si.load_from_db()
#check outstanding after advance allocation
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount")))
#added to avoid Document has been modified exception
pe = frappe.get_doc("Payment Entry", pe.name)
pe.cancel()
si.load_from_db()
#check outstanding after advance cancellation
self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount")))
def create_sales_invoice(**args):
si = frappe.new_doc("Sales Invoice")

View File

@@ -25,7 +25,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
this.set_indicator();
this.onload();
this.make_menu_list();
this.set_interval_for_si_sync();
this.si_docs = this.get_doc_from_localstorage();
},
@@ -73,8 +72,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
this.get_data_from_server(function(){
me.create_new();
});
this.check_internet_connection();
},
make_menu_list: function(){
@@ -204,13 +201,10 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
freeze: true,
freeze_message: __("Master data syncing, it might take some time"),
callback: function(r){
window.items = r.message.items;
window.customers = r.message.customers;
window.pricing_rules = r.message.pricing_rules;
window.meta = r.message.meta;
window.print_template = r.message.print_template;
me.default_customer = r.message.default_customer || null;
me.init_master_data(r)
localStorage.setItem('doc', JSON.stringify(r.message.doc));
me.set_interval_for_si_sync();
me.check_internet_connection();
if(callback){
callback();
}
@@ -218,6 +212,22 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
})
},
init_master_data: function(r){
var me = this;
this.meta = r.message.meta;
this.item_data = r.message.items;
this.customers = r.message.customers;
this.serial_no_data = r.message.serial_no_data;
this.batch_no_data = r.message.batch_no_data;
this.tax_data = r.message.tax_data;
this.price_list_data = r.message.price_list_data;
this.bin_data = r.message.bin_data;
this.pricing_rules = r.message.pricing_rules;
this.print_template = r.message.print_template;
this.pos_profile_data = r.message.pos_profile;
this.default_customer = r.message.default_customer || null;
},
save_previous_entry : function(){
if(this.frm.doc.items.length > 0){
this.create_invoice()
@@ -233,20 +243,19 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
},
load_data: function(load_doc){
this.items = window.items;
this.customers = window.customers;
this.pricing_rules = window.pricing_rules;
var me = this;
this.items = this.item_data;
if(load_doc) {
this.frm.doc = JSON.parse(localStorage.getItem('doc'));
}
$.each(window.meta, function(i, data){
$.each(this.meta, function(i, data){
frappe.meta.sync(data)
})
this.print_template = frappe.render_template("print_template",
{content: window.print_template, title:"POS",
{content: this.print_template, title:"POS",
base_url: frappe.urllib.get_base_url(), print_css: frappe.boot.print_css})
},
@@ -387,12 +396,12 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
var $wrap = me.wrapper.find(".item-list");
me.wrapper.find(".item-list").empty();
if (this.items) {
if (this.items.length > 0) {
$.each(this.items, function(index, obj) {
if(index < 30){
$(frappe.render_template("pos_item", {
item_code: obj.name,
item_price: format_currency(obj.price_list_rate, me.frm.doc.currency),
item_price: format_currency(me.price_list_data[obj.name], me.frm.doc.currency),
item_name: obj.name===obj.item_name ? "" : obj.item_name,
item_image: obj.image ? "url('" + obj.image + "')" : null,
color: frappe.get_palette(obj.item_name),
@@ -400,6 +409,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
})).tooltip().appendTo($wrap);
}
});
} else {
$("<h4>Searching record not found.</h4>").appendTo($wrap)
}
if(this.items.length == 1
@@ -426,7 +437,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
this.item_batch_no = {};
if(item_code){
return $.grep(window.items, function(item){
return $.grep(this.item_data, function(item){
if(item.item_code == item_code ){
return true
}
@@ -439,14 +450,15 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
search_status = true
if(key){
return $.grep(window.items, function(item){
return $.grep(this.item_data, function(item){
if(search_status){
if(in_list(item.batch_nos, me.search.$input.val())){
if(in_list(me.batch_no_data[item.item_code], me.search.$input.val())){
search_status = false;
return me.item_batch_no[item.item_code] = me.search.$input.val()
} else if(in_list(Object.keys(item.serial_nos), me.search.$input.val())) {
} else if( me.serial_no_data[item.item_code]
&& in_list(Object.keys(me.serial_no_data[item.item_code]), me.search.$input.val())) {
search_status = false;
me.item_serial_no[item.item_code] = [me.search.$input.val(), item.serial_nos[me.search.$input.val()]]
me.item_serial_no[item.item_code] = [me.search.$input.val(), me.serial_no_data[item.item_code][me.search.$input.val()]]
return true
} else if(item.barcode == me.search.$input.val()) {
search_status = false;
@@ -458,7 +470,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
}
})
}else{
return window.items;
return this.item_data;
}
},
@@ -611,18 +623,18 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
this.child.description = this.items[0].description;
this.child.qty = 1;
this.child.item_group = this.items[0].item_group;
this.child.cost_center = this.items[0].cost_center;
this.child.income_account = this.items[0].income_account;
this.child.cost_center = this.pos_profile_data['cost_center'] || this.items[0].cost_center;
this.child.income_account = this.pos_profile_data['income_account'] || this.items[0].income_account;
this.child.warehouse = (this.item_serial_no[this.child.item_code]
? this.item_serial_no[this.child.item_code][1] : this.items[0].default_warehouse);
this.child.price_list_rate = flt(this.items[0].price_list_rate, 9) / flt(this.frm.doc.conversion_rate, 9);
this.child.rate = flt(this.items[0].price_list_rate, 9) / flt(this.frm.doc.conversion_rate, 9);
this.child.actual_qty = this.items[0].actual_qty;
? this.item_serial_no[this.child.item_code][1] : (this.pos_profile_data['warehouse'] || this.items[0].default_warehouse) );
this.child.price_list_rate = flt(this.price_list_data[this.child.item_code], 9) / flt(this.frm.doc.conversion_rate, 9);
this.child.rate = flt(this.price_list_data[this.child.item_code], 9) / flt(this.frm.doc.conversion_rate, 9);
this.child.actual_qty = me.get_actual_qty(this.items[0]);
this.child.amount = flt(this.child.qty) * flt(this.child.rate);
this.child.batch_no = this.item_batch_no[this.child.item_code];
this.child.serial_no = (this.item_serial_no[this.child.item_code]
? this.item_serial_no[this.child.item_code][0] : '');
this.child.item_tax_rate = this.items[0].taxes;
this.child.item_tax_rate = JSON.stringify(this.tax_data[this.child.item_code]);
},
update_paid_amount_status: function(update_paid_amount){
@@ -668,7 +680,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
item_code: d.item_code,
item_name: (d.item_name===d.item_code || !d.item_name) ? "" : ("<br>" + d.item_name),
qty: d.qty,
actual_qty: d.actual_qty,
actual_qty: me.actual_qty,
projected_qty: d.projected_qty,
rate: format_number(d.rate, me.frm.doc.currency),
amount: format_currency(d.amount, me.frm.doc.currency)
@@ -1064,8 +1076,18 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
},
validate_warehouse: function(){
if(!this.items[0].default_warehouse){
if(this.items[0].is_stock_item && !this.items[0].default_warehouse && !this.pos_profile_data['warehouse']){
frappe.throw(__("Default warehouse is required for selected item"))
}
},
get_actual_qty: function(item) {
this.actual_qty = 0.0;
var warehouse = this.pos_profile_data['warehouse'] || item.default_warehouse;
if(warehouse && this.bin_data[item.item_code]) {
this.actual_qty = this.bin_data[item.item_code][warehouse] || 0;
}
return this.actual_qty
}
})

View File

@@ -4,7 +4,7 @@
<h2 class="text-center">{%= __(report.report_name) %}</h2>
<h4 class="text-center">{%= filters.customer || filters.supplier %} </h4>
<h5 class="text-center">
{%= filters.ageing_based_on %}
{%= __(filters.ageing_based_on) %}
{%= __("Until") %}
{%= dateutil.str_to_user(filters.report_date) %}
</h5>
@@ -12,7 +12,7 @@
<table class="table table-bordered">
<thead>
<tr>
{% if(__(report.report_name) == "Accounts Receivable" || __(report.report_name) == "Accounts Payable") { %}
{% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
<th style="width: 15%">{%= __("Date") %}</th>
<th style="width: 15%">{%= __("Ref") %}</th>
<th style="width: 40%">{%= __("Party") %}</th>
@@ -30,7 +30,7 @@
<tbody>
{% for(var i=0, l=data.length; i<l; i++) { %}
<tr>
{% if(__(report.report_name) == "Accounts Receivable" || __(report.report_name) == "Accounts Payable") { %}
{% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
{% if(data[i][__("Customer")] || data[i][__("Supplier")]) { %}
<td>{%= dateutil.str_to_user(data[i][__("Posting Date")]) %}</td>
<td>{%= data[i][__("Voucher Type")] %}
@@ -38,21 +38,21 @@
<td>{%= data[i][__("Customer Name")] || data[i][__("Customer")] || data[i][__("Supplier Name")] || data[i][__("Supplier")] %}
<br>{%= __("Remarks") %}: {%= data[i][__("Remarks")] %}</td>
<td style="text-align: right">
{%= format_currency(data[i][__("Invoiced Amount")], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["Invoiced Amount"], data[i]["currency"]) %}</td>
<td style="text-align: right">
{%= format_currency(data[i][__("Paid Amount")], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["Paid Amount"], data[i]["currency"]) %}</td>
<td style="text-align: right">
{%= format_currency(data[i][__("Outstanding Amount")], data[i]["currency"]) %}</td>
{%= format_currency(data[i]["Outstanding Amount"], data[i]["currency"]) %}</td>
{% } else { %}
<td></td>
<td></td>
<td><b>{%= __("Total") %}</b></td>
<td style="text-align: right">
{%= format_currency(data[i][__("Invoiced Amount")]) %}</td>
{%= format_currency(data[i]["Invoiced Amount"]) %}</td>
<td style="text-align: right">
{%= format_currency(data[i][__("Paid Amount")]) %}</td>
{%= format_currency(data[i]["Paid Amount"]) %}</td>
<td style="text-align: right">
{%= format_currency(data[i][__("Outstanding Amount")]) %}</td>
{%= format_currency(data[i]["Outstanding Amount"]) %}</td>
{% } %}
{% } else { %}
{% if(data[i][__("Customer")] || data[i][__("Supplier")]|| "&nbsp;") { %}
@@ -71,4 +71,4 @@
{% } %}
</tbody>
</table>
<p class="text-right text-muted">Printed On {%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>
<p class="text-right text-muted">{{ __("Printed On") }}{%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>

View File

@@ -88,6 +88,9 @@ class ReceivablePayableReport(object):
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
if not self.filters.get("company"):
self.filters["company"] = frappe.db.get_single_value('Global Defaults', 'default_company')
company_currency = frappe.db.get_value("Company", self.filters.get("company"), "default_currency")
data = []

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt
from frappe.utils import flt, cint
from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data)
def execute(filters=None):
@@ -14,10 +14,10 @@ def execute(filters=None):
liability = get_data(filters.company, "Liability", "Credit", period_list, only_current_fiscal_year=False)
equity = get_data(filters.company, "Equity", "Credit", period_list, only_current_fiscal_year=False)
provisional_profit_loss,total_credit = get_provisional_profit_loss(asset, liability, equity,
provisional_profit_loss, total_credit = get_provisional_profit_loss(asset, liability, equity,
period_list, filters.company)
message,opening_balance = check_opening_balance(asset, liability, equity)
message, opening_balance = check_opening_balance(asset, liability, equity)
data = []
data.extend(asset or [])
@@ -32,7 +32,9 @@ def execute(filters=None):
}
for period in period_list:
unclosed[period.key] = opening_balance
provisional_profit_loss[period.key] = provisional_profit_loss[period.key] - opening_balance
if provisional_profit_loss:
provisional_profit_loss[period.key] = provisional_profit_loss[period.key] - opening_balance
unclosed["total"]=opening_balance
data.append(unclosed)
@@ -48,15 +50,11 @@ def execute(filters=None):
return columns, data, message, chart
def get_provisional_profit_loss(asset, liability, equity, period_list, company):
provisional_profit_loss = {}
total_row = {}
if asset and (liability or equity):
total = total_row_total=0
currency = frappe.db.get_value("Company", company, "default_currency")
provisional_profit_loss = {
"account_name": "'" + _("Provisional Profit / Loss (Credit)") + "'",
"account": None,
"warn_if_negative": True,
"currency": currency
}
total_row = {
"account_name": "'" + _("Total (Credit)") + "'",
"account": None,
@@ -85,19 +83,25 @@ def get_provisional_profit_loss(asset, liability, equity, period_list, company):
total_row["total"] = total_row_total
if has_value:
return provisional_profit_loss, total_row
return None,total_row
return None, None
provisional_profit_loss.update({
"account_name": "'" + _("Provisional Profit / Loss (Credit)") + "'",
"account": None,
"warn_if_negative": True,
"currency": currency
})
return provisional_profit_loss, total_row
def check_opening_balance(asset, liability, equity):
# Check if previous year balance sheet closed
opening_balance = 0
float_precision = cint(frappe.db.get_default("float_precision")) or 2
if asset:
opening_balance = flt(asset[0].get("opening_balance", 0))
opening_balance = flt(asset[0].get("opening_balance", 0), float_precision)
if liability:
opening_balance -= flt(liability[0].get("opening_balance", 0))
opening_balance -= flt(liability[0].get("opening_balance", 0), float_precision)
if equity:
opening_balance -= flt(equity[0].get("opening_balance", 0))
opening_balance -= flt(equity[0].get("opening_balance", 0), float_precision)
if opening_balance:
return _("Previous Financial Year is not closed"),opening_balance

View File

@@ -8,7 +8,7 @@
<thead>
<tr>
<th style="width: 15%">{%= __("Posting Date") %}</th>
<th style="width: 15%">{%= __("Journal Entry") %}</th>
<th style="width: 15%">{%= __("Payment Entry") %}</th>
<th style="width: 40%">{%= __("Reference") %}</th>
<th style="width: 15%; text-align: right;">{%= __("Debit") %}</th>
<th style="width: 15%; text-align: right;">{%= __("Credit") %}</th>
@@ -19,10 +19,10 @@
{% if (data[i]["posting_date"]) { %}
<tr>
<td>{%= dateutil.str_to_user(data[i]["posting_date"]) %}</td>
<td>{%= data[i]["journal_entry"] %}</td>
<td>{%= data[i]["payment_entry"] %}</td>
<td>{%= __("Against") %}: {%= data[i]["against_account"] %}
{% if (data[i]["reference"]) { %}
<br>{%= __("Reference") %}: {%= data[i]["reference"] %}
{% if (data[i]["reference_no"]) { %}
<br>{%= __("Reference") %}: {%= data[i]["reference_no"] %}
{% if (data[i]["ref_date"]) { %}
<br>{%= __("Reference Date") %}: {%= dateutil.str_to_user(data[i]["ref_date"]) %}
{% } %}
@@ -38,7 +38,7 @@
<tr>
<td></td>
<td></td>
<td>{%= data[i]["journal_entry"] %}</td>
<td>{%= data[i]["payment_entry"] %}</td>
<td style="text-align: right">{%= format_currency(data[i]["debit"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["credit"]) %}</td>
</tr>

View File

@@ -129,7 +129,7 @@ def get_entries(filters):
reference_no, reference_date as ref_date,
if(paid_to=%(account)s, received_amount, 0) as debit,
if(paid_from=%(account)s, paid_amount, 0) as credit,
posting_date, party as against_account, clearance_date,
posting_date, ifnull(party,if(paid_from=%(account)s,paid_to,paid_from)) as against_account, clearance_date,
if(paid_to=%(account)s, paid_to_account_currency, paid_from_account_currency) as account_currency
from `tabPayment Entry`
where

View File

@@ -0,0 +1 @@
{% include "accounts/report/financial_statements.html" %}

View File

@@ -0,0 +1 @@
{% include "accounts/report/financial_statements.html" %}

View File

@@ -50,6 +50,19 @@ frappe.query_reports["Trial Balance for Party"] = {
"options": ["Customer", "Supplier"],
"default": "Customer"
},
{
"fieldname":"party",
"label": __("Party"),
"fieldtype": "Dynamic Link",
"get_options": function() {
var party_type = frappe.query_report_filters_by_name.party_type.get_value();
var party = frappe.query_report_filters_by_name.party.get_value();
if(party && !party_type) {
frappe.throw(__("Please select Party Type first"));
}
return party_type;
}
},
{
"fieldname": "show_zero_values",
"label": __("Show zero values"),

View File

@@ -20,13 +20,23 @@ def execute(filters=None):
def get_data(filters, show_party_name):
party_name_field = "customer_name" if filters.get("party_type")=="Customer" else "supplier_name"
parties = frappe.get_all(filters.get("party_type"), fields = ["name", party_name_field], order_by="name")
party_filters = {"name": filters.get("party")} if filters.get("party") else {}
parties = frappe.get_all(filters.get("party_type"), fields = ["name", party_name_field],
filters = party_filters, order_by="name")
company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
opening_balances = get_opening_balances(filters)
balances_within_period = get_balances_within_period(filters)
data = []
total_debit, total_credit = 0, 0
# total_debit, total_credit = 0, 0
total_row = frappe._dict({
"opening_debit": 0,
"opening_credit": 0,
"debit": 0,
"credit": 0,
"closing_debit": 0,
"closing_credit": 0
})
for party in parties:
row = { "party": party.name }
if show_party_name:
@@ -45,11 +55,7 @@ def get_data(filters, show_party_name):
"debit": debit,
"credit": credit
})
# totals
total_debit += debit
total_credit += credit
# closing
closing_debit, closing_credit = toggle_debit_credit(opening_debit + debit, opening_credit + credit)
row.update({
@@ -57,6 +63,10 @@ def get_data(filters, show_party_name):
"closing_credit": closing_credit
})
# totals
for col in total_row:
total_row[col] += row.get(col)
row.update({
"currency": company_currency
})
@@ -69,13 +79,12 @@ def get_data(filters, show_party_name):
data.append(row)
# Add total row
if total_debit or total_credit:
data.append({
"party": "'" + _("Totals") + "'",
"debit": total_debit,
"credit": total_credit,
"currency": company_currency
})
total_row.update({
"party": "'" + _("Totals") + "'",
"currency": company_currency
})
data.append(total_row)
return data

View File

@@ -231,6 +231,7 @@ class PurchaseOrder(BuyingController):
"target_parent_dt": "Sales Order",
"target_dt": "Sales Order Item",
'target_field': 'ordered_qty',
"join_field": "sales_order_item",
"target_parent_field": ''
})

View File

@@ -371,6 +371,12 @@ def get_data():
"doctype": "GL Entry",
"is_query_report": True,
},
{
"type": "report",
"name": "Profitability Analysis",
"doctype": "GL Entry",
"is_query_report": True,
},
{
"type": "report",
"name": "Payment Period Based On Invoice Date",

View File

@@ -32,12 +32,13 @@ def get_filters_cond(doctype, filters, conditions):
# searches for active employees
def employee_query(doctype, txt, searchfield, start, page_len, filters):
conditions = []
return frappe.db.sql("""select name, employee_name from `tabEmployee`
where status = 'Active'
and docstatus < 2
and ({key} like %(txt)s
or employee_name like %(txt)s)
{mcond}
{fcond} {mcond}
order by
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
if(locate(%(_txt)s, employee_name), locate(%(_txt)s, employee_name), 99999),
@@ -45,6 +46,7 @@ def employee_query(doctype, txt, searchfield, start, page_len, filters):
name, employee_name
limit %(start)s, %(page_len)s""".format(**{
'key': searchfield,
'fcond': get_filters_cond(doctype, filters, conditions),
'mcond': get_match_cond(doctype)
}), {
'txt': "%%%s%%" % txt,

View File

@@ -207,6 +207,7 @@ def make_return_doc(doctype, source_name, target_doc=None):
target_doc.rejected_qty = -1* source_doc.rejected_qty
target_doc.qty = -1* source_doc.qty
target_doc.purchase_order = source_doc.purchase_order
target_doc.purchase_order_item = source_doc.purchase_order_item
target_doc.rejected_warehouse = source_doc.rejected_warehouse
elif doctype == "Purchase Invoice":
target_doc.received_qty = -1* source_doc.received_qty

View File

@@ -164,14 +164,18 @@ class SellingController(StockController):
frappe.throw(_("Maxiumm discount for Item {0} is {1}%").format(d.item_code, discount))
def validate_selling_price(self):
def throw_message(item_name, rate, ref_rate_field):
frappe.throw(_("""Selling price for item {0} is lower than its {1}. Selling price should be atleast {2}""")
.format(item_name, ref_rate_field, rate))
if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"):
return
for it in self.get("items"):
last_purchase_rate, is_stock_item = frappe.db.get_value("Item", it.name, ["last_purchase_rate", "is_stock_item"])
last_purchase_rate, is_stock_item = frappe.db.get_value("Item", it.item_code, ["last_purchase_rate", "is_stock_item"])
if flt(it.base_rate) < flt(last_purchase_rate):
throw(it.name, last_purchase_rate, "last purchase rate")
throw_message(it.item_name, last_purchase_rate, "last purchase rate")
last_valuation_rate = frappe.db.sql("""
SELECT valuation_rate FROM `tabStock Ledger Entry` WHERE item_code = %s
@@ -182,9 +186,6 @@ class SellingController(StockController):
if is_stock_item and flt(it.base_rate) < flt(last_valuation_rate):
throw_message(it.name, last_valuation_rate, "valuation rate")
def throw_message(item_name, rate, ref_rate_field):
frappe.throw(_("""Selling price for item {0} is lower than its {1}. Selling price should be atleast {2}""")
.format(item_name, ref_rate_field, rate))
def get_item_list(self):
il = []

View File

@@ -271,19 +271,19 @@ class StatusUpdater(Document):
%(update_modified)s
where name='%(name)s'""" % args)
# update field
if args.get('status_field'):
frappe.db.sql("""update `tab%(target_parent_dt)s`
set %(status_field)s = if(%(target_parent_field)s<0.001,
'Not %(keyword)s', if(%(target_parent_field)s>=99.99,
'Fully %(keyword)s', 'Partly %(keyword)s'))
where name='%(name)s'""" % args)
# update field
if args.get('status_field'):
frappe.db.sql("""update `tab%(target_parent_dt)s`
set %(status_field)s = if(%(target_parent_field)s<0.001,
'Not %(keyword)s', if(%(target_parent_field)s>=99.99,
'Fully %(keyword)s', 'Partly %(keyword)s'))
where name='%(name)s'""" % args)
if update_modified:
target = frappe.get_doc(args["target_parent_dt"], args["name"])
target.set_status(update=True)
target.notify_update()
notify_status(target)
if update_modified:
target = frappe.get_doc(args["target_parent_dt"], args["name"])
target.set_status(update=True)
target.notify_update()
notify_status(target)
def _update_modified(self, args, update_modified):
args['update_modified'] = ''

View File

@@ -23,20 +23,19 @@ frappe.ui.form.on("Opportunity", {
refresh: function(frm) {
var doc = frm.doc;
frm.events.enquiry_from(frm);
if(doc.status!=="Lost") {
if(doc.with_items){
frm.add_custom_button(__('Supplier Quotation'),
function() {
frm.trigger("make_supplier_quotation")
}, __("Make"));
frm.add_custom_button(__('Quotation'),
cur_frm.cscript.create_quotation, __("Make"));
frm.page.set_inner_btn_group_as_primary(__("Make"));
}
frm.add_custom_button(__('Quotation'),
cur_frm.cscript.create_quotation, __("Make"));
frm.page.set_inner_btn_group_as_primary(__("Make"));
if(doc.status!=="Quotation") {
frm.add_custom_button(__('Lost'),
cur_frm.cscript['Declare Opportunity Lost']);
@@ -61,9 +60,10 @@ erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({
this.frm.doc.enquiry_from = "Lead";
if(!this.frm.doc.status)
set_multiple(cdt, cdn, { status:'Draft' });
set_multiple(this.frm.doc.doctype, this.frm.doc.name, { status:'Open' });
if(!this.frm.doc.company && frappe.defaults.get_user_default("Company"))
set_multiple(cdt, cdn, { company:frappe.defaults.get_user_default("Company") });
set_multiple(this.frm.doc.doctype, this.frm.doc.name,
{ company:frappe.defaults.get_user_default("Company") });
this.setup_queries();
},

View File

@@ -39,6 +39,9 @@ class Opportunity(TransactionBase):
if not self.title:
self.title = self.customer_name
if not self.with_items:
self.items = []
def make_new_lead_if_required(self):

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

View File

@@ -7,7 +7,7 @@ Supplier Quotation.
#### Purchase Order Flow Chart
![Purchase Order]({{docs_base_url}}/assets/old_images/erpnext/purchase-order-f.jpg)
![Purchase Order]({{docs_base_url}}/assets/img/buying/buying_flow.png)
In ERPNext, you can also make a Purchase Order directly by going to:
@@ -39,6 +39,12 @@ which you collect from your Customer. In many regions, what you pay to your
government is only the difference between what you collect from your Customer
and what you pay to your Supplier. This is called Value Added Tax (VAT).
#### Add Taxes in Purchase Order
<img class="screenshot" alt="Purchase Order" src="{{docs_base_url}}/assets/img/buying/add_taxes_to_doc.png">
#### Show Tax break-up
<img class="screenshot" alt="Purchase Order" src="{{docs_base_url}}/assets/img/buying/show_tax_breakup.png">
For example you buy Items worth X and sell them for 1.3X. So your Customer
pays 1.3 times the tax you pay your Supplier. Since you have already paid tax
to your Supplier for X, what you owe your government is only the tax on 0.3X.
@@ -49,7 +55,7 @@ Ideally you must create two Accounts for each type of VAT you pay and collect,
effect. Please contact your accountant if you need more help or post a query
on our forums!
#### Purchase UOM and Stock UOM Conversion
@@ -82,5 +88,5 @@ __Step 5:__ Notice that the stock quantity will be updated accordingly.
__Step 6:__ Save and Submit the Form.
{next}

View File

@@ -8,7 +8,7 @@ You can make a supplier quotation from a Material Request
#### Supplier Quotation Flow-Chart
![Supplier Quotation]({{docs_base_url}}/assets/old_images/erpnext/supplier-quotation-f.jpg)
![Supplier Quotation]({{docs_base_url}}/assets/img/buying/buying_flow.png)
You can also make a Supplier Quotation directly from:
@@ -23,11 +23,22 @@ usually send out a message (Request for Quote) to various Suppliers. In
many cases, especially if you have centralized buying, you may want to record
all the quotes so that
* You can easily compare prices in the future
* You can easily compare prices in the future
* Audit whether all Suppliers were given the opportunity to quote.
Supplier Quotations are not necessary for most small businesses. Always
evaluate the cost of collecting information to the value it really provides!
You could only do this for high value items.
#### Taxes
If your Supplier is going to charge you additional taxes or charge like a shipping or insurance charge, you can add it here. It will help you to accurately track your costs. Also, if some of these charges add to the value of the product you will have to mention them in the Taxes table. You can also use templates for your taxes. For more information on setting up your taxes see the Purchase Taxes and Charges Template.
You can select relevant tax by going to "Taxes and Charges" section and adding an entry to the table as shown below,
<img class="screenshot" alt="Supplier Quotation" src="{{docs_base_url}}/assets/img/buying/add_taxes_to_doc.png">
Besides, in case of multiple items you can keep track of taxes on each by clicking "Show tax break-up"
<img class="screenshot" alt="Supplier Quotation" src="{{docs_base_url}}/assets/img/buying/show_tax_breakup.png">
{next}

View File

@@ -212,3 +212,5 @@ bot_parsers = [
]
get_site_info = 'erpnext.utilities.get_site_info'
payment_gateway_enabled = "erpnext.accounts.utils.create_payment_gateway_and_account"

View File

@@ -1,7 +1,7 @@
{
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 0,
"allow_rename": 1,
"autoname": "field:expense_type",
"beta": 0,
"creation": "2012-03-27 14:35:55",
@@ -10,11 +10,13 @@
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 0,
"engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "expense_type",
"fieldtype": "Data",
"hidden": 0,
@@ -41,6 +43,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "description",
"fieldtype": "Small Text",
"hidden": 0,
@@ -68,6 +71,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "accounts",
"fieldtype": "Table",
"hidden": 0,
@@ -102,7 +106,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-07-18 12:36:10.096252",
"modified": "2016-11-07 11:54:10.936716",
"modified_by": "Administrator",
"module": "HR",
"name": "Expense Claim Type",
@@ -118,6 +122,7 @@
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
@@ -138,6 +143,7 @@
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 0,
"read": 1,

View File

@@ -22,7 +22,7 @@ class ProcessPayroll(Document):
sal_struct = frappe.db.sql("""
select name from `tabSalary Structure`
where docstatus != 2 and company = %(company)s and
where docstatus != 2 and is_active = 'Yes' and company = %(company)s and
ifnull(salary_slip_based_on_timesheet,0) = %(salary_slip_based_on_timesheet)s""",
{"company": self.company, "salary_slip_based_on_timesheet":self.salary_slip_based_on_timesheet})
@@ -51,8 +51,8 @@ class ProcessPayroll(Document):
def get_joining_releiving_condition(self):
cond = """
and ifnull(t1.date_of_joining, '0000-00-00') <= '%(from_date)s'
and ifnull(t1.relieving_date, '2199-12-31') >= '%(to_date)s'
and ifnull(t1.date_of_joining, '0000-00-00') <= '%(to_date)s'
and ifnull(t1.relieving_date, '2199-12-31') >= '%(from_date)s'
""" % {"from_date": self.from_date, "to_date": self.to_date}
return cond

View File

@@ -31,6 +31,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -58,8 +59,9 @@
"print_hide_if_no_value": 0,
"print_width": "120px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
@@ -86,6 +88,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -112,6 +115,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -137,6 +141,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -164,6 +169,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -182,7 +188,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-08-31 08:08:47.359578",
"modified": "2016-11-16 12:44:37.733773",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Component",
@@ -199,6 +205,7 @@
"export": 1,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,

View File

@@ -10,7 +10,6 @@ from frappe import _
class SalaryComponent(Document):
def validate(self):
self.validate_abbr()
def validate_abbr(self):
if not self.salary_component_abbr:
@@ -21,8 +20,5 @@ class SalaryComponent(Document):
if self.get('__islocal') and len(self.salary_component_abbr) > 5:
frappe.throw(_("Abbreviation cannot have more than 5 characters"))
if not self.salary_component_abbr.strip():
frappe.throw(_("Abbreviation is mandatory"))
if frappe.db.sql("select salary_component_abbr from `tabSalary Component` where name!=%s and salary_component_abbr=%s", (self.name, self.salary_component_abbr)):
frappe.throw(_("Abbreviation already used for another salary component"))

View File

@@ -28,7 +28,15 @@ frappe.ui.form.on('Salary Structure', {
type: "deduction"
}
}
})
});
frm.set_query("employee", "employees", function(doc) {
return {
query: "erpnext.controllers.queries.employee_query",
filters: {
company: doc.company
}
}
});
},
refresh: function(frm) {
@@ -182,11 +190,3 @@ frappe.ui.form.on('Salary Detail', {
calculate_totals(frm.doc);
}
})
frappe.ui.form.on('Salary Structure Employee', {
onload: function(frm) {
frm.set_query("employee","employees", function(doc,cdt,cdn) {
return{ query: "erpnext.controllers.queries.employee_query" }
})
}
});

View File

@@ -8,32 +8,32 @@ from frappe import msgprint, _
def execute(filters=None):
if not filters: filters = {}
salary_slips = get_salary_slips(filters)
columns, earning_types, ded_types = get_columns(salary_slips)
ss_earning_map = get_ss_earning_map(salary_slips)
ss_ded_map = get_ss_ded_map(salary_slips)
data = []
for ss in salary_slips:
row = [ss.name, ss.employee, ss.employee_name, ss.branch, ss.department, ss.designation,
ss.company, ss.month, ss.leave_withut_pay, ss.payment_days]
for e in earning_types:
row.append(ss_earning_map.get(ss.name, {}).get(e))
row += [ss.arrear_amount, ss.leave_encashment_amount, ss.gross_pay]
for d in ded_types:
row.append(ss_ded_map.get(ss.name, {}).get(d))
row += [ss.total_deduction, ss.net_pay]
data.append(row)
return columns, data
def get_columns(salary_slips):
columns = [
_("Salary Slip ID") + ":Link/Salary Slip:150",_("Employee") + ":Link/Employee:120", _("Employee Name") + "::140", _("Branch") + ":Link/Branch:120",
@@ -41,7 +41,7 @@ def get_columns(salary_slips):
_("Company") + ":Link/Company:120", _("Month") + "::80", _("Leave Without Pay") + ":Float:130",
_("Payment Days") + ":Float:120"
]
salary_components = {_("Earning"): [], _("Deduction"): []}
for component in frappe.db.sql("""select distinct sd.salary_component, sc.type
@@ -61,47 +61,47 @@ def get_salary_slips(filters):
conditions, filters = get_conditions(filters)
salary_slips = frappe.db.sql("""select * from `tabSalary Slip` where docstatus = 1 %s
order by employee, month""" % conditions, filters, as_dict=1)
if not salary_slips:
msgprint(_("No salary slip found for month: ") + cstr(filters.get("month")) +
_(" and year: ") + cstr(filters.get("fiscal_year")), raise_exception=1)
frappe.throw(_("No salary slip found for month {0} and year {1}").format(
filters.get("month"), filters.get("fiscal_year")))
return salary_slips
def get_conditions(filters):
conditions = ""
if filters.get("month"):
month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov",
month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov",
"Dec"].index(filters["month"]) + 1
filters["month"] = month
conditions += " and month = %(month)s"
if filters.get("fiscal_year"): conditions += " and fiscal_year = %(fiscal_year)s"
if filters.get("company"): conditions += " and company = %(company)s"
if filters.get("employee"): conditions += " and employee = %(employee)s"
return conditions, filters
def get_ss_earning_map(salary_slips):
ss_earnings = frappe.db.sql("""select parent, salary_component, amount
ss_earnings = frappe.db.sql("""select parent, salary_component, amount
from `tabSalary Detail` where parent in (%s)""" %
(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]), as_dict=1)
ss_earning_map = {}
for d in ss_earnings:
ss_earning_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, [])
ss_earning_map[d.parent][d.salary_component] = flt(d.amount)
return ss_earning_map
def get_ss_ded_map(salary_slips):
ss_deductions = frappe.db.sql("""select parent, salary_component, amount
ss_deductions = frappe.db.sql("""select parent, salary_component, amount
from `tabSalary Detail` where parent in (%s)""" %
(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]), as_dict=1)
ss_ded_map = {}
for d in ss_deductions:
ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, [])
ss_ded_map[d.parent][d.salary_component] = flt(d.amount)
return ss_ded_map

View File

@@ -816,7 +816,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2016-08-17 05:35:34.331954",
"modified": "2016-11-16 05:35:34.331954",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Planning Tool",

View File

@@ -486,7 +486,9 @@ class ProductionPlanningTool(Document):
"qty": requested_qty,
"schedule_date": add_days(nowdate(), cint(item_wrapper.lead_time_days)),
"warehouse": self.purchase_request_for_warehouse,
"sales_order": sales_order if sales_order!="No Sales Order" else None
"sales_order": sales_order if sales_order!="No Sales Order" else None,
"project": frappe.db.get_value("Sales Order", sales_order, "project") \
if sales_order!="No Sales Order" else None
})
material_request.flags.ignore_permissions = 1

View File

@@ -1,17 +1,19 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
//--------- ONLOAD -------------
cur_frm.cscript.onload = function(doc, cdt, cdn) {
frappe.call({
type:"GET",
method:"erpnext.manufacturing.doctype.workstation.workstation.get_default_holiday_list",
callback: function(r) {
if(!r.exe && r.message){
cur_frm.set_value("holiday_list", r.message);
}
frappe.ui.form.on("Workstation", {
onload: function(frm) {
if(frm.is_new())
{
frappe.call({
type:"GET",
method:"erpnext.manufacturing.doctype.workstation.workstation.get_default_holiday_list",
callback: function(r) {
if(!r.exe && r.message){
cur_frm.set_value("holiday_list", r.message);
}
}
})
}
})
}
}
})

View File

@@ -346,4 +346,7 @@ execute:frappe.db.sql("update `tabStock Entry` set total_amount = null where pur
erpnext.patches.v7_0.repost_gle_for_pi_with_update_stock #2016-11-01
erpnext.patches.v7_1.add_account_user_role_for_timesheet
erpnext.patches.v7_0.set_base_amount_in_invoice_payment_table
erpnext.patches.v7_1.update_invoice_status
erpnext.patches.v7_1.update_invoice_status
erpnext.patches.v7_0.po_status_issue_for_pr_return
erpnext.patches.v7_1.update_missing_salary_component_type
erpnext.patches.v7_0.update_autoname_field

View File

@@ -6,6 +6,8 @@ from erpnext.patches.v7_0.migrate_schools_to_erpnext import reload_doctypes_for_
def execute():
'''hide new style icons if old ones are set'''
frappe.reload_doc('desk', 'doctype', 'desktop_icon')
reload_doctypes_for_schools_icons()
sync_desktop_icons()

View File

@@ -0,0 +1,36 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
parent_list = []
count = 0
for data in frappe.db.sql("""
select
`tabPurchase Receipt Item`.purchase_order, `tabPurchase Receipt Item`.name,
`tabPurchase Receipt Item`.item_code, `tabPurchase Receipt Item`.idx,
`tabPurchase Receipt Item`.parent
from
`tabPurchase Receipt Item`, `tabPurchase Receipt`
where
`tabPurchase Receipt Item`.parent = `tabPurchase Receipt`.name and
`tabPurchase Receipt Item`.purchase_order_item is null and
`tabPurchase Receipt Item`.purchase_order is not null and
`tabPurchase Receipt`.is_return = 1""", as_dict=1):
name = frappe.db.get_value('Purchase Order Item',
{'item_code': data.item_code, 'parent': data.purchase_order, 'idx': data.idx}, 'name')
if name:
frappe.db.set_value('Purchase Receipt Item', data.name, 'purchase_order_item', name, update_modified=False)
parent_list.append(data.parent)
count +=1
if count % 200 == 0:
frappe.db.commit()
if len(parent_list) > 0:
for parent in set(parent_list):
doc = frappe.get_doc('Purchase Receipt', parent)
doc.update_qty(update_modified=False)

View File

@@ -9,6 +9,8 @@ def execute():
if not cint(frappe.defaults.get_global_default("auto_accounting_for_stock")):
return
frappe.reload_doctype("Purchase Invoice")
for pi in frappe.db.sql("""select name from `tabPurchase Invoice`
where update_stock=1 and docstatus=1 order by posting_date asc""", as_dict=1):

View File

@@ -6,7 +6,8 @@ def execute():
si_list = frappe.db.sql("""
select distinct parent
from `tabSales Invoice Payment`
where docstatus!=2 and amount != 0 and base_amount = 0
where docstatus!=2 and parenttype = 'Sales Invoice'
and amount != 0 and base_amount = 0
""")
count = 0
@@ -20,4 +21,4 @@ def execute():
count +=1
if count % 200 == 0:
frappe.db.commit()
frappe.db.commit()

View File

@@ -0,0 +1,14 @@
# 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
def execute():
doctypes = frappe.db.sql(""" select name, autoname from `tabDocType`
where autoname like 'field:%' and allow_rename = 1""", as_dict=1)
for doctype in doctypes:
fieldname = doctype.autoname.split(":")[1]
if fieldname:
frappe.db.sql(""" update `tab%s` set %s = name """%(doctype.name, fieldname))

View File

@@ -14,6 +14,4 @@ def execute():
employee.prefered_contact_email = "User ID"
employee.prefered_email = employee.user_id
employee.flags.ignore_mandatory = True
employee.flags.ignore_validate = True
employee.save()
employee.db_update()

View File

@@ -0,0 +1,48 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr
'''
Some components do not have type set, try and guess whether they turn up in
earnings or deductions in existing salary slips
'''
def execute():
frappe.reload_doc("accounts", "doctype", "salary_component_account")
for s in frappe.db.sql('''select name, type, salary_component_abbr from `tabSalary Component`
where ifnull(type, "")="" or ifnull(salary_component_abbr, "") = ""''', as_dict=1):
component = frappe.get_doc('Salary Component', s.name)
# guess
if not s.type:
guess = frappe.db.sql('''select
parentfield from `tabSalary Detail`
where salary_component=%s limit 1''', s.name)
if guess:
component.type = 'Earning' if guess[0][0]=='earnings' else 'Deduction'
else:
component.type = 'Deduction'
if not s.salary_component_abbr:
abbr = ''.join([c[0] for c in component.salary_component.split()]).upper()
abbr_count = frappe.db.sql("""
select
count(name)
from
`tabSalary Component`
where
salary_component_abbr = %s or salary_component_abbr like %s
""", (abbr, abbr + "-%%"))
if abbr_count and abbr_count[0][0] > 0:
abbr = abbr + "-" + cstr(abbr_count[0][0])
component.salary_component_abbr = abbr
component.save()

View File

@@ -2,6 +2,7 @@ import frappe
def execute():
frappe.reload_doctype('Role')
frappe.reload_doctype('User')
for role_name in ('Customer', 'Supplier', 'Student'):
if frappe.db.exists('Role', role_name):
frappe.db.set_value('Role', role_name, 'desk_access', 0)

View File

@@ -181,7 +181,6 @@
}
.cart-dropdown-container .cart-items-dropdown {
max-height: 350px;
overflow: auto;
}
.cart-dropdown-container .cart-items-dropdown .cart-dropdown {
display: block;

View File

@@ -65,7 +65,7 @@ $.extend(shopping_cart, {
var cart_count = getCookie("cart_count");
if(cart_count) {
$(".shopping-cart").toggleClass('hidden', true);
$(".shopping-cart").toggleClass('hidden', false);
}
var $cart = $('.cart-icon');

View File

@@ -233,7 +233,6 @@
.cart-items-dropdown {
max-height: 350px;
overflow: auto;
}
.cart-items-dropdown .cart-dropdown {

View File

@@ -10,7 +10,7 @@ def get_data():
'items': ['Student Log', 'Student Group', 'Student Attendance']
},
{
'items': ['Program Enrollment', 'Fees', 'Assessment', 'Guardian']
'items': ['Program Enrollment', 'Fees', 'Assessment']
}
]
}

View File

@@ -23,7 +23,7 @@ class StudentAdmission(WebsiteGenerator):
context.parents = [{'name': 'admissions', 'title': _('All Student Admissions') }]
def get_title(self):
return _("Admissions for {0}").format(self.academic_term)
return _("Admissions for {0}").format(self.academic_year)
def get_list_context(context):
context.title = _("Student Admissions")

View File

@@ -920,7 +920,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2016-10-10 06:19:19.319038",
"modified": "2016-11-17 10:26:13.225135",
"modified_by": "Administrator",
"module": "Schools",
"name": "Student Applicant",
@@ -947,27 +947,6 @@
"share": 1,
"submit": 1,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 1,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 0,
"role": "Guest",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
}
],
"quick_entry": 1,

View File

@@ -372,7 +372,7 @@
"in_list_view": 0,
"label": "Customer's Purchase Order",
"length": 0,
"no_copy": 1,
"no_copy": 0,
"oldfieldname": "po_no",
"oldfieldtype": "Data",
"permlevel": 0,
@@ -403,7 +403,7 @@
"in_list_view": 0,
"label": "Customer's Purchase Order Date",
"length": 0,
"no_copy": 1,
"no_copy": 0,
"oldfieldname": "po_date",
"oldfieldtype": "Date",
"permlevel": 0,
@@ -3226,7 +3226,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-11-05 08:09:08.921026",
"modified": "2016-11-14 16:07:45.817880",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",

View File

@@ -66,27 +66,42 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
});
}
if(this.frm.fields_dict["packed_items"] &&
this.frm.fields_dict["packed_items"].grid.get_field('batch_no')) {
this.frm.set_query("batch_no", "packed_items", function(doc, cdt, cdn) {
return me.set_query_for_batch(doc, cdt, cdn)
});
}
if(this.frm.fields_dict["items"].grid.get_field('batch_no')) {
this.frm.set_query("batch_no", "items", function(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
if(!item.item_code) {
frappe.throw(__("Please enter Item Code to get batch no"));
} else {
filters = {
'item_code': item.item_code,
'posting_date': me.frm.doc.posting_date || frappe.datetime.nowdate(),
}
if(item.warehouse) filters["warehouse"] = item.warehouse
return {
query : "erpnext.controllers.queries.get_batch_no",
filters: filters
}
}
return me.set_query_for_batch(doc, cdt, cdn)
});
}
},
set_query_for_batch: function(doc, cdt, cdn) {
// Show item's batches in the dropdown of batch no
var me = this;
var item = frappe.get_doc(cdt, cdn);
if(!item.item_code) {
frappe.throw(__("Please enter Item Code to get batch no"));
} else {
filters = {
'item_code': item.item_code,
'posting_date': me.frm.doc.posting_date || frappe.datetime.nowdate(),
}
if(item.warehouse) filters["warehouse"] = item.warehouse
return {
query : "erpnext.controllers.queries.get_batch_no",
filters: filters
}
}
},
refresh: function() {
this._super();
this.frm.toggle_display("customer_name",

View File

@@ -14,7 +14,8 @@ class NamingSeriesNotSetError(frappe.ValidationError): pass
class NamingSeries(Document):
def get_transactions(self, arg=None):
doctypes = list(set(frappe.db.sql_list("""select parent
from `tabDocField` where fieldname='naming_series'""")
from `tabDocField` df where fieldname='naming_series' and
exists(select * from `tabDocPerm` dp, `tabRole` role where dp.role = role.name and dp.parent = df.parent and not role.disabled)""")
+ frappe.db.sql_list("""select dt from `tabCustom Field`
where fieldname='naming_series'""")))

View File

@@ -68,7 +68,7 @@ def setup_complete(args=None):
frappe.message_log.pop()
pass
def create_fiscal_year_and_company(args):
if (args.get('fy_start_date')):
curr_fiscal_year = get_fy_details(args.get('fy_start_date'), args.get('fy_end_date'))
@@ -244,12 +244,12 @@ def get_fy_details(fy_start_date, fy_end_date):
else:
fy = cstr(start_year) + '-' + cstr(start_year + 1)
return fy
def create_sales_tax(args):
country_wise_tax = get_country_wise_tax(args.get("country"))
if country_wise_tax and len(country_wise_tax) > 0:
for sales_tax, tax_data in country_wise_tax.items():
make_tax_account_and_template(args.get("company_name").strip(),
make_tax_account_and_template(args.get("company_name").strip(),
tax_data.get('account_name'), tax_data.get('tax_rate'), sales_tax)
def get_country_wise_tax(country):
@@ -267,7 +267,7 @@ def create_taxes(args):
account_name = args.get("tax_" + str(i))
make_tax_account_and_template(args.get("company_name").strip(), account_name, tax_rate)
def make_tax_account_and_template(company, account_name, tax_rate, template_name=None):
try:
account = make_tax_account(company, account_name, tax_rate)
@@ -280,14 +280,14 @@ def make_tax_account_and_template(company, account_name, tax_rate, template_name
raise
except RootNotEditable, e:
pass
def get_tax_account_group(company):
tax_group = frappe.db.get_value("Account",
tax_group = frappe.db.get_value("Account",
{"account_name": "Duties and Taxes", "is_group": 1, "company": company})
if not tax_group:
tax_group = frappe.db.get_value("Account", {"is_group": 1, "root_type": "Liability",
tax_group = frappe.db.get_value("Account", {"is_group": 1, "root_type": "Liability",
"account_type": "Tax", "company": company})
return tax_group
def make_tax_account(company, account_name, tax_rate):
@@ -308,7 +308,7 @@ def make_tax_account(company, account_name, tax_rate):
def make_sales_and_purchase_tax_templates(account, template_name=None):
if not template_name:
template_name = account.name
sales_tax_template = {
"doctype": "Sales Taxes and Charges Template",
"title": template_name,
@@ -548,35 +548,50 @@ def create_academic_term():
academic_term = frappe.new_doc("Academic Term")
academic_term.academic_year = y
academic_term.term_name = t
academic_term.save()
try:
academic_term.save()
except frappe.DuplicateEntryError:
pass
def create_academic_year():
ac = ["2013-14", "2014-15", "2015-16", "2016-17", "2017-18"]
for d in ac:
academic_year = frappe.new_doc("Academic Year")
academic_year.academic_year_name = d
academic_year.save()
try:
academic_year.save()
except frappe.DuplicateEntryError:
pass
def create_program(args):
for i in xrange(1,6):
if args.get("program_" + str(i)):
program = frappe.new_doc("Program")
program.program_name = args.get("program_" + str(i))
program.save()
try:
program.save()
except frappe.DuplicateEntryError:
pass
def create_course(args):
for i in xrange(1,6):
if args.get("course_" + str(i)):
course = frappe.new_doc("Course")
course.course_name = args.get("course_" + str(i))
course.save()
try:
course.save()
except frappe.DuplicateEntryError:
pass
def create_instructor(args):
for i in xrange(1,6):
if args.get("instructor_" + str(i)):
instructor = frappe.new_doc("Instructor")
instructor.instructor_name = args.get("instructor_" + str(i))
instructor.save()
try:
instructor.save()
except frappe.DuplicateEntryError:
pass
def create_room(args):
for i in xrange(1,6):
@@ -584,6 +599,9 @@ def create_room(args):
room = frappe.new_doc("Room")
room.room_name = args.get("room_" + str(i))
room.seating_capacity = args.get("room_capacity_" + str(i))
room.save()
try:
room.save()
except frappe.DuplicateEntryError:
pass

View File

@@ -31,6 +31,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -60,6 +61,7 @@
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1,
@@ -89,6 +91,7 @@
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -114,6 +117,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -139,6 +143,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -165,6 +170,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -193,6 +199,7 @@
"print_hide_if_no_value": 0,
"print_width": "300px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -219,6 +226,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -245,6 +253,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -272,6 +281,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -297,6 +307,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -325,6 +336,7 @@
"print_hide_if_no_value": 0,
"print_width": "100px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -355,6 +367,7 @@
"print_hide_if_no_value": 0,
"print_width": "100px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -380,6 +393,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -409,6 +423,7 @@
"print_hide_if_no_value": 0,
"print_width": "50px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
@@ -439,6 +454,7 @@
"print_hide_if_no_value": 0,
"print_width": "100px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -466,6 +482,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -495,6 +512,7 @@
"print_hide_if_no_value": 0,
"print_width": "100px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -521,6 +539,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -549,6 +568,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -576,6 +596,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -603,6 +624,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -627,6 +649,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -656,6 +679,7 @@
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -686,6 +710,7 @@
"print_hide_if_no_value": 0,
"print_width": "100px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -711,6 +736,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -740,6 +766,7 @@
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -770,6 +797,7 @@
"print_hide_if_no_value": 0,
"print_width": "100px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -797,6 +825,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -822,6 +851,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -849,6 +879,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -876,6 +907,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -901,6 +933,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -928,6 +961,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -955,6 +989,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -980,6 +1015,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1009,6 +1045,7 @@
"print_hide_if_no_value": 0,
"print_width": "100px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1039,6 +1076,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1066,6 +1104,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1094,6 +1133,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1122,6 +1162,7 @@
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1151,6 +1192,7 @@
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1181,6 +1223,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1210,6 +1253,7 @@
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1238,6 +1282,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1262,6 +1307,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1288,6 +1334,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1316,6 +1363,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1337,12 +1385,13 @@
"in_list_view": 0,
"label": "Against Sales Order",
"length": 0,
"no_copy": 0,
"no_copy": 1,
"options": "Sales Order",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1363,12 +1412,13 @@
"in_list_view": 0,
"label": "Against Sales Invoice",
"length": 0,
"no_copy": 0,
"no_copy": 1,
"options": "Sales Invoice",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1397,6 +1447,7 @@
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1,
@@ -1424,6 +1475,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1452,6 +1504,7 @@
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1480,6 +1533,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1507,6 +1561,7 @@
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -1524,7 +1579,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-11-01 13:01:29.621272",
"modified": "2016-11-23 12:33:37.728117",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note Item",

View File

@@ -141,7 +141,7 @@ class Item(WebsiteGenerator):
def make_route(self):
if not self.route:
return frappe.db.get_value('Item Group', self.item_group, 'route') + '/' + self.scrub(self.item_name)
return cstr(frappe.db.get_value('Item Group', self.item_group, 'route')) + '/' + self.scrub(self.item_name)
def get_parents(self, context):
item_group, route = frappe.db.get_value('Item Group', self.item_group, ['name', 'route'])

View File

@@ -372,6 +372,7 @@ def raise_production_orders(material_request):
mr= frappe.get_doc("Material Request", material_request)
errors =[]
production_orders = []
default_wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
for d in mr.items:
if (d.qty - d.ordered_qty) >0:
if frappe.db.get_value("BOM", {"item": d.item_code, "is_default": 1}):
@@ -379,6 +380,7 @@ def raise_production_orders(material_request):
prod_order.production_item = d.item_code
prod_order.qty = d.qty - d.ordered_qty
prod_order.fg_warehouse = d.warehouse
prod_order.wip_warehouse = default_wip_warehouse
prod_order.description = d.description
prod_order.stock_uom = d.uom
prod_order.expected_delivery_date = d.schedule_date

View File

@@ -16,7 +16,7 @@ class PackedItem(Document):
def get_product_bundle_items(item_code):
return frappe.db.sql("""select t1.item_code, t1.qty, t1.uom, t1.description
from `tabProduct Bundle Item` t1, `tabProduct Bundle` t2
where t2.new_item_code=%s and t1.parent = t2.name""", item_code, as_dict=1)
where t2.new_item_code=%s and t1.parent = t2.name order by t1.idx""", item_code, as_dict=1)
def get_packing_item_details(item):
return frappe.db.sql("""select item_name, description, stock_uom from `tabItem`

View File

@@ -8,6 +8,7 @@ frappe.query_reports["Stock Balance"] = {
"label": __("From Date"),
"fieldtype": "Date",
"width": "80",
"reqd": 1,
"default": sys_defaults.year_start_date,
},
{
@@ -15,6 +16,7 @@ frappe.query_reports["Stock Balance"] = {
"label": __("To Date"),
"fieldtype": "Date",
"width": "80",
"reqd": 1,
"default": frappe.datetime.get_today()
},
{

View File

@@ -3,7 +3,7 @@
{% block title %} {{ title }} {% endblock %}
{% block breadcrumbs %}
{% include "templates/includes/breadcrumbs.html" %}
{% include "templates/includes/breadcrumbs.html" %}
{% endblock %}
{% block page_content %}
@@ -25,17 +25,17 @@
{{ _("Item Code") }}: <span itemprop="productID">{{ variant and variant.name or name }}</span></p>
<br>
<div class="item-attribute-selectors">
{% if has_variants %}
{% for d in attributes %}
{% if has_variants %}
{% for d in attributes %}
{% if attribute_values[d.attribute] -%}
<div class="item-view-attribute {% if (attribute_values[d.attribute] | len)==1 -%} hidden {%- endif %}"
style="margin-bottom: 10px;">
<h6 class="text-muted">{{ _(d.attribute) }}</h6>
<select class="form-control"
style="max-width: 140px"
data-attribute="{{ d.attribute }}">
<div class="item-view-attribute {% if (attribute_values[d.attribute] | len)==1 -%} hidden {%- endif %}"
style="margin-bottom: 10px;">
<h6 class="text-muted">{{ _(d.attribute) }}</h6>
<select class="form-control"
style="max-width: 140px"
data-attribute="{{ d.attribute }}">
{% for value in attribute_values[d.attribute] %}
<option value="{{ value }}"
<option value="{{ value }}"
{% if selected_attributes and selected_attributes[d.attribute]==value -%}
selected
{%- elif disabled_attributes and value in disabled_attributes.get(d.attribute, []) -%}
@@ -43,12 +43,12 @@
{%- endif %}>
{{ _(value) }}
</option>
{% endfor %}
</select>
</div>
{% endfor %}
</select>
</div>
{%- endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
</div>
<br>
<div style="min-height: 100px; margin: 10px 0;">
@@ -56,18 +56,17 @@
<h4 class="item-price" itemprop="price"></h4>
<div class="item-stock" itemprop="availability"></div>
</div>
<div class="item-cart hide">
<div id="item-add-to-cart">
<button class="btn btn-primary btn-sm">
{{ _("Add to Cart") }}</button>
</div>
<div id="item-update-cart"
style="display: none;
padding-left: 0px; padding-right: 0px;
padding-top: 10px;">
<a href="/cart">{{ _("Goto Cart") }}</a>
</div>
</div>
<div class="item-cart hide">
<div id="item-add-to-cart">
<button class="btn btn-primary btn-sm">
{{ _("Add to Cart") }}</button>
</div>
<div id="item-update-cart" style="display: none;">
<a href="/cart" class='btn btn-sm btn-default'>
<i class='octicon octicon-check'></i>
{{ _("View in Cart") }}</a>
</div>
</div>
</div>
</div>
</div>
@@ -101,10 +100,10 @@
<script>
{% include "templates/includes/product_page.js" %}
{% if variant_info %}
window.variant_info = {{ variant_info }};
{% else %}
window.variant_info = null;
{% endif %}
{% if variant_info %}
window.variant_info = {{ variant_info }};
{% else %}
window.variant_info = null;
{% endif %}
</script>
{% endblock %}

View File

@@ -1,6 +1,6 @@
<div class="cart-dropdown-container">
<div id="cart-error" class="alert alert-danger"
style="display: none;"></div>
style="display: none;"></div>
<div class="row cart-items-dropdown cart-item-header text-muted">
<div class="col-sm-6 col-xs-6 h6 text-uppercase">
{{ _("Item") }}
@@ -9,13 +9,13 @@
{{ _("Price") }}
</div>
</div>
{% if doc.items %}
<div class="cart-items-dropdown">
{% include "templates/includes/cart/cart_items_dropdown.html" %}
</div>
<div class="checkout-btn">
<a href="/cart" class="btn btn-block btn-primary">{{ _("Checkout") }}</a>
<a href="/cart" class="btn btn-block btn-primary">{{ _("Checkout") }}</a>
</div>
{% else %}
<p>{{ _("Cart is Empty") }}</p>

View File

@@ -7,7 +7,6 @@
</div>
<div class="col-sm-4 col-xs-4 text-right col-amount">
{{ d.get_formatted("amount") }}
</div>
</div>
{% endfor %}

View File

@@ -1,7 +1,12 @@
{% macro product_image_square(website_image, css_class="") %}
{% if website_image -%} <meta itemprop="image" content="{{ frappe.utils.quoted(website_image) | abs_url }}"></meta>{%- endif %}
<div class="product-image product-image-square {% if not website_image -%} missing-image {%- endif %} {{ css_class }}"
{% if website_image -%} style="background-image: url('{{ frappe.utils.quoted(website_image) | abs_url }}');" {%- endif %}>
{% if website_image -%}
<meta itemprop="image" content="{{ frappe.utils.quoted(website_image) | abs_url }}"></meta>
{%- endif %}
<div class="product-image product-image-square
{% if not website_image -%} missing-image {%- endif %} {{ css_class }}"
{% if website_image -%}
style="background-image: url('{{ frappe.utils.quoted(website_image) | abs_url }}');"
{%- endif %}>
</div>
{% endmacro %}

View File

@@ -2,7 +2,7 @@
{% block navbar_right_extension %}
<li class="shopping-cart hidden">
<div class="cart-icon small">
<div class="cart-icon">
<a class="dropdown-toggle" href="#" data-toggle="dropdown" id="navLogin">
Cart <span class="badge-wrapper" id="cart-count"></span>
</a>

View File

@@ -4,7 +4,7 @@
<div class="row item_name_and_description">
<div class="col-xs-4 col-sm-2 order-image-col">
<div class="order-image">
{{ product_image_square(d.image) }}
{{ product_image_square(d.thumbnail or d.image) }}
</div>
</div>
<div class="col-xs-8 col-sm-10">
@@ -13,23 +13,24 @@
</div>
</div>
{% endmacro %}
{% macro item_name_and_description_cart(d) %}
<div class="row item_name_dropdown">
<div class="col-xs-4 col-sm-4 order-image-col">
<div class="order-image">
{{ product_image_square(d.image) }}
{{ product_image_square(d.thumbnail or d.image) }}
</div>
</div>
<div class="col-xs-8 col-sm-8">
{{ d.item_code|truncate(25) }}
{{ d.item_code|truncate(25) }}
<div class="input-group number-spinner">
<span class="input-group-btn">
<button class="btn btn-default cart-btn" data-dir="dwn">
</button>
</span>
<input class="form-control text-right cart-qty"
value = "{{ d.get_formatted('qty') }}"
data-item-code="{{ d.item_code }}">
<input class="form-control text-right cart-qty"
value = "{{ d.get_formatted('qty') }}"
data-item-code="{{ d.item_code }}">
<span class="input-group-btn">
<button class="btn btn-default cart-btn" data-dir="up">
+</button>

View File

@@ -10,15 +10,43 @@ from frappe.utils import cint, formatdate
@frappe.whitelist(allow_guest=True)
def send_message(subject="Website Query", message="", sender="", status="Open"):
from frappe.www.contact import send_message as website_send_message
lead = customer = None
website_send_message(subject, message, sender)
customer = frappe.db.get_value('Contact', dict(email_id=sender), 'customer')
if not customer:
lead = frappe.db.get_value('Lead', dict(email_id=sender))
if not lead:
new_lead = frappe.get_doc(dict(
doctype='Lead',
email_id = sender,
lead_name = sender.split('@')[0].title()
)).insert(ignore_permissions=True)
opportunity = frappe.get_doc(dict(
doctype='Opportunity',
enquiry_from = 'Customer' if customer else 'Lead',
status = 'Open',
title = subject,
to_discuss=message
))
if customer:
opportunity.customer = customer
else:
opportunity.lead = new_lead.name
opportunity.insert(ignore_permissions=True)
comm = frappe.get_doc({
"doctype":"Communication",
"subject": subject,
"content": message,
"sender": sender,
"sent_or_received": "Received"
"sent_or_received": "Received",
'reference_doctype': 'Opportunity',
'reference_name': opportunity.name
})
comm.insert(ignore_permissions=True)

View File

@@ -420,7 +420,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 +226,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 +68,Avg. Selling Rate,Moy. Taux de vente
DocType: Assessment,Examiner Name,Nom de l&#39;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}
@@ -722,7 +722,7 @@ The tax rate you define here will be the standard tax rate for all **Items**. If
#### Description of Columns
1. Calculation Type:
1. Calculation Type:
- This can be on **Net Total** (that is the sum of basic amount).
- **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.
- **Actual** (as mentioned).
@@ -733,19 +733,19 @@ The tax rate you define here will be the standard tax rate for all **Items**. If
6. Amount: Tax amount.
7. Total: Cumulative total to this point.
8. Enter Row: If based on ""Previous Row Total"" you can select the row number which will be taken as a base for this calculation (default is the previous row).
9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.","Modèle de la taxe standard qui peut être appliqué à toutes les opérations de vente. Ce modèle peut contenir la liste des chefs d'impôt ainsi que d'autres chefs dépenses / revenus comme le ""port"", ""assurance"", ""Manipulation"", etc.
9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.","Modèle de la taxe standard qui peut être appliqué à toutes les opérations de vente. Ce modèle peut contenir la liste des chefs d'impôt ainsi que d'autres chefs dépenses / revenus comme le ""port"", ""assurance"", ""Manipulation"", etc.
#### Remarque
#### Remarque
Le taux d'imposition vous définir ici sera le taux d'imposition standard pour tous les articles ** **. Se il ya ** ** Articles qui ont des taux différents, ils doivent être ajoutés dans le ** Impôt de l'article ** ** table dans le Point ** maître.
#### Description des colonnes
#### Description des colonnes
1. Type de calcul:
1. Type de calcul:
- Cela peut être le ** Net Total ** (ce est la somme de montant de base).
- ** Sur Rang Précédent Total / Montant ** (pour les taxes ou frais cumulatifs). Si vous sélectionnez cette option, la taxe sera appliquée en pourcentage de la rangée précédente (dans la table d'impôt) montant ou totale.
- ** ** Réelles (comme mentionné).
2. Compte chef: Le grand livre de compte en vertu de laquelle cette taxe sera réservé
2. Compte chef: Le grand livre de compte en vertu de laquelle cette taxe sera réservé
3. Centre de Coût: Si la taxe / redevance est un revenu (comme le transport) ou dépenses qu'elle doit être réservé contre un centre de coûts.
4. Description: Description de la taxe (qui sera imprimée sur les factures / guillemets).
5. Taux: Le taux d'imposition.
@@ -941,7 +941,7 @@ apps/erpnext/erpnext/accounts/doctype/c_form/c_form.py +30,"Row {0}: Invoice {1}
Please enter a valid Invoice","Row {0}: Invoice {1} est invalide, il pourrait être annulé / n&#39;existe pas. \ S&#39;il vous plaît entrer une facture valide"
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +105,Row {0}: Payment against Sales/Purchase Order should always be marked as advance,Row {0}: Paiement contre Ventes / bon de commande doit toujours être marqué comme avance
apps/erpnext/erpnext/setup/setup_wizard/industry_type.py +16,Chemical,chimique
apps/erpnext/erpnext/schools/doctype/grading_structure/grading_structure.py +24,"The intervals for Grade Code {0} overlaps with the grade intervals for other grades.
apps/erpnext/erpnext/schools/doctype/grading_structure/grading_structure.py +24,"The intervals for Grade Code {0} overlaps with the grade intervals for other grades.
Please check intervals {0} and {1} and try again",Les intervalles de code grade {0} chevauchements avec les intervalles de qualité pour les autres grades. S&#39;il vous plaît vérifier les intervalles {0} et {1} et essayez à nouveau
apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.py +694,All items have already been transferred for this Production Order.,Tous les éléments ont déjà été transférés pour cet ordre de production.
DocType: Process Payroll,Select Payroll Year and Month,Sélectionnez paie Année et mois
@@ -2171,7 +2171,7 @@ The tax rate you define here will be the standard tax rate for all **Items**. If
#### Description of Columns
1. Calculation Type:
1. Calculation Type:
- This can be on **Net Total** (that is the sum of basic amount).
- **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.
- **Actual** (as mentioned).
@@ -2183,19 +2183,19 @@ The tax rate you define here will be the standard tax rate for all **Items**. If
7. Total: Cumulative total to this point.
8. Enter Row: If based on ""Previous Row Total"" you can select the row number which will be taken as a base for this calculation (default is the previous row).
9. Consider Tax or Charge for: In this section you can specify if the tax / charge is only for valuation (not a part of total) or only for total (does not add value to the item) or for both.
10. Add or Deduct: Whether you want to add or deduct the tax.","Modèle de la taxe standard qui peut être appliqué à toutes les opérations d'achat. Ce modèle peut contenir la liste des chefs d'impôt ainsi que d'autres chefs de dépenses comme ""Expédition"", ""assurance"", ""Manipulation"", etc.
10. Add or Deduct: Whether you want to add or deduct the tax.","Modèle de la taxe standard qui peut être appliqué à toutes les opérations d'achat. Ce modèle peut contenir la liste des chefs d'impôt ainsi que d'autres chefs de dépenses comme ""Expédition"", ""assurance"", ""Manipulation"", etc.
#### Remarque
#### Remarque
Le taux d'imposition que vous définissez ici sera le taux d'imposition standard pour tous les articles ** **. Se il ya ** ** Articles qui ont des taux différents, ils doivent être ajoutés dans le ** Impôt de l'article ** ** table dans le Point ** maître.
#### Description des colonnes
#### Description des colonnes
1. Type de calcul:
1. Type de calcul:
- Cela peut être le ** Net Total ** (ce est la somme de montant de base).
- ** Sur Rang Précédent Total / Montant ** (pour les taxes ou frais cumulatifs). Si vous sélectionnez cette option, la taxe sera appliquée en pourcentage de la rangée précédente (dans la table d'impôt) montant ou totale.
- ** ** Réelles (comme mentionné).
2. Compte chef: Le grand livre de compte en vertu de laquelle cette taxe sera réservé
2. Compte chef: Le grand livre de compte en vertu de laquelle cette taxe sera réservé
3. Centre de Coût: Si la taxe / redevance est un revenu (comme le transport) ou dépenses qu'elle doit être réservé contre un centre de coûts.
4. Description: Description de la taxe (qui sera imprimée sur les factures / guillemets).
5. Taux: Le taux d'imposition.
@@ -2389,7 +2389,7 @@ Examples:
1. Ways of addressing disputes, indemnity, liability, etc.
1. Address and Contact of your Company.","Conditions d'utilisation standard qui peuvent être ajoutés aux ventes et achats.
Exemples:
Exemples:
1. Validité de l'offre.
1. Conditions de paiement (à l'avance, à crédit, une partie avance etc).
@@ -2398,7 +2398,7 @@ Examples:
1. Garantie cas échéant.
1. Politique de retour.
1. Conditions d'expédition, le cas échéant.
1. Façons de différends adressage, indemnisation, la responsabilité, etc.
1. Façons de différends adressage, indemnisation, la responsabilité, etc.
1. Adresse et contact de votre société."
DocType: Attendance,Leave Type,Type de Congé
apps/erpnext/erpnext/controllers/stock_controller.py +173,Expense / Difference account ({0}) must be a 'Profit or Loss' account,Dépenses / compte de la différence ({0}) doit être un compte «de résultat»
@@ -3384,7 +3384,7 @@ DocType: Accounts Settings,"If enabled, the system will post accounting entries
apps/erpnext/erpnext/setup/setup_wizard/industry_type.py +15,Brokerage,courtage
DocType: Address,Postal Code,Code Postal
DocType: Production Order Operation,"in Minutes
Updated via 'Time Log'","Mise à jour en quelques minutes
Updated via 'Time Log'","Mise à jour en quelques minutes
via 'Log Time'"
DocType: Customer,From Lead,Du prospect
apps/erpnext/erpnext/config/manufacturing.py +13,Orders released for production.,Commandes validé pour la production.
@@ -3564,7 +3564,7 @@ apps/erpnext/erpnext/controllers/recurring_document.py +133,Please find attached
apps/erpnext/erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.py +34,Bank Statement balance as per General Ledger,Solde du relevé bancaire que par General Ledger
DocType: Job Applicant,Applicant Name,Nom du demandeur
DocType: Authorization Rule,Customer / Item Name,Client / Nom d&#39;article
DocType: Product Bundle,"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**.
DocType: Product Bundle,"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**.
The package **Item** will have ""Is Stock Item"" as ""No"" and ""Is Sales Item"" as ""Yes"".
@@ -3711,17 +3711,17 @@ DocType: Address Template,"<h4>Default Template</h4>
{% if phone %}Phone: {{ phone }}&lt;br&gt;{% endif -%}
{% if fax %}Fax: {{ fax }}&lt;br&gt;{% endif -%}
{% if email_id %}Email: {{ email_id }}&lt;br&gt;{% endif -%}
</code></pre>","<H4> Modèle par défaut </ h4>
<p> <a Utilise href=""http://jinja.pocoo.org/docs/templates/""> Jinja Templating </a> et tous les champs d'adresse ( y compris les champs personnalisés le cas échéant) sera disponible </ p>
<pre> <code> {{address_line1}} & lt; br & gt;
{% si address_line2%} {{address_line2}} & lt; br & gt; { % endif -%}
{{ville}} & lt; br & gt;
{% si l'état%} {{}} Etat & lt; br & gt; {% endif -%} {% if
code PIN%} PIN: {{code PIN}} & lt; br & gt; {% endif -%}
{{pays}} & lt; br & gt;
{% si le téléphone%} Téléphone: {{téléphone}} & lt; br & gt; { % endif -%}
{% if télécopieur%} Fax: {{fax}} & lt; br & gt; {% endif -%}
{% si email_id%} Email: {{email_id}} & lt; br & gt ; {% endif -%}
</code></pre>","<H4> Modèle par défaut </ h4>
<p> <a Utilise href=""http://jinja.pocoo.org/docs/templates/""> Jinja Templating </a> et tous les champs d'adresse ( y compris les champs personnalisés le cas échéant) sera disponible </ p>
<pre> <code> {{address_line1}} & lt; br & gt;
{% si address_line2%} {{address_line2}} & lt; br & gt; { % endif -%}
{{ville}} & lt; br & gt;
{% si l'état%} {{}} Etat & lt; br & gt; {% endif -%} {% if
code PIN%} PIN: {{code PIN}} & lt; br & gt; {% endif -%}
{{pays}} & lt; br & gt;
{% si le téléphone%} Téléphone: {{téléphone}} & lt; br & gt; { % endif -%}
{% if télécopieur%} Fax: {{fax}} & lt; br & gt; {% endif -%}
{% si email_id%} Email: {{email_id}} & lt; br & gt ; {% endif -%}
</ code> </ pre>"
DocType: Salary Detail,Default Amount,Montant par défaut
apps/erpnext/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +93,Warehouse not found in the system,Entrepôt pas trouvé dans le système
@@ -3914,7 +3914,7 @@ DocType: Purchase Invoice Item,Rejected Serial No,N° de série rejetés
apps/erpnext/erpnext/accounts/doctype/fiscal_year/fiscal_year.py +80,Year start date or end date is overlapping with {0}. To avoid please set company,Année de début ou de fin chevauche avec {0}. Pour éviter s'il vous plaît définir la société
apps/erpnext/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py +157,Start date should be less than end date for Item {0},La date de début doit être inférieure à la date de fin de l'article {0}
DocType: Item,"Example: ABCD.#####
If series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.","Exemple:. ABCD #####
If series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.","Exemple:. ABCD #####
Si la série est réglé et n ° de série ne est pas mentionné dans les transactions, le numéro de série, puis automatique sera créé sur la base de cette série. Si vous voulez toujours de mentionner explicitement numéros de série pour ce produit. laissez ce champ vide."
DocType: Upload Attendance,Upload Attendance,Chargez fréquentation
apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.js +113,BOM and Manufacturing Quantity are required,BOM et fabrication Quantité sont nécessaires
1 DocType: Employee Salary Mode Mode de rémunération
420 apps/erpnext/erpnext/accounts/report/gross_profit/gross_profit.py +68 Avg. Selling Rate Moy. Taux de vente
421 DocType: Assessment Examiner Name Nom de l&#39;examinateur
422 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}
423 DocType: Purchase Invoice Item Quantity and Rate Quantité et Prix
424 DocType: Delivery Note % Installed Installé%
425 apps/erpnext/erpnext/public/js/setup_wizard.js +378 Classrooms/ Laboratories etc where lectures can be scheduled. Les salles de classe / Laboratoires etc où des conférences peuvent être programmées.
426 apps/erpnext/erpnext/accounts/doctype/cost_center/cost_center.js +46 Please enter company name first S'il vous plaît entrez en premier le nom de l'entreprise
722 apps/erpnext/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py +107 Office Maintenance Expenses Entretient et dépense bureau
723 apps/erpnext/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.js +115 Please enter Item first S'il vous plaît entrer article premier
724 DocType: Account Liability Responsabilité
725 apps/erpnext/erpnext/hr/doctype/expense_claim/expense_claim.py +61 Sanctioned Amount cannot be greater than Claim Amount in Row {0}. Le montant approuvé ne peut pas être supérieur au montant réclamé en ligne {0}.
726 DocType: Company Default Cost of Goods Sold Account Par défaut Coût des marchandises vendues compte
727 apps/erpnext/erpnext/stock/get_item_details.py +275 Price List not selected Liste des prix non sélectionnée
728 DocType: Employee Family Background Antécédents familiaux
733 apps/erpnext/erpnext/accounts/report/general_ledger/general_ledger.py +50 To filter based on Party, select Party Type first Pour filtrer sur la base du Parti, sélectionnez Parti premier type
734 apps/erpnext/erpnext/controllers/sales_and_purchase_return.py +48 'Update Stock' can not be checked because items are not delivered via {0} 'Mettre à jour Stock' ne peut pas être vérifié parce que les articles ne sont pas livrés par {0}
735 apps/erpnext/erpnext/public/js/setup_wizard.js +298 Nos Nos
736 DocType: Item Items with higher weightage will be shown higher Articles avec weightage supérieur seront affichés supérieur
737 DocType: Bank Reconciliation Detail Bank Reconciliation Detail Détail du rapprochement bancaire
738 apps/erpnext/erpnext/controllers/accounts_controller.py +545 Row #{0}: Asset {1} must be submitted Row # {0}: {1} Asset doit être soumise
739 apps/erpnext/erpnext/hr/doctype/leave_control_panel/leave_control_panel.py +40 No employee found Aucun employé trouvé
740 DocType: Supplier Quotation Stopped Arrêté
741 DocType: Item If subcontracted to a vendor Si en sous-traitance à un fournisseur
742 DocType: SMS Center All Customer Contact Tous les contacts clients
743 apps/erpnext/erpnext/config/stock.py +148 Upload stock balance via csv. Chargez solde disponible via csv.
744 DocType: Warehouse Tree Details Arbre Détails
745 Support Analytics Analyse du support
746 DocType: Item Website Warehouse Entrepôt site web
747 DocType: Payment Reconciliation Minimum Invoice Amount Montant minimum de facturation
748 apps/erpnext/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py +64 Item Row {idx}: {doctype} {docname} does not exist in above '{doctype}' table Item Row {idx}: {doctype} {} docname n&#39;existe pas dans ci-dessus &#39;{doctype}&#39; table
749 apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +259 Timesheet {0} is already completed or cancelled Timesheet {0} est déjà terminée ou annulée
750 DocType: Purchase Invoice The day of the month on which auto invoice will be generated e.g. 05, 28 etc Le jour du mois où la facture automatique sera généré par exemple 05, 28 etc
751 DocType: Asset Opening Accumulated Depreciation Ouverture Amortissement cumulé
941 apps/erpnext/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +71 Removed items with no change in quantity or value. Les articles retirés avec aucun changement dans la quantité ou la valeur.
942 DocType: Delivery Note Delivery To Livraison à
943 apps/erpnext/erpnext/stock/doctype/item/item.py +637 Attribute table is mandatory Table attribut est obligatoire
944 DocType: Production Planning Tool Get Sales Orders Obtenez des commandes clients
945 apps/erpnext/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +64 {0} can not be negative {0} ne peut pas être négatif
946 apps/erpnext/erpnext/schools/doctype/announcement/announcement.py +18 Please select a Student S&#39;il vous plaît sélectionner un étudiant
947 apps/erpnext/erpnext/public/js/pos/pos.html +29 Discount Remise
2171 DocType: Item Quality Parameters Paramètres de qualité
2172 sales-browser ventes navigateur
2173 apps/erpnext/erpnext/accounts/doctype/account/account.js +56 Ledger Grand livre
2174 DocType: Target Detail Target Amount Montant Ciblé
2175 DocType: Shopping Cart Settings Shopping Cart Settings Panier Paramètres
2176 DocType: Journal Entry Accounting Entries Écritures comptables
2177 apps/erpnext/erpnext/setup/doctype/authorization_rule/authorization_rule.py +24 Duplicate Entry. Please check Authorization Rule {0} Point {0} n'est pas un objet sérialisé
2183 DocType: Stock Entry Detail Serial No / Batch N ° de série / lot
2184 apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py +297 Not Paid and Not Delivered Non rémunéré et non remis
2185 DocType: Product Bundle Parent Item Article Parent
2186 DocType: Account Account Type Type de compte
2187 DocType: Delivery Note DN-RET- DN-RET-
2188 apps/erpnext/erpnext/hr/doctype/leave_allocation/leave_allocation.py +118 Leave Type {0} cannot be carry-forwarded Laissez type {0} ne peut pas être transmis carry-
2189 apps/erpnext/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py +216 Maintenance Schedule is not generated for all the items. Please click on 'Generate Schedule' Programme d'entretien n'est pas créer pour tous les articles. S'il vous plait clickez sur 'Créer un programme'
2190 To Produce A Produire
2191 apps/erpnext/erpnext/config/hr.py +93 Payroll Paie
2192 apps/erpnext/erpnext/accounts/doctype/payment_entry/payment_entry.js +163 For row {0} in {1}. To include {2} in Item rate, rows {3} must also be included Pour la ligne {0} dans {1}. Pour inclure {2} dans le prix de l&#39;article, les lignes {3} doivent également être inclus
2193 DocType: Packing Slip Identification of the package for the delivery (for print) Identification de l&#39;emballage pour la livraison (pour l&#39;impression)
2194 DocType: Bin Reserved Quantity Quantité réservée
2195 DocType: Landed Cost Voucher Purchase Receipt Items Acheter des articles reçus
2196 apps/erpnext/erpnext/config/learn.py +21 Customizing Forms Personnalisation des formulaires
2197 apps/erpnext/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py +155 Depreciation Amount during the period Montant d&#39;amortissement au cours de la période
2198 apps/erpnext/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py +32 Disabled template must not be default template modèle handicapé ne doit pas être modèle par défaut
2199 DocType: Account Income Account Compte de résultat
2200 DocType: Payment Request Amount in customer's currency Montant dans la devise du client
2201 apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +742 Delivery Livraison
2389 DocType: Rename Tool Rename Log Renommez identifiez-vous
2390 DocType: Maintenance Visit Purpose Against Document No Sur le document n °
2391 apps/erpnext/erpnext/config/selling.py +110 Manage Sales Partners. Gérer les partenaires commerciaux.
2392 DocType: Quality Inspection Inspection Type Type d&#39;inspection
2393 apps/erpnext/erpnext/stock/doctype/warehouse/warehouse.py +231 Warehouses with existing transaction can not be converted to group. Entrepôts avec transaction existants ne peuvent pas être convertis en groupe.
2394 apps/erpnext/erpnext/controllers/recurring_document.py +166 Please select {0} S'il vous plaît sélectionnez {0}
2395 DocType: C-Form C-Form No Formulaire - C No
2398 apps/erpnext/erpnext/setup/setup_wizard/install_fixtures.py +96 Researcher chercheur
2399 DocType: Program Enrollment Tool Student Program Enrollment Tool Student Outil d&#39;inscription Programme des étudiants
2400 apps/erpnext/erpnext/hr/doctype/job_applicant/job_applicant.py +25 Name or Email is mandatory Nom ou Email est obligatoire
2401 apps/erpnext/erpnext/config/stock.py +158 Incoming quality inspection. Contrôle de la qualité entrant.
2402 DocType: Purchase Order Item Returned Qty Retourné Quantité
2403 DocType: Employee Exit Quitter
2404 apps/erpnext/erpnext/accounts/doctype/account/account.py +159 Root Type is mandatory Type de Root est obligatoire
3384 apps/erpnext/erpnext/accounts/doctype/asset/depreciation.py +106 Asset {0} cannot be scrapped, as it is already {1} Asset {0} ne peut pas être mis au rebut, car il est déjà {1}
3385 DocType: Task Total Expense Claim (via Expense Claim) Frais totaux (via Note de Frais)
3386 apps/erpnext/erpnext/accounts/report/sales_register/sales_register.py +70 Customer Id Client Id
3387 apps/erpnext/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js +176 Mark Absent Marquer absent
3388 DocType: Journal Entry Account Exchange Rate Taux de change
3389 apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +527 Sales Order {0} is not submitted Bon de commande {0} n'a pas été transmis
3390 DocType: Homepage Tag Line Tag ligne
3564 DocType: Maintenance Visit Purpose Maintenance Visit Purpose But de la visite d'entretien
3565 apps/erpnext/erpnext/accounts/report/budget_variance_report/budget_variance_report.js +16 Period période
3566 apps/erpnext/erpnext/stock/doctype/warehouse/warehouse.js +18 General Ledger Grand livre général
3567 apps/erpnext/erpnext/selling/doctype/campaign/campaign.js +10 View Leads Voir Prospects
3568 DocType: Program Enrollment Tool New Program Nouveau programme
3569 DocType: Item Attribute Value Attribute Value Attribut Valeur
3570 apps/erpnext/erpnext/hr/doctype/job_applicant/job_applicant.py +42 Email id must be unique, already exists for {0} ID E-mail doit être unique , existe déjà pour {0}
3711 apps/erpnext/erpnext/hr/doctype/attendance/attendance.py +34 Attendance can not be marked for future dates La participation ne peut pas être marqué pour les dates à venir
3712 DocType: Pricing Rule Pricing Rule Help Prix règle Aide
3713 DocType: Purchase Taxes and Charges Account Head Responsable du compte
3714 apps/erpnext/erpnext/config/stock.py +163 Update additional costs to calculate landed cost of items Mettre à jour les coûts supplémentaires pour calculer le coût au débarquement des articles
3715 apps/erpnext/erpnext/setup/setup_wizard/install_fixtures.py +112 Electrical Electrique
3716 DocType: Stock Entry Total Value Difference (Out - In) Valeur totale différence (Sor - En)
3717 apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +318 Row {0}: Exchange Rate is mandatory Ligne {0}: Taux de change est obligatoire
3718 apps/erpnext/erpnext/setup/doctype/sales_person/sales_person.py +27 User ID not set for Employee {0} ID utilisateur non défini pour l'Employé {0}
3719 DocType: Stock Entry Default Source Warehouse Source d&#39;entrepôt par défaut
3720 DocType: Item Customer Code Code client
3721 apps/erpnext/erpnext/hr/doctype/employee/employee.py +210 Birthday Reminder for {0} Rappel d'anniversaire pour {0}
3722 apps/erpnext/erpnext/selling/report/inactive_customers/inactive_customers.py +72 Days Since Last Order Jours depuis la dernière commande
3723 apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +324 Debit To account must be a Balance Sheet account Débit Pour compte doit être un compte de bilan
3724 DocType: Buying Settings Naming Series Nommer Séries
3725 DocType: Leave Block List Leave Block List Name Laisser Nom de la liste de blocage
3726 apps/erpnext/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py +32 Stock Assets payable
3727 apps/erpnext/erpnext/hr/doctype/process_payroll/process_payroll.js +29 Do you really want to Submit all Salary Slip for month {0} and year {1} Statut du document de transition {0} {1}, n'est pas autorisé
3914 DocType: Purchase Invoice Total Advance Total avance
3915 apps/erpnext/erpnext/schools/doctype/academic_term/academic_term.py +22 The Term End Date cannot be earlier than the Term Start Date. Please correct the dates and try again. La date de fin de terme ne peut pas être antérieure à la date de début de durée. S&#39;il vous plaît corriger les dates et essayez à nouveau.
3916 DocType: Stock Reconciliation Item Quantity Difference Quantité Différence
3917 apps/erpnext/erpnext/config/hr.py +253 Processing Payroll Traitement de la paie
3918 DocType: Opportunity Item Basic Rate Taux de base
3919 DocType: GL Entry Credit Amount Le montant du crédit
3920 DocType: Cheque Print Template Signatory Position Position signataire

View File

@@ -103,4 +103,5 @@ def update_contact(doc, method):
for key in ("first_name", "last_name", "phone"):
if doc.get(key):
contact.set(key, doc.get(key))
contact.flags.ignore_mandatory = True
contact.save(ignore_permissions=True)

View File

@@ -125,6 +125,20 @@ class TransactionBase(StatusUpdater):
ret = None
return ret
def delink_advance_entries(self, linked_doc_name):
total_allocated_amount = 0
for adv in self.advances:
consider_for_total_advance = True
if adv.reference_name == linked_doc_name:
frappe.db.sql("""delete from `tab{0} Advance`
where name = %s""".format(self.doctype), adv.name)
consider_for_total_advance = False
if consider_for_total_advance:
total_allocated_amount += flt(adv.allocated_amount, adv.precision("allocated_amount"))
frappe.db.set_value(self.doctype, self.name, "total_advance", total_allocated_amount, update_modified=False)
def delete_events(ref_type, ref_name):
frappe.delete_doc("Event", frappe.db.sql_list("""select name from `tabEvent`

View File

@@ -4,4 +4,4 @@ import frappe
def get_context(context):
# do your magic here
pass
context.show_sidebar = True