Compare commits

..

64 Commits

Author SHA1 Message Date
Frappe Bot
9ce994a320 Merge branch 'hotfix' 2019-03-01 09:12:25 +00:00
Frappe Bot
3ec0bb7e53 bumped to version 11.1.13 2019-03-01 09:12:25 +00:00
rohitwaghchaure
066da6b1b6 Merge pull request #16817 from gaurav-naik/italy-einvoice-bank-details-fix
fix(regional,italy): bank details, custom button on sales invoice
2019-03-01 14:26:07 +05:30
rohitwaghchaure
5e71a56c7a Merge pull request #16807 from rohitwaghchaure/remove_validation_for_group_by_voucher_consolidate
fix: when General Ledger is opened from Purchase Receipt or Delivery note, user get Opening and Closing printed twice
2019-03-01 14:25:00 +05:30
Gaurav
6a4625b94c fix(regional,italy): codacy fixes in regional sales_invoice js 2019-03-01 13:58:39 +05:30
Gaurav
b30a9b1869 fix(regional,italy): bank details, custom button on sales invoice
Updates to Bank details in e-invoice XML
Additional fields on Payment Schedule
Button to Generate E-Invoice on Sales Invoice (generates and replaces attached e-invoice)
Replaced `x.decode('utf-8')` with `frappe.safe_decode(x, encoding='utf-8')` in setup.py
Updated italian localisation patch line in patches.txt
2019-03-01 12:38:35 +05:30
Rohit Waghchaure
c21cda2790 Removed validation for group by voucher in general ledger 2019-02-28 16:20:45 +05:30
Frappe Bot
5d414af86b Merge branch 'hotfix' 2019-02-28 10:08:08 +00:00
Frappe Bot
58135976dd bumped to version 11.1.12 2019-02-28 10:08:08 +00:00
rohitwaghchaure
1d41c1c2de Merge pull request #16787 from rohitwaghchaure/italian_more_fixes
fix: e-invoicing patch, patch to set country code in the address
2019-02-28 11:28:04 +05:30
rohitwaghchaure
75e17c664a Merge pull request #16797 from rohitwaghchaure/cost_update_not_working_for_price_list
fix: bom cost update is not working
2019-02-27 20:52:28 +05:30
Rohit Waghchaure
b48effebce fix: test case 2019-02-27 19:33:22 +05:30
Rohit Waghchaure
cd34c70670 fix: bom cost update is not working 2019-02-27 18:01:30 +05:30
Rohit Waghchaure
74cfe57716 fix: e-invoicing patch, patch to set country code in the address 2019-02-27 14:38:36 +05:30
Rushabh Mehta
76f36f68d3 Merge pull request #16790 from crossxcell99/master
fix: call base class onload method
2019-02-27 08:31:14 +05:30
crossxcell99
f95171e808 fix: call base clase onload method 2019-02-26 18:01:37 +01:00
Sagar Vora
2ca1f135ef Merge branch 'hotfix' 2019-02-26 17:08:58 +05:30
Sagar Vora
5a14e46a1b bumped to version 11.1.11 2019-02-26 17:28:58 +05:50
Sagar Vora
311a9c79e3 fix: use node v10 for CI 2019-02-26 16:56:37 +05:30
Nabin Hait
39c489bfdc Merge pull request #16781 from deepeshgarg007/summary
fix: Make company filter mandatory in sales person wise transaction summary
2019-02-26 16:00:51 +05:30
Nabin Hait
be5124fe10 Merge pull request #16784 from rohitwaghchaure/multiple_fixes_e_invoicing
fix: multiple e-invoicing issues for italy region
2019-02-26 15:52:56 +05:30
Rohit Waghchaure
0f98cb8b83 fix: multiple e-invoicing issues for italy region 2019-02-26 15:09:27 +05:30
deepeshgarg007
d2d84e3c9d fix: Company filter fix 2019-02-26 11:52:22 +05:30
Sagar Vora
1ca2d47d35 fix: update node to version supported by Yarn (#16772) 2019-02-25 21:10:11 +05:30
Suraj Shetty
5636f924a9 fix: get mode of payment while selecting payment term in payment term template (#16765) 2019-02-25 12:43:34 +05:30
Nabin Hait
9990306399 fix: Consider only active BOMs while updating cost via BOM Update Tool (#16753) 2019-02-25 11:59:05 +05:30
Rushabh Mehta
e2de8e0fa5 fix: expense claim type (#16760) 2019-02-25 11:56:30 +05:30
Suraj Shetty
3ed3332c46 Merge pull request #16726 from deepeshgarg007/bom-item
fix: Removed duplicate fields from BOM Item
2019-02-22 10:26:29 +05:30
Suraj Shetty
2dadc1ef98 chore: Remove trailing whitespaces 2019-02-21 20:51:35 +05:30
deepeshgarg007
bf6b36a39b fix: Removed white spaces 2019-02-21 19:30:27 +05:30
deepeshgarg007
56b52d43e6 Merge branch 'hotfix' of https://github.com/frappe/erpnext into bom-item 2019-02-21 18:30:02 +05:30
Saurabh
539c77c591 Merge branch 'hotfix' 2019-02-21 18:25:28 +05:30
Saurabh
76cd402ca5 bumped to version 11.1.10 2019-02-21 18:55:28 +06:00
Saurabh
e5ff28a92c Merge pull request #16754 from deepeshgarg007/state_code
fix: State code issue fix
2019-02-21 18:21:24 +05:30
Nabin Hait
367d7c104e Merge pull request #16724 from rohitwaghchaure/user_progress_issue
fix: user progress issue
2019-02-21 18:13:52 +05:30
Saurabh
47738f9792 Merge pull request #16750 from nabinhait/cc-against-bs
fix: Ignore cost center while fetching outstanding invoices if not allowed from accounts settings
2019-02-21 18:12:06 +05:30
Nabin Hait
e08cb3a49b Merge pull request #16745 from nabinhait/manage-returned-qty
fix: Consider returned qty while making invoice from DN / PR
2019-02-21 18:11:37 +05:30
Nabin Hait
31f46b313c Merge pull request #16728 from rohitwaghchaure/maintainance_visit_issue
fix: not able to cancel maintenance visit
2019-02-21 18:10:46 +05:30
Nabin Hait
e328869b10 Merge pull request #16738 from deepeshgarg007/unique_tree_options
fix: Filter out unique values for tree options
2019-02-21 18:09:42 +05:30
Nabin Hait
e3b1b11bc5 Merge pull request #16740 from nabinhait/leave-calendar
fix: Calendar events for leaves considering user permissions
2019-02-21 18:08:19 +05:30
Saurabh
a05ccb76f4 Merge pull request #16748 from nabinhait/multi-company-serial-invoicing
fix: Validate serial no usage in invoice considering multi company transaction
2019-02-21 18:07:40 +05:30
Nabin Hait
e797ec7463 Merge pull request #16746 from deepeshgarg007/gross_profit
fix: Decimal point issue in gross profit print
2019-02-21 18:07:14 +05:30
deepeshgarg007
1915e15a9e fix: State code issue fix in regional module(Italy) 2019-02-21 17:55:57 +05:30
rohitwaghchaure
a49f59fcec Merge pull request #16751 from rohitwaghchaure/parent_value_showing_as_zero
(Profit and Loss Statement, fix): for parent account value was showing as zero
2019-02-21 17:50:51 +05:30
Rohit Waghchaure
90691dc0d8 (Profit and Loss Statement, fix): for parent account value was showing as zero 2019-02-21 17:18:28 +05:30
Nabin Hait
b24caad789 fix: Ignore cost center while fetching outstanding invocies if not allowed from accounts settings 2019-02-21 17:11:35 +05:30
Suraj Shetty
463a3cf8cf Merge pull request #16725 from deepeshgarg007/item_dashboard
fix: Item name display issue fix in item dashboard
2019-02-21 14:42:38 +05:30
Nabin Hait
26972c954d fix: Validate serial no usage in invoice considering multi company transaction 2019-02-21 14:32:41 +05:30
deepeshgarg007
14ff6bfc32 fix: Decimal point issue in gross profit print 2019-02-21 12:08:32 +05:30
Nabin Hait
816a4655a0 fix: Consider returned qty while making invoice from DN / PR 2019-02-21 12:02:36 +05:30
Nabin Hait
40c15d2e74 fix: Calendar events for leaves considering user permissions 2019-02-20 18:55:38 +05:30
Saurabh
bc3bdd77f6 Merge branch 'hotfix' 2019-02-20 18:14:17 +05:30
Saurabh
ada93e5d77 bumped to version 11.1.9 2019-02-20 18:44:17 +06:00
deepeshgarg007
0d64d622e5 fix: filter only unique values for tree options 2019-02-20 17:55:14 +05:30
rohitwaghchaure
485bd93dae Merge pull request #16737 from saurabh6790/indentation_fixes
fix: reload report doc and indentation fixes
2019-02-20 17:40:50 +05:30
rohitwaghchaure
c18e925d61 fix: Moved regional methods from controller to hooks (#16736) 2019-02-20 17:13:15 +05:30
Saurabh
9fcfc63f77 fix: reload report doc and indentation fixes 2019-02-20 17:04:18 +05:30
rohitwaghchaure
ef3f864123 fix: not able to submit purchase order (#16735) 2019-02-20 15:47:06 +05:30
rohitwaghchaure
e141865c43 Merge pull request #16722 from rohitwaghchaure/stop_button_not_working
fix: stop button not working in material request
2019-02-20 12:30:26 +05:30
Rohit Waghchaure
7e02e1c3cd fix: not able to cancel maintenance visit 2019-02-19 22:53:31 +05:30
deepeshgarg007
1b04534095 fix: Removed duplicate fields from BOM Item 2019-02-19 21:36:12 +05:30
deepeshgarg007
942c894f93 fix: fetch item name in item dashboard 2019-02-19 19:51:23 +05:30
Rohit Waghchaure
f4049f9dfd fix: user progress issue 2019-02-19 19:46:14 +05:30
Rohit Waghchaure
389cd6ad63 fix: stop button not working in material request 2019-02-19 19:18:07 +05:30
39 changed files with 902 additions and 635 deletions

View File

@@ -15,7 +15,7 @@ install:
- sudo rm /etc/apt/sources.list.d/docker.list
- sudo apt-get install hhvm && rm -rf /home/travis/.kiex/
- sudo apt-get purge -y mysql-common mysql-server mysql-client
- nvm install v7.10.0
- nvm install 10
- pip install python-coveralls
- wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py
- sudo python install.py --develop --user travis --without-bench-setup

View File

@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '11.1.8'
__version__ = '11.1.13'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -6,7 +6,7 @@ from __future__ import unicode_literals
import frappe, erpnext, json
from frappe import _, scrub, ValidationError
from frappe.utils import flt, comma_or, nowdate, getdate
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on, get_allow_cost_center_in_entry_of_bs_account
from erpnext.accounts.party import get_party_account
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
from erpnext.setup.utils import get_exchange_rate
@@ -564,8 +564,8 @@ def get_outstanding_reference_documents(args):
.format(frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"]))
# Add cost center condition
if args.get("cost_center"):
condition += " and cost_center='%s'" % args.get("cost_center")
if args.get("cost_center") and get_allow_cost_center_in_entry_of_bs_account():
condition += " and cost_center='%s'" % args.get("cost_center")
outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"),
args.get("party_account"), condition=condition)

View File

@@ -8,5 +8,6 @@ frappe.ui.form.on('Payment Terms Template', {
frm.add_fetch("payment_term", "due_date_based_on", "due_date_based_on");
frm.add_fetch("payment_term", "credit_days", "credit_days");
frm.add_fetch("payment_term", "credit_months", "credit_months");
frm.add_fetch("payment_term", "mode_of_payment", "mode_of_payment");
}
});

View File

@@ -46,6 +46,7 @@ class PurchaseInvoice(BuyingController):
}]
def onload(self):
super(PurchaseInvoice, self).onload()
supplier_tds = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category")
self.set_onload("supplier_tds", supplier_tds)

View File

@@ -0,0 +1,3 @@
{% include "erpnext/regional/italy/sales_invoice.js" %}
erpnext.setup_e_invoice_button('Sales Invoice')

View File

@@ -201,7 +201,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
get_query: function() {
var filters = {
docstatus: 1,
company: me.frm.doc.company
company: me.frm.doc.company,
is_return: 0
};
if(me.frm.doc.customer) filters["customer"] = me.frm.doc.customer;
return {

View File

@@ -24,7 +24,6 @@ from erpnext.accounts.general_ledger import get_round_off_account_and_cost_cente
from erpnext.accounts.doctype.loyalty_program.loyalty_program import \
get_loyalty_program_details_with_points, get_loyalty_details, validate_loyalty_points
from erpnext.accounts.deferred_revenue import validate_service_stop_date
from erpnext.controllers.accounts_controller import on_submit_regional, on_cancel_regional
from erpnext.healthcare.utils import manage_invoice_submit_cancel
@@ -199,8 +198,6 @@ class SalesInvoice(SellingController):
if "Healthcare" in active_domains:
manage_invoice_submit_cancel(self, "on_submit")
on_submit_regional(self)
def validate_pos_paid_amount(self):
if len(self.payments) == 0 and self.is_pos:
frappe.throw(_("At least one mode of payment is required for POS invoice."))
@@ -256,8 +253,6 @@ class SalesInvoice(SellingController):
if "Healthcare" in active_domains:
manage_invoice_submit_cancel(self, "on_cancel")
on_cancel_regional(self)
def update_status_updater_args(self):
if cint(self.update_stock):
self.status_updater.extend([{
@@ -1017,9 +1012,10 @@ class SalesInvoice(SellingController):
for serial_no in item.serial_no.split("\n"):
sales_invoice = frappe.db.get_value("Serial No", serial_no, "sales_invoice")
if sales_invoice and self.name != sales_invoice:
frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}".format(
serial_no, sales_invoice
)))
sales_invoice_company = frappe.db.get_value("Sales Invoice", sales_invoice, "company")
if sales_invoice_company == self.company:
frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}"
.format(serial_no, sales_invoice)))
def update_project(self):
if self.project:

View File

@@ -270,7 +270,7 @@ def add_total_row(out, root_type, balance_must_be, period_list, company_currency
for period in period_list:
total_row.setdefault(period.key, 0.0)
total_row[period.key] += row.get(period.key, 0.0)
row[period.key] = 0.0
row[period.key] = row.get(period.key, 0.0)
total_row.setdefault("total", 0.0)
total_row["total"] += flt(row["total"])

View File

@@ -53,7 +53,7 @@ def validate_filters(filters, account_details):
frappe.throw(_("Can not filter based on Account, if grouped by Account"))
if (filters.get("voucher_no")
and filters.get("group_by") in [_('Group by Voucher'), _('Group by Voucher (Consolidated)')]):
and filters.get("group_by") in [_('Group by Voucher')]):
frappe.throw(_("Can not filter based on Voucher No, if grouped by Voucher"))
if filters.from_date > filters.to_date:

View File

@@ -135,9 +135,9 @@ class GrossProfitGenerator(object):
row.buying_rate, row.base_rate = 0.0, 0.0
# calculate gross profit
row.gross_profit = row.base_amount - row.buying_amount
row.gross_profit = flt(row.base_amount - row.buying_amount, 3)
if row.base_amount:
row.gross_profit_percent = (row.gross_profit / row.base_amount) * 100.0
row.gross_profit_percent = flt((row.gross_profit / row.base_amount) * 100.0, 3)
else:
row.gross_profit_percent = 0.0
@@ -174,8 +174,8 @@ class GrossProfitGenerator(object):
self.grouped_data.append(row)
def set_average_rate(self, new_row):
new_row.gross_profit = new_row.base_amount - new_row.buying_amount
new_row.gross_profit_percent = ((new_row.gross_profit / new_row.base_amount) * 100.0) \
new_row.gross_profit = flt(new_row.base_amount - new_row.buying_amount,3)
new_row.gross_profit_percent = flt(((new_row.gross_profit / new_row.base_amount) * 100.0),3) \
if new_row.base_amount else 0
new_row.buying_rate = (new_row.buying_amount / new_row.qty) if new_row.qty else 0
new_row.base_rate = (new_row.base_amount / new_row.qty) if new_row.qty else 0

View File

@@ -1138,11 +1138,3 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name):
@erpnext.allow_regional
def validate_regional(doc):
pass
@erpnext.allow_regional
def on_submit_regional(doc):
pass
@erpnext.allow_regional
def on_cancel_regional(doc):
pass

View File

@@ -202,7 +202,8 @@ doc_events = {
"validate": "erpnext.portal.doctype.products_settings.products_settings.home_page_is_products"
},
"Sales Invoice": {
"on_submit": "erpnext.regional.france.utils.create_transaction_log",
"on_submit": ["erpnext.regional.france.utils.create_transaction_log", "erpnext.regional.italy.utils.sales_invoice_on_submit"],
"on_cancel": "erpnext.regional.italy.utils.sales_invoice_on_cancel",
"on_trash": "erpnext.regional.check_deletion_permission"
},
"Payment Entry": {
@@ -305,7 +306,5 @@ regional_overrides = {
'Italy': {
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.italy.utils.update_itemised_tax_data',
'erpnext.controllers.accounts_controller.validate_regional': 'erpnext.regional.italy.utils.sales_invoice_validate',
'erpnext.controllers.accounts_controller.on_submit_regional': 'erpnext.regional.italy.utils.sales_invoice_on_submit',
'erpnext.controllers.accounts_controller.on_cancel_regional': 'erpnext.regional.italy.utils.sales_invoice_on_cancel'
}
}

View File

@@ -35,6 +35,7 @@ $.extend(cur_frm.cscript, new erpnext.hr.ExpenseClaimController({frm: cur_frm}))
cur_frm.add_fetch('employee', 'company', 'company');
cur_frm.add_fetch('employee','employee_name','employee_name');
cur_frm.add_fetch('expense_type','description','description');
cur_frm.cscript.onload = function(doc) {
if (doc.__islocal) {

View File

@@ -1,366 +1,378 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2013-02-22 01:27:46",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"editable_grid": 1,
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2013-02-22 01:27:46",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"editable_grid": 1,
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "expense_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Expense Date",
"length": 0,
"no_copy": 0,
"oldfieldname": "expense_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"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,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "expense_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Expense Date",
"length": 0,
"no_copy": 0,
"oldfieldname": "expense_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"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,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"unique": 0,
"width": "150px"
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 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,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 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,
"translatable": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "expense_type",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Expense Claim Type",
"length": 0,
"no_copy": 0,
"oldfieldname": "expense_type",
"oldfieldtype": "Link",
"options": "Expense Claim Type",
"permlevel": 0,
"print_hide": 0,
"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,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "expense_type",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Expense Claim Type",
"length": 0,
"no_copy": 0,
"oldfieldname": "expense_type",
"oldfieldtype": "Link",
"options": "Expense Claim Type",
"permlevel": 0,
"print_hide": 0,
"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,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"unique": 0,
"width": "150px"
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "expense_type",
"fieldname": "default_account",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Default Account",
"length": 0,
"no_copy": 0,
"options": "Account",
"permlevel": 0,
"precision": "",
"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,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "expense_type",
"fieldname": "default_account",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Default Account",
"length": 0,
"no_copy": 0,
"options": "Account",
"permlevel": 0,
"precision": "",
"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,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_4",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 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,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_4",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 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,
"translatable": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "expense_type.description",
"fieldname": "description",
"fieldtype": "Text Editor",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Description",
"length": 0,
"no_copy": 0,
"oldfieldname": "description",
"oldfieldtype": "Small Text",
"options": "",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "300px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "",
"fieldname": "description",
"fieldtype": "Text Editor",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Description",
"length": 0,
"no_copy": 0,
"oldfieldname": "description",
"oldfieldtype": "Small Text",
"options": "",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "300px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"unique": 0,
"width": "300px"
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 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,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 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,
"translatable": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "claim_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Claim Amount",
"length": 0,
"no_copy": 0,
"oldfieldname": "claim_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"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,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "claim_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Claim Amount",
"length": 0,
"no_copy": 0,
"oldfieldname": "claim_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"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,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"unique": 0,
"width": "150px"
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_8",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 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,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_8",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 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,
"translatable": 0,
"unique": 0
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sanctioned_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Sanctioned Amount",
"length": 0,
"no_copy": 1,
"oldfieldname": "sanctioned_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"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,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sanctioned_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Sanctioned Amount",
"length": 0,
"no_copy": 1,
"oldfieldname": "sanctioned_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"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,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"unique": 0,
"width": "150px"
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-05-16 22:42:56.727863",
"modified_by": "Administrator",
"module": "HR",
"name": "Expense Claim Detail",
"owner": "harshada@webnotestech.com",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-02-24 08:41:36.122565",
"modified_by": "Administrator",
"module": "HR",
"name": "Expense Claim Detail",
"owner": "harshada@webnotestech.com",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}

View File

@@ -487,7 +487,6 @@ def get_events(start, end, filters=None):
add_block_dates(events, start, end, employee, company)
add_holidays(events, start, end, employee, company)
return events
def add_department_leaves(events, start, end, employee, company):
@@ -500,10 +499,22 @@ def add_department_leaves(events, start, end, employee, company):
department_employees = frappe.db.sql_list("""select name from tabEmployee where department=%s
and company=%s""", (department, company))
match_conditions = "and employee in (\"%s\")" % '", "'.join(department_employees)
add_leaves(events, start, end, match_conditions=match_conditions)
filter_conditions = "employee in (\"%s\")" % '", "'.join(department_employees)
add_leaves(events, start, end, filter_conditions=filter_conditions)
def add_leaves(events, start, end, filter_conditions=None):
conditions = []
if filter_conditions:
conditions.append(filter_conditions)
if not cint(frappe.db.get_value("HR Settings", None, "show_leaves_of_all_department_members_in_calendar")):
from frappe.desk.reportview import build_match_conditions
match_conditions = build_match_conditions("Leave Application")
if match_conditions:
conditions.append(match_conditions)
def add_leaves(events, start, end, match_conditions=None):
query = """select name, from_date, to_date, employee_name, half_day,
status, employee, docstatus
from `tabLeave Application` where
@@ -511,8 +522,8 @@ def add_leaves(events, start, end, match_conditions=None):
and docstatus < 2
and status!="Rejected" """
if match_conditions:
query += match_conditions
if conditions:
query += ' and ' + ' and '.join(conditions)
for d in frappe.db.sql(query, {"start":start, "end": end}, as_dict=True):
e = {

View File

@@ -41,12 +41,19 @@ class MaintenanceVisit(TransactionBase):
work_done = nm and nm[0][3] or ''
else:
status = 'Open'
mntc_date = ''
service_person = ''
work_done = ''
mntc_date = None
service_person = None
work_done = None
frappe.db.sql("update `tabWarranty Claim` set resolution_date=%s, resolved_by=%s, resolution_details=%s, status=%s where name =%s",(mntc_date,service_person,work_done,status,d.prevdoc_docname))
wc_doc = frappe.get_doc('Warranty Claim', d.prevdoc_docname)
wc_doc.update({
'resolution_date': mntc_date,
'resolved_by': service_person,
'resolution_details': work_done,
'status': status
})
wc_doc.db_update()
def check_if_last_visit(self):
"""check if last maintenance visit against same sales order/ Warranty Claim"""

View File

@@ -706,8 +706,11 @@ def get_children(doctype, parent=None, is_root=False, **filters):
def get_boms_in_bottom_up_order(bom_no=None):
def _get_parent(bom_no):
return frappe.db.sql_list("""select distinct parent from `tabBOM Item`
where bom_no = %s and docstatus=1 and parenttype='BOM'""", bom_no)
return frappe.db.sql_list("""
select distinct bom_item.parent from `tabBOM Item` bom_item
where bom_item.bom_no = %s and bom_item.docstatus=1 and bom_item.parenttype='BOM'
and exists(select bom.name from `tabBOM` bom where bom.name=bom_item.parent and bom.is_active=1)
""", bom_no)
count = 0
bom_list = []
@@ -715,9 +718,10 @@ def get_boms_in_bottom_up_order(bom_no=None):
bom_list.append(bom_no)
else:
# get all leaf BOMs
bom_list = frappe.db.sql_list("""select name from `tabBOM` bom where docstatus=1
and not exists(select bom_no from `tabBOM Item`
where parent=bom.name and ifnull(bom_no, '')!='')""")
bom_list = frappe.db.sql_list("""select name from `tabBOM` bom
where docstatus=1 and is_active=1
and not exists(select bom_no from `tabBOM Item`
where parent=bom.name and ifnull(bom_no, '')!='')""")
while(count < len(bom_list)):
for child_bom in _get_parent(bom_list[count]):

View File

@@ -78,6 +78,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "operation",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item operation",
"length": 0,
"no_copy": 0,
"options": "Operation",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@@ -893,6 +926,38 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "allow_alternative_item",
"fieldtype": "Check",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow Alternative Item",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"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,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@@ -958,71 +1023,6 @@
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "operation",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Item operation",
"length": 0,
"no_copy": 0,
"options": "Operation",
"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,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "allow_alternative_item",
"fieldtype": "Check",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow Alternative Item",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"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,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
@@ -1035,7 +1035,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-11-23 15:05:55.187136",
"modified": "2019-02-21 19:19:54.872459",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Item",
@@ -1050,4 +1050,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

View File

@@ -587,4 +587,4 @@ erpnext.patches.v11_1.setup_guardian_role
execute:frappe.delete_doc('DocType', 'Notification Control')
erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
erpnext.patches.v11_0.make_italian_localization_fields
erpnext.patches.v11_0.make_italian_localization_fields # 01-03-2019

View File

@@ -8,21 +8,23 @@ import frappe
def execute():
company = frappe.get_all('Company', filters = {'country': 'Italy'})
if not company:
return
company = frappe.get_all('Company', filters = {'country': 'Italy'})
if not company:
return
frappe.reload_doc('regional', 'report', 'electronic_invoice_register')
make_custom_fields()
setup_report()
make_custom_fields()
setup_report()
# Set state codes
condition = ""
for state, code in state_codes.items():
condition += " when '{0}' then '{1}'".format(frappe.db.escape(state), frappe.db.escape(code))
# Set state codes
condition = ""
for state, code in state_codes.items():
condition += " when '{0}' then '{1}'".format(frappe.db.escape(state), frappe.db.escape(code))
if condition:
condition = "state_code = (case state {0} end),".format(condition)
if condition:
frappe.db.sql("""
UPDATE tabAddress set state_code = (case state {condition} end)
WHERE country in ('Italy', 'Italia', 'Italian Republic', 'Repubblica Italiana')
""".format(condition=condition))
frappe.db.sql("""
UPDATE tabAddress set {condition} country_code = UPPER(ifnull((select code
from `tabCountry` where name = `tabAddress`.country), ''))
""".format(condition=condition))

View File

@@ -73,7 +73,7 @@ erpnext.stock.StockController = frappe.ui.form.Controller.extend({
from_date: me.frm.doc.posting_date,
to_date: me.frm.doc.posting_date,
company: me.frm.doc.company,
group_by: ""
group_by: "Group by Voucher (Consolidated)"
};
frappe.set_route("query-report", "General Ledger");
}, __("View"));

View File

@@ -255,11 +255,16 @@ $.extend(erpnext.utils, {
// get valid options for tree based on user permission & locals dict
let unscrub_option = frappe.model.unscrub(option);
let user_permission = frappe.defaults.get_user_permissions();
let options;
if(user_permission && user_permission[unscrub_option]) {
return user_permission[unscrub_option].map(perm => perm.doc);
options = user_permission[unscrub_option].map(perm => perm.doc);
} else {
return $.map(locals[`:${unscrub_option}`], function(c) { return c.name; }).sort();
options = $.map(locals[`:${unscrub_option}`], function(c) { return c.name; }).sort();
}
// filter unique values, as there may be multiple user permissions for any value
return options.filter((value, index, self) => self.indexOf(value) === index);
},
get_tree_default: function(option) {
// set default for a field based on user permission

View File

@@ -9,7 +9,7 @@
{%- if address.state_code %}
<Provincia>{{ address.state_code }}</Provincia>
{%- endif %}
<Nazione>{{ address.country_code|upper }}</Nazione>
<Nazione>{{ address.country_code }}</Nazione>
{%- endmacro %}
{%- macro render_discount_or_margin(item) -%}
@@ -32,15 +32,15 @@
{%- endmacro -%}
<?xml version='1.0' encoding='UTF-8'?>
<p:FatturaElettronica xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:p="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
versione="{{ doc.transmission_format_code }}"
<p:FatturaElettronica xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:p="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
versione="{{ doc.transmission_format_code }}"
xsi:schemaLocation="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2 http://www.fatturapa.gov.it/export/fatturazione/sdi/fatturapa/v1.2/Schema_del_file_xml_FatturaPA_versione_1.2.xsd">
<FatturaElettronicaHeader>
<DatiTrasmissione>
<IdTrasmittente>
<IdPaese>{{ doc.company_address_data.country_code|upper or "IT" }}</IdPaese>
<IdPaese>{{ doc.company_address_data.country_code }}</IdPaese>
<IdCodice>{{ doc.company_fiscal_code or doc.company_tax_id | replace("IT","") }}</IdCodice>
</IdTrasmittente>
<ProgressivoInvio>{{ doc.progressive_number }}</ProgressivoInvio>
@@ -56,7 +56,7 @@
<CedentePrestatore>
<DatiAnagrafici>
<IdFiscaleIVA>
<IdPaese>{{ doc.company_address_data.country_code|upper or "IT"}}</IdPaese>
<IdPaese>{{ doc.company_address_data.country_code }}</IdPaese>
<IdCodice>{{ doc.company_tax_id | replace("IT","") }}</IdCodice>
</IdFiscaleIVA>
{%- if doc.company_fiscal_code %}
@@ -99,7 +99,7 @@
<CodiceFiscale>{{ doc.customer_data.fiscal_code }}</CodiceFiscale>
{%- else %}
<IdFiscaleIVA>
<IdPaese>{{ doc.customer_address_data.country_code|upper or "IT" }}</IdPaese>
<IdPaese>{{ doc.customer_address_data.country_code }}</IdPaese>
<IdCodice>{{ doc.tax_id | replace("IT","") }}</IdCodice>
</IdFiscaleIVA>
{%- endif %}
@@ -160,7 +160,7 @@
<CodiceTipo>CODICE</CodiceTipo>
<CodiceValore>{{ item.item_code }}</CodiceValore>
</CodiceArticolo>
<Descrizione>{{ item.description or item.item_name }}</Descrizione>
<Descrizione>{{ html2text(item.description or '') or item.item_name }}</Descrizione>
<Quantita>{{ format_float(item.qty) }}</Quantita>
<UnitaMisura>{{ item.stock_uom }}</UnitaMisura>
<PrezzoUnitario>{{ format_float(item.price_list_rate or item.rate) }}</PrezzoUnitario>
@@ -199,7 +199,15 @@
<ModalitaPagamento>{{ payment_term.mode_of_payment_code.split("-")[0] }}</ModalitaPagamento>
<DataScadenzaPagamento>{{ payment_term.due_date }}</DataScadenzaPagamento>
<ImportoPagamento>{{ format_float(payment_term.payment_amount) }}</ImportoPagamento>
{%- if payment_term.bank_account_iban %}<IBAN>{{ payment_term.bank_account_iban }}</IBAN>{%- endif %}
<IstitutoFinanziario>{{ payment_term.bank_account_name }}</IstitutoFinanziario>
{%- if payment_term.bank_account_iban %}
<IBAN>{{ payment_term.bank_account_iban }}</IBAN>
<ABI>{{ payment_term.bank_account_iban[5:10] }}</ABI>
<CAB>{{ payment_term.bank_account_iban[10:15] }}</CAB>
{%- endif %}
{%- if payment_term.bank_account_swift_number %}
<BIC>{{ payment_term.bank_account_swift_number }}</BIC>
{%- endif %}
</DettaglioPagamento>
{%- endfor %}
</DatiPagamento>

View File

@@ -0,0 +1,19 @@
erpnext.setup_e_invoice_button = (doctype) => {
frappe.ui.form.on(doctype, {
refresh: (frm) => {
if(frm.doc.docstatus == 1) {
frm.add_custom_button('Generate E-Invoice', () => {
var w = window.open(
frappe.urllib.get_full_url(
"/api/method/erpnext.regional.italy.utils.generate_single_invoice?"
+ "docname=" + frm.doc.name
)
)
if (!w) {
frappe.msgprint(__("Please enable pop-ups")); return;
}
});
}
}
});
};

View File

@@ -10,12 +10,12 @@ from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
from erpnext.regional.italy import fiscal_regimes, tax_exemption_reasons, mode_of_payment_codes, vat_collectability_options
def setup(company=None, patch=True):
make_custom_fields()
setup_report()
make_custom_fields()
setup_report()
def make_custom_fields(update=True):
invoice_item_fields = [
dict(fieldname='tax_rate', label='Tax Rate',
invoice_item_fields = [
dict(fieldname='tax_rate', label='Tax Rate',
fieldtype='Float', insert_after='description',
print_hide=1, hidden=1, read_only=1),
dict(fieldname='tax_amount', label='Tax Amount',
@@ -24,135 +24,138 @@ def make_custom_fields(update=True):
dict(fieldname='total_amount', label='Total Amount',
fieldtype='Currency', insert_after='tax_amount',
print_hide=1, hidden=1, read_only=1, options="currency")
]
]
custom_fields = {
'Company': [
dict(fieldname='sb_e_invoicing', label='E-Invoicing',
fieldtype='Section Break', insert_after='date_of_establishment', print_hide=1),
dict(fieldname='fiscal_regime', label='Fiscal Regime',
fieldtype='Select', insert_after='sb_e_invoicing', print_hide=1,
options="\n".join(map(lambda x: x.decode('utf-8'), fiscal_regimes))),
dict(fieldname='fiscal_code', label='Fiscal Code', fieldtype='Data', insert_after='fiscal_regime', print_hide=1,
description=_("Applicable if the company is an Individual or a Proprietorship")),
dict(fieldname='vat_collectability', label='VAT Collectability',
fieldtype='Select', insert_after='fiscal_code', print_hide=1,
options="\n".join(map(lambda x: x.decode('utf-8'), vat_collectability_options))),
dict(fieldname='cb_e_invoicing1', fieldtype='Column Break', insert_after='vat_collectability', print_hide=1),
dict(fieldname='registrar_office_province', label='Province of the Registrar Office',
fieldtype='Data', insert_after='cb_e_invoicing1', print_hide=1, length=2),
dict(fieldname='registration_number', label='Registration Number',
fieldtype='Data', insert_after='registrar_office_province', print_hide=1, length=20),
dict(fieldname='share_capital_amount', label='Share Capital',
fieldtype='Currency', insert_after='registration_number', print_hide=1,
description=_('Applicable if the company is SpA, SApA or SRL')),
dict(fieldname='no_of_members', label='No of Members',
fieldtype='Select', insert_after='share_capital_amount', print_hide=1,
options="\nSU-Socio Unico\nSM-Piu Soci", description=_("Applicable if the company is a limited liability company")),
dict(fieldname='liquidation_state', label='Liquidation State',
fieldtype='Select', insert_after='no_of_members', print_hide=1,
options="\nLS-In Liquidazione\nLN-Non in Liquidazione")
],
'Sales Taxes and Charges': [
dict(fieldname='tax_exemption_reason', label='Tax Exemption Reason',
fieldtype='Select', insert_after='included_in_print_rate', print_hide=1,
depends_on='eval:doc.charge_type!="Actual" && doc.rate==0.0',
options="\n" + "\n".join(map(lambda x: x.decode('utf-8'), tax_exemption_reasons))),
dict(fieldname='tax_exemption_law', label='Tax Exempt Under',
fieldtype='Text', insert_after='tax_exemption_reason', print_hide=1,
depends_on='eval:doc.charge_type!="Actual" && doc.rate==0.0')
],
'Customer': [
dict(fieldname='fiscal_code', label='Fiscal Code', fieldtype='Data', insert_after='tax_id', print_hide=1),
dict(fieldname='recipient_code', label='Recipient Code',
fieldtype='Data', insert_after='fiscal_code', print_hide=1, default="0000000"),
dict(fieldname='pec', label='Recipient PEC',
fieldtype='Data', insert_after='fiscal_code', print_hide=1),
dict(fieldname='is_public_administration', label='Is Public Administration',
fieldtype='Check', insert_after='is_internal_customer', print_hide=1,
description=_("Set this if the customer is a Public Administration company."),
depends_on='eval:doc.customer_type=="Company"'),
dict(fieldname='first_name', label='First Name', fieldtype='Data',
insert_after='salutation', print_hide=1, depends_on='eval:doc.customer_type!="Company"'),
dict(fieldname='last_name', label='Last Name', fieldtype='Data',
insert_after='first_name', print_hide=1, depends_on='eval:doc.customer_type!="Company"')
],
'Mode of Payment': [
dict(fieldname='mode_of_payment_code', label='Code',
fieldtype='Select', insert_after='included_in_print_rate', print_hide=1,
options="\n".join(map(lambda x: x.decode('utf-8'), mode_of_payment_codes)))
],
'Payment Schedule': [
dict(fieldname='mode_of_payment_code', label='Code',
fieldtype='Select', insert_after='mode_of_payment', print_hide=1,
options="\n".join(map(lambda x: x.decode('utf-8'), mode_of_payment_codes)),
fetch_from="mode_of_payment.mode_of_payment_code", read_only=1),
dict(fieldname='bank_account', label='Bank Account',
fieldtype='Link', insert_after='mode_of_payment_code', print_hide=1,
options="Bank Account"),
dict(fieldname='bank_account_name', label='Bank Account Name',
fieldtype='Data', insert_after='bank_account', print_hide=1,
fetch_from="bank_account.account_name", read_only=1),
dict(fieldname='bank_account_no', label='Bank Account No',
fieldtype='Data', insert_after='bank_account_name', print_hide=1,
fetch_from="bank_account.bank_account_no", read_only=1),
dict(fieldname='bank_account_iban', label='IBAN',
fieldtype='Data', insert_after='bank_account_name', print_hide=1,
fetch_from="bank_account.iban", read_only=1),
],
"Sales Invoice": [
dict(fieldname='vat_collectability', label='VAT Collectability',
fieldtype='Select', insert_after='taxes_and_charges', print_hide=1,
options="\n".join(map(lambda x: x.decode('utf-8'), vat_collectability_options)),
fetch_from="company.vat_collectability"),
dict(fieldname='sb_e_invoicing_reference', label='E-Invoicing',
fieldtype='Section Break', insert_after='pos_total_qty', print_hide=1),
dict(fieldname='company_tax_id', label='Company Tax ID',
fieldtype='Data', insert_after='sb_e_invoicing_reference', print_hide=1, read_only=1,
fetch_from="company.tax_id"),
dict(fieldname='company_fiscal_code', label='Company Fiscal Code',
fieldtype='Data', insert_after='company_tax_id', print_hide=1, read_only=1,
fetch_from="company.fiscal_code"),
dict(fieldname='company_fiscal_regime', label='Company Fiscal Regime',
fieldtype='Data', insert_after='company_fiscal_code', print_hide=1, read_only=1,
fetch_from="company.fiscal_regime"),
dict(fieldname='cb_e_invoicing_reference', fieldtype='Column Break',
insert_after='company_fiscal_regime', print_hide=1),
dict(fieldname='customer_fiscal_code', label='Customer Fiscal Code',
fieldtype='Data', insert_after='cb_e_invoicing_reference', read_only=1,
fetch_from="customer.fiscal_code"),
],
'Purchase Invoice Item': invoice_item_fields,
custom_fields = {
'Company': [
dict(fieldname='sb_e_invoicing', label='E-Invoicing',
fieldtype='Section Break', insert_after='date_of_establishment', print_hide=1),
dict(fieldname='fiscal_regime', label='Fiscal Regime',
fieldtype='Select', insert_after='sb_e_invoicing', print_hide=1,
options="\n".join(map(lambda x: frappe.safe_decode(x, encoding='utf-8'), fiscal_regimes))),
dict(fieldname='fiscal_code', label='Fiscal Code', fieldtype='Data', insert_after='fiscal_regime', print_hide=1,
description=_("Applicable if the company is an Individual or a Proprietorship")),
dict(fieldname='vat_collectability', label='VAT Collectability',
fieldtype='Select', insert_after='fiscal_code', print_hide=1,
options="\n".join(map(lambda x: frappe.safe_decode(x, encoding='utf-8'), vat_collectability_options))),
dict(fieldname='cb_e_invoicing1', fieldtype='Column Break', insert_after='vat_collectability', print_hide=1),
dict(fieldname='registrar_office_province', label='Province of the Registrar Office',
fieldtype='Data', insert_after='cb_e_invoicing1', print_hide=1, length=2),
dict(fieldname='registration_number', label='Registration Number',
fieldtype='Data', insert_after='registrar_office_province', print_hide=1, length=20),
dict(fieldname='share_capital_amount', label='Share Capital',
fieldtype='Currency', insert_after='registration_number', print_hide=1,
description=_('Applicable if the company is SpA, SApA or SRL')),
dict(fieldname='no_of_members', label='No of Members',
fieldtype='Select', insert_after='share_capital_amount', print_hide=1,
options="\nSU-Socio Unico\nSM-Piu Soci", description=_("Applicable if the company is a limited liability company")),
dict(fieldname='liquidation_state', label='Liquidation State',
fieldtype='Select', insert_after='no_of_members', print_hide=1,
options="\nLS-In Liquidazione\nLN-Non in Liquidazione")
],
'Sales Taxes and Charges': [
dict(fieldname='tax_exemption_reason', label='Tax Exemption Reason',
fieldtype='Select', insert_after='included_in_print_rate', print_hide=1,
depends_on='eval:doc.charge_type!="Actual" && doc.rate==0.0',
options="\n" + "\n".join(map(lambda x: frappe.safe_decode(x, encoding='utf-8'), tax_exemption_reasons))),
dict(fieldname='tax_exemption_law', label='Tax Exempt Under',
fieldtype='Text', insert_after='tax_exemption_reason', print_hide=1,
depends_on='eval:doc.charge_type!="Actual" && doc.rate==0.0')
],
'Customer': [
dict(fieldname='fiscal_code', label='Fiscal Code', fieldtype='Data', insert_after='tax_id', print_hide=1),
dict(fieldname='recipient_code', label='Recipient Code',
fieldtype='Data', insert_after='fiscal_code', print_hide=1, default="0000000"),
dict(fieldname='pec', label='Recipient PEC',
fieldtype='Data', insert_after='fiscal_code', print_hide=1),
dict(fieldname='is_public_administration', label='Is Public Administration',
fieldtype='Check', insert_after='is_internal_customer', print_hide=1,
description=_("Set this if the customer is a Public Administration company."),
depends_on='eval:doc.customer_type=="Company"'),
dict(fieldname='first_name', label='First Name', fieldtype='Data',
insert_after='salutation', print_hide=1, depends_on='eval:doc.customer_type!="Company"'),
dict(fieldname='last_name', label='Last Name', fieldtype='Data',
insert_after='first_name', print_hide=1, depends_on='eval:doc.customer_type!="Company"')
],
'Mode of Payment': [
dict(fieldname='mode_of_payment_code', label='Code',
fieldtype='Select', insert_after='included_in_print_rate', print_hide=1,
options="\n".join(map(lambda x: frappe.safe_decode(x, encoding='utf-8'), mode_of_payment_codes)))
],
'Payment Schedule': [
dict(fieldname='mode_of_payment_code', label='Code',
fieldtype='Select', insert_after='mode_of_payment', print_hide=1,
options="\n".join(map(lambda x: frappe.safe_decode(x, encoding='utf-8'), mode_of_payment_codes)),
fetch_from="mode_of_payment.mode_of_payment_code", read_only=1),
dict(fieldname='bank_account', label='Bank Account',
fieldtype='Link', insert_after='mode_of_payment_code', print_hide=1,
options="Bank Account"),
dict(fieldname='bank_account_name', label='Bank Name',
fieldtype='Data', insert_after='bank_account', print_hide=1,
fetch_from="bank_account.bank", read_only=1),
dict(fieldname='bank_account_no', label='Bank Account No',
fieldtype='Data', insert_after='bank_account_name', print_hide=1,
fetch_from="bank_account.bank_account_no", read_only=1),
dict(fieldname='bank_account_iban', label='IBAN',
fieldtype='Data', insert_after='bank_account_name', print_hide=1,
fetch_from="bank_account.iban", read_only=1),
dict(fieldname='bank_account_swift_number', label='Swift Code (BIC)',
fieldtype='Data', insert_after='bank_account_iban', print_hide=1,
fetch_from="bank_account.swift_number", read_only=1),
],
"Sales Invoice": [
dict(fieldname='vat_collectability', label='VAT Collectability',
fieldtype='Select', insert_after='taxes_and_charges', print_hide=1,
options="\n".join(map(lambda x: frappe.safe_decode(x, encoding='utf-8'), vat_collectability_options)),
fetch_from="company.vat_collectability"),
dict(fieldname='sb_e_invoicing_reference', label='E-Invoicing',
fieldtype='Section Break', insert_after='pos_total_qty', print_hide=1),
dict(fieldname='company_tax_id', label='Company Tax ID',
fieldtype='Data', insert_after='sb_e_invoicing_reference', print_hide=1, read_only=1,
fetch_from="company.tax_id"),
dict(fieldname='company_fiscal_code', label='Company Fiscal Code',
fieldtype='Data', insert_after='company_tax_id', print_hide=1, read_only=1,
fetch_from="company.fiscal_code"),
dict(fieldname='company_fiscal_regime', label='Company Fiscal Regime',
fieldtype='Data', insert_after='company_fiscal_code', print_hide=1, read_only=1,
fetch_from="company.fiscal_regime"),
dict(fieldname='cb_e_invoicing_reference', fieldtype='Column Break',
insert_after='company_fiscal_regime', print_hide=1),
dict(fieldname='customer_fiscal_code', label='Customer Fiscal Code',
fieldtype='Data', insert_after='cb_e_invoicing_reference', read_only=1,
fetch_from="customer.fiscal_code"),
],
'Purchase Invoice Item': invoice_item_fields,
'Sales Order Item': invoice_item_fields,
'Delivery Note Item': invoice_item_fields,
'Sales Invoice Item': invoice_item_fields,
'Sales Invoice Item': invoice_item_fields,
'Quotation Item': invoice_item_fields,
'Purchase Order Item': invoice_item_fields,
'Purchase Receipt Item': invoice_item_fields,
'Supplier Quotation Item': invoice_item_fields,
'Address': [
dict(fieldname='country_code', label='Country Code',
fieldtype='Data', insert_after='country', print_hide=1, read_only=1,
fetch_from="country.code"),
dict(fieldname='state_code', label='State Code',
fieldtype='Data', insert_after='state', print_hide=1)
]
}
'Address': [
dict(fieldname='country_code', label='Country Code',
fieldtype='Data', insert_after='country', print_hide=1, read_only=0,
fetch_from="country.code"),
dict(fieldname='state_code', label='State Code',
fieldtype='Data', insert_after='state', print_hide=1)
]
}
create_custom_fields(custom_fields, ignore_validate = frappe.flags.in_patch, update=update)
create_custom_fields(custom_fields, ignore_validate = frappe.flags.in_patch, update=update)
def setup_report():
report_name = 'Electronic Invoice Register'
report_name = 'Electronic Invoice Register'
frappe.db.sql(""" update `tabReport` set disabled = 0 where
name = %s """, report_name)
frappe.db.sql(""" update `tabReport` set disabled = 0 where
name = %s """, report_name)
if not frappe.db.get_value('Custom Role', dict(report=report_name)):
frappe.get_doc(dict(
doctype='Custom Role',
report=report_name,
roles= [
dict(role='Accounts User'),
dict(role='Accounts Manager')
]
)).insert()
if not frappe.db.get_value('Custom Role', dict(report=report_name)):
frappe.get_doc(dict(
doctype='Custom Role',
report=report_name,
roles= [
dict(role='Accounts User'),
dict(role='Accounts Manager')
]
)).insert()

View File

@@ -183,10 +183,20 @@ def get_invoice_summary(items, taxes):
#Preflight for successful e-invoice export.
def sales_invoice_validate(doc):
#Validate company
if doc.doctype != 'Sales Invoice':
return
if not doc.company_address:
frappe.throw(_("Please set an Address on the Company '%s'" % doc.company), title=_("E-Invoicing Information Missing"))
else:
validate_address(doc.company_address, "Company")
validate_address(doc.company_address)
company_fiscal_regime = frappe.get_cached_value("Company", doc.company, 'fiscal_regime')
if not company_fiscal_regime:
frappe.throw(_("Fiscal Regime is mandatory, kindly set the fiscal regime in the company {0}")
.format(doc.company))
else:
doc.company_fiscal_regime = company_fiscal_regime
if not doc.company_tax_id and not doc.company_fiscal_code:
frappe.throw(_("Please set either the Tax ID or Fiscal Code on Company '%s'" % doc.company), title=_("E-Invoicing Information Missing"))
@@ -207,7 +217,7 @@ def sales_invoice_validate(doc):
if not doc.customer_address:
frappe.throw(_("Please set the Customer Address"), title=_("E-Invoicing Information Missing"))
else:
validate_address(doc.customer_address, "Customer")
validate_address(doc.customer_address)
if not len(doc.taxes):
frappe.throw(_("Please set at least one row in the Taxes and Charges Table"), title=_("E-Invoicing Information Missing"))
@@ -217,10 +227,18 @@ def sales_invoice_validate(doc):
frappe.throw(_("Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges".format(row.idx)),
title=_("E-Invoicing Information Missing"))
for schedule in doc.payment_schedule:
if schedule.mode_of_payment and not schedule.mode_of_payment_code:
schedule.mode_of_payment_code = frappe.get_cached_value('Mode of Payment',
schedule.mode_of_payment, 'mode_of_payment_code')
#Ensure payment details are valid for e-invoice.
def sales_invoice_on_submit(doc):
def sales_invoice_on_submit(doc, method):
#Validate payment details
if get_company_country(doc.company) not in ['Italy',
'Italia', 'Italian Republic', 'Repubblica Italiana']:
return
if not len(doc.payment_schedule):
frappe.throw(_("Please set the Payment Schedule"), title=_("E-Invoicing Information Missing"))
else:
@@ -234,38 +252,61 @@ def sales_invoice_on_submit(doc):
prepare_and_attach_invoice(doc)
def prepare_and_attach_invoice(doc):
progressive_name, progressive_number = get_progressive_name_and_number(doc)
def prepare_and_attach_invoice(doc, replace=False):
progressive_name, progressive_number = get_progressive_name_and_number(doc, replace)
invoice = prepare_invoice(doc, progressive_number)
invoice_xml = frappe.render_template('erpnext/regional/italy/e-invoice.xml', context={"doc": invoice}, is_path=True)
invoice_xml = invoice_xml.replace("&", "&amp;")
xml_filename = progressive_name + ".xml"
save_file(xml_filename, invoice_xml, dt=doc.doctype, dn=doc.name, is_private=True)
return save_file(xml_filename, invoice_xml, dt=doc.doctype, dn=doc.name, is_private=True)
@frappe.whitelist()
def generate_single_invoice(docname):
doc = frappe.get_doc("Sales Invoice", docname)
e_invoice = prepare_and_attach_invoice(doc, True)
content = None
with open(frappe.get_site_path('private', 'files', e_invoice.file_name), "r") as f:
content = f.read()
frappe.local.response.filename = e_invoice.file_name
frappe.local.response.filecontent = content
frappe.local.response.type = "download"
#Delete e-invoice attachment on cancel.
def sales_invoice_on_cancel(doc):
def sales_invoice_on_cancel(doc, method):
if get_company_country(doc.company) not in ['Italy',
'Italia', 'Italian Republic', 'Repubblica Italiana']:
return
for attachment in get_e_invoice_attachments(doc):
remove_file(attachment.name, attached_to_doctype=doc.doctype, attached_to_name=doc.name)
def get_company_country(company):
return frappe.get_cached_value('Company', company, 'country')
def get_e_invoice_attachments(invoice):
out = []
attachments = get_attachments(invoice.doctype, invoice.name)
company_tax_id = invoice.company_tax_id if invoice.company_tax_id.startswith("IT") else "IT" + invoice.company_tax_id
for attachment in attachments:
if attachment.file_name.startswith(company_tax_id) and attachment.file_name.endswith(".xml"):
if attachment.file_name and attachment.file_name.startswith(company_tax_id) and attachment.file_name.endswith(".xml"):
out.append(attachment)
return out
def validate_address(address_name, address_context):
pincode, city = frappe.db.get_value("Address", address_name, ["pincode", "city"])
if not pincode:
frappe.throw(_("Please set pin code on %s Address" % address_context), title=_("E-Invoicing Information Missing"))
if not city:
frappe.throw(_("Please set city on %s Address" % address_context), title=_("E-Invoicing Information Missing"))
def validate_address(address_name):
fields = ["pincode", "city", "country_code"]
data = frappe.get_cached_value("Address", address_name, fields, as_dict=1) or {}
for field in fields:
if not data.get(field):
frappe.throw(_("Please set {0} for address {1}".format(field.replace('-',''), address_name)),
title=_("E-Invoicing Information Missing"))
def get_unamended_name(doc):
attributes = ["naming_series", "amended_from"]
@@ -278,7 +319,13 @@ def get_unamended_name(doc):
else:
return doc.name
def get_progressive_name_and_number(doc):
def get_progressive_name_and_number(doc, replace=False):
if replace:
for attachment in get_e_invoice_attachments(doc):
remove_file(attachment.name, attached_to_doctype=doc.doctype, attached_to_name=doc.name)
filename = attachment.file_name.split(".xml")[0]
return filename, filename.split("_")[1]
company_tax_id = doc.company_tax_id if doc.company_tax_id.startswith("IT") else "IT" + doc.company_tax_id
progressive_name = frappe.model.naming.make_autoname(company_tax_id + "_.#####")
progressive_number = progressive_name.split("_")[1]
@@ -286,6 +333,12 @@ def get_progressive_name_and_number(doc):
return progressive_name, progressive_number
def set_state_code(doc, method):
if doc.get('country_code'):
doc.country_code = doc.country_code.upper()
if not doc.get('state'):
return
if not (hasattr(doc, "state_code") and doc.country in ["Italy", "Italia", "Italian Republic", "Repubblica Italiana"]):
return

View File

@@ -33,7 +33,8 @@ frappe.query_reports["Sales Person-wise Transaction Summary"] = {
label: __("Company"),
fieldtype: "Link",
options: "Company",
default: frappe.defaults.get_user_default("Company")
default: frappe.defaults.get_user_default("Company"),
reqd: 1
},
{
fieldname:"item_group",

View File

@@ -15,7 +15,7 @@ def execute(filters=None):
item_details = get_item_details()
data = []
company_currency = get_company_currency(filters["company"])
company_currency = get_company_currency(filters.get("company"))
for d in entries:
if d.stock_qty > 0 or filters.get('show_return_entries', 0):

View File

@@ -16,8 +16,9 @@ def get_setup_progress():
return frappe.local.setup_progress
def get_action_completed_state(action_name):
return [d.is_completed for d in get_setup_progress().actions
if d.action_name == action_name][0]
for d in get_setup_progress().actions:
if d.action_name == action_name:
return d.is_completed
def update_action_completed_state(action_name):
action_table_doc = [d for d in get_setup_progress().actions

View File

@@ -33,7 +33,7 @@ def boot_session(bootinfo):
tabCompany limit 1""") and 'Yes' or 'No'
bootinfo.docs += frappe.db.sql("""select name, default_currency, cost_center, default_terms,
default_letter_head, default_bank_account, enable_perpetual_inventory from `tabCompany`""",
default_letter_head, default_bank_account, enable_perpetual_inventory, country from `tabCompany`""",
as_dict=1, update={"doctype":":Company"})
party_account_types = frappe.db.sql(""" select name, ifnull(account_type, '') from `tabParty Type`""")

View File

@@ -28,7 +28,7 @@ def get_data(item_code=None, warehouse=None, item_group=None,
# user does not have access on warehouse
return []
return frappe.db.get_all('Bin', fields=['item_code', 'warehouse', 'projected_qty',
items = frappe.db.get_all('Bin', fields=['item_code', 'warehouse', 'projected_qty',
'reserved_qty', 'reserved_qty_for_production', 'reserved_qty_for_sub_contract', 'actual_qty', 'valuation_rate'],
or_filters={
'projected_qty': ['!=', 0],
@@ -41,3 +41,10 @@ def get_data(item_code=None, warehouse=None, item_group=None,
order_by=sort_by + ' ' + sort_order,
limit_start=start,
limit_page_length='21')
for item in items:
item.update({
'item_name': frappe.get_cached_value("Item", item.item_code, 'item_name')
})
return items

View File

@@ -391,7 +391,7 @@ def get_invoiced_qty_map(delivery_note):
return invoiced_qty_map
def get_returned_qty_map(sales_orders):
def get_returned_qty_map_against_so(sales_orders):
"""returns a map: {so_detail: returned_qty}"""
returned_qty_map = {}
@@ -403,12 +403,25 @@ def get_returned_qty_map(sales_orders):
return returned_qty_map
def get_returned_qty_map_against_dn(delivery_note):
"""returns a map: {so_detail: returned_qty}"""
returned_qty_map = frappe._dict(frappe.db.sql("""select dn_item.item_code, sum(abs(dn_item.qty)) as qty
from `tabDelivery Note Item` dn_item, `tabDelivery Note` dn
where dn.name = dn_item.parent
and dn.docstatus = 1
and dn.is_return = 1
and dn.return_against = %s
group by dn_item.item_code
""", delivery_note))
return returned_qty_map
@frappe.whitelist()
def make_sales_invoice(source_name, target_doc=None):
doc = frappe.get_doc('Delivery Note', source_name)
sales_orders = [d.against_sales_order for d in doc.items]
returned_qty_map = get_returned_qty_map(sales_orders)
returned_qty_map_against_so = get_returned_qty_map_against_so(sales_orders)
returned_qty_map_against_dn = get_returned_qty_map_against_dn(source_name)
invoiced_qty_map = get_invoiced_qty_map(source_name)
def set_missing_values(source, target):
@@ -428,13 +441,26 @@ def make_sales_invoice(source_name, target_doc=None):
target.update(get_fetch_values("Sales Invoice", 'company_address', target.company_address))
def update_item(source_doc, target_doc, source_parent):
target_doc.qty = (source_doc.qty -
invoiced_qty_map.get(source_doc.name, 0) - returned_qty_map.get(source_doc.so_detail, 0))
target_doc.qty, returned_qty = get_pending_qty(source_doc)
if not source_doc.so_detail:
returned_qty_map_against_dn[source_doc.item_code] = returned_qty
if source_doc.serial_no and source_parent.per_billed > 0:
target_doc.serial_no = get_delivery_note_serial_no(source_doc.item_code,
target_doc.qty, source_parent.name)
def get_pending_qty(item_row):
pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0) - returned_qty_map_against_so.get(item_row.so_detail, 0)
returned_qty = flt(returned_qty_map_against_dn.get(item_row.item_code, 0))
if not item_row.so_detail:
if returned_qty >= pending_qty:
pending_qty = 0
returned_qty -= pending_qty
else:
pending_qty -= returned_qty
returned_qty = 0
return pending_qty, returned_qty
doc = get_mapped_doc("Delivery Note", source_name, {
"Delivery Note": {
"doctype": "Sales Invoice",
@@ -453,7 +479,7 @@ def make_sales_invoice(source_name, target_doc=None):
"cost_center": "cost_center"
},
"postprocess": update_item,
"filter": lambda d: abs(d.qty) - abs(invoiced_qty_map.get(d.name, 0))<=0
"filter": lambda d: get_pending_qty(d)[0]<=0
},
"Sales Taxes and Charges": {
"doctype": "Sales Taxes and Charges",

View File

@@ -636,7 +636,7 @@ class TestDeliveryNote(unittest.TestCase):
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
set_perpetual_inventory(0, company)
def test_make_sales_invoice_from_dn_for_returned_qty(self):
from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
@@ -655,6 +655,33 @@ class TestDeliveryNote(unittest.TestCase):
si = make_sales_invoice(dn.name)
self.assertEquals(si.items[0].qty, 1)
def test_make_sales_invoice_from_dn_with_returned_qty_against_dn(self):
from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice
dn = create_delivery_note(qty=8, do_not_submit=True)
dn.append("items", {
"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC",
"qty": 1,
"rate": 100,
"conversion_factor": 1.0,
"expense_account": "Cost of Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC"
})
dn.submit()
si1 = make_sales_invoice(dn.name)
si1.items[0].qty = 4
si1.items.pop(1)
si1.save()
si1.submit()
create_delivery_note(is_return=1, return_against=dn.name, qty=-2)
si2 = make_sales_invoice(dn.name)
self.assertEquals(si2.items[0].qty, 2)
self.assertEquals(si2.items[1].qty, 1)
def create_delivery_note(**args):
dn = frappe.new_doc("Delivery Note")
args = frappe._dict(args)

View File

@@ -11,7 +11,7 @@ from erpnext.stock.doctype.item_price.item_price import ItemPriceDuplicateItem
class TestItemPrice(unittest.TestCase):
def setUp(self):
frappe.db.sql("delete from `tabItem Price`")
frappe.db.sql("delete from `tabItem Price`")
make_test_records_for_doctype("Item Price", force=True)
def test_duplicate_item(self):

View File

@@ -85,7 +85,7 @@ frappe.ui.form.on('Material Request', {
// stop
frm.add_custom_button(__('Stop'),
() => frm.events.update_status(frm, 'Stop'));
() => frm.events.update_status(frm, 'Stopped'));
}
}

View File

@@ -125,7 +125,7 @@ class PurchaseReceipt(BuyingController):
else:
self.status = "Completed"
# Updating stock ledger should always be called after updating prevdoc status,
# because updating ordered qty, reserved_qty_for_subcontract in bin
# depends upon updated ordered qty in PO
@@ -311,7 +311,7 @@ class PurchaseReceipt(BuyingController):
"\n".join(warehouse_with_no_account))
return process_gl_map(gl_entries)
def get_asset_gl_entry(self, gl_entries):
for d in self.get("items"):
if d.is_fixed_asset:
@@ -405,6 +405,11 @@ def update_billed_amount_based_on_po(po_detail, update_modified=True):
@frappe.whitelist()
def make_purchase_invoice(source_name, target_doc=None):
from frappe.model.mapper import get_mapped_doc
doc = frappe.get_doc('Purchase Receipt', source_name)
purchase_orders = [d.purchase_order for d in doc.items]
returned_qty_map_against_po = get_returned_qty_map_against_po(purchase_orders)
returned_qty_map_against_pr = get_returned_qty_map_against_pr(source_name)
invoiced_qty_map = get_invoiced_qty_map(source_name)
def set_missing_values(source, target):
@@ -417,7 +422,23 @@ def make_purchase_invoice(source_name, target_doc=None):
doc.run_method("calculate_taxes_and_totals")
def update_item(source_doc, target_doc, source_parent):
target_doc.qty = source_doc.qty - invoiced_qty_map.get(source_doc.name, 0)
target_doc.qty, returned_qty = get_pending_qty(source_doc)
if not source_doc.purchase_order_item:
returned_qty_map_against_pr[source_doc.item_code] = returned_qty
def get_pending_qty(item_row):
pending_qty = item_row.qty - invoiced_qty_map.get(item_row.name, 0) \
- returned_qty_map_against_po.get(item_row.purchase_order_item, 0)
returned_qty = flt(returned_qty_map_against_pr.get(item_row.item_code, 0))
if not item_row.purchase_order_item:
if returned_qty >= pending_qty:
pending_qty = 0
returned_qty -= pending_qty
else:
pending_qty -= returned_qty
returned_qty = 0
return pending_qty, returned_qty
doclist = get_mapped_doc("Purchase Receipt", source_name, {
"Purchase Receipt": {
@@ -440,7 +461,7 @@ def make_purchase_invoice(source_name, target_doc=None):
"asset": "asset",
},
"postprocess": update_item,
"filter": lambda d: abs(d.qty) - abs(invoiced_qty_map.get(d.name, 0))<=0
"filter": lambda d: get_pending_qty(d)[0]<=0
},
"Purchase Taxes and Charges": {
"doctype": "Purchase Taxes and Charges",
@@ -462,6 +483,31 @@ def get_invoiced_qty_map(purchase_receipt):
return invoiced_qty_map
def get_returned_qty_map_against_po(purchase_orders):
"""returns a map: {so_detail: returned_qty}"""
returned_qty_map = {}
for name, returned_qty in frappe.get_all('Purchase Order Item', fields = ["name", "returned_qty"],
filters = {'parent': ('in', purchase_orders), 'docstatus': 1}, as_list=1):
if not returned_qty_map.get(name):
returned_qty_map[name] = 0
returned_qty_map[name] += returned_qty
return returned_qty_map
def get_returned_qty_map_against_pr(purchase_receipt):
"""returns a map: {so_detail: returned_qty}"""
returned_qty_map = frappe._dict(frappe.db.sql("""select pr_item.item_code, sum(abs(pr_item.qty)) as qty
from `tabPurchase Receipt Item` pr_item, `tabPurchase Receipt` pr
where pr.name = pr_item.parent
and pr.docstatus = 1
and pr.is_return = 1
and pr.return_against = %s
group by pr_item.item_code
""", purchase_receipt))
return returned_qty_map
@frappe.whitelist()
def make_purchase_return(source_name, target_doc=None):
from erpnext.controllers.sales_and_purchase_return import make_return_doc

View File

@@ -404,6 +404,44 @@ class TestPurchaseReceipt(unittest.TestCase):
set_perpetual_inventory(0, pr.company)
def test_make_purchase_invoice_from_pr_for_returned_qty(self):
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order, create_pr_against_po
po = create_purchase_order()
pr = create_pr_against_po(po.name)
pr1 = make_purchase_receipt(is_return=1, return_against=pr.name, qty=-1, do_not_submit=True)
pr1.items[0].purchase_order = po.name
pr1.items[0].purchase_order_item = po.items[0].name
pr1.submit()
pi = make_purchase_invoice(pr.name)
self.assertEquals(pi.items[0].qty, 3)
def test_make_purchase_invoice_from_dn_with_returned_qty_against_dn(self):
pr1 = make_purchase_receipt(qty=8, do_not_submit=True)
pr1.append("items", {
"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC",
"qty": 1,
"received_qty": 1,
"rate": 100,
"conversion_factor": 1.0,
})
pr1.submit()
pi1 = make_purchase_invoice(pr1.name)
pi1.items[0].qty = 4
pi1.items.pop(1)
pi1.save()
pi1.submit()
make_purchase_receipt(is_return=1, return_against=pr1.name, qty=-2)
pi2 = make_purchase_invoice(pr1.name)
self.assertEquals(pi2.items[0].qty, 2)
self.assertEquals(pi2.items[1].qty, 1)
def get_gl_entries(voucher_type, voucher_no):
return frappe.db.sql("""select account, debit, credit, cost_center
from `tabGL Entry` where voucher_type=%s and voucher_no=%s

View File

@@ -490,7 +490,7 @@ def get_price_list_rate_for(args, item_code):
price_list_rate = get_item_price(item_price_args, item_code)
if price_list_rate:
desired_qty = args.get("qty")
if check_packing_list(price_list_rate[0][0], desired_qty, item_code):
if desired_qty and check_packing_list(price_list_rate[0][0], desired_qty, item_code):
item_price_data = price_list_rate
else:
for field in ["customer", "supplier", "min_qty"]:
@@ -521,12 +521,15 @@ def check_packing_list(price_list_rate_name, desired_qty, item_code):
:param qty: Derised Qt
"""
flag = True
item_price = frappe.get_doc("Item Price", price_list_rate_name)
if desired_qty and item_price.packing_unit:
if item_price.packing_unit:
packing_increment = desired_qty % item_price.packing_unit
if packing_increment == 0:
return True
if packing_increment != 0:
flag = False
return flag
def validate_price_list(args):
if args.get("price_list"):