From 33fe86777c6de18e2f98bbb73962a2ec3772357c Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 2 Aug 2013 12:39:10 +0530 Subject: [PATCH 01/33] [usability] Allow user to edit Price List if this option is checked in Selling Settings [issue] webnotes/erpnext#707 --- selling/doctype/sales_common/sales_common.js | 10 ++++++++++ selling/doctype/selling_settings/selling_settings.py | 5 +++-- selling/doctype/selling_settings/selling_settings.txt | 8 +++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/selling/doctype/sales_common/sales_common.js b/selling/doctype/sales_common/sales_common.js index e59a7474f9c..b3ae0fe17af 100644 --- a/selling/doctype/sales_common/sales_common.js +++ b/selling/doctype/sales_common/sales_common.js @@ -29,6 +29,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this._super(); this.toggle_rounded_total(); this.setup_queries(); + this.toggle_editable_price_list_rate(); }, setup_queries: function() { @@ -317,6 +318,15 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ } }, + toggle_editable_price_list_rate: function() { + var df = wn.meta.get_docfield(this.tname, "ref_rate", this.frm.doc.name); + var editable_price_list_rate = cint(wn.defaults.get_default("editable_price_list_rate")); + + if(df && editable_price_list_rate) { + df.read_only = 0; + } + }, + calculate_taxes_and_totals: function() { this._super(); this.calculate_total_advance("Sales Invoice", "advance_adjustment_details"); diff --git a/selling/doctype/selling_settings/selling_settings.py b/selling/doctype/selling_settings/selling_settings.py index febf3754ef7..b25e987c3f9 100644 --- a/selling/doctype/selling_settings/selling_settings.py +++ b/selling/doctype/selling_settings/selling_settings.py @@ -8,5 +8,6 @@ class DocType: self.doc, self.doclist = d, dl def validate(self): - for key in ["cust_master_name", "customer_group", "territory", "maintain_same_sales_rate"]: - webnotes.conn.set_default(key, self.doc.fields.get(key, "")) + for key in ["cust_master_name", "customer_group", "territory", "maintain_same_sales_rate", + "editable_price_list_rate"]: + webnotes.conn.set_default(key, self.doc.fields.get(key, "")) diff --git a/selling/doctype/selling_settings/selling_settings.txt b/selling/doctype/selling_settings/selling_settings.txt index 934cd41d27b..97a339a4864 100644 --- a/selling/doctype/selling_settings/selling_settings.txt +++ b/selling/doctype/selling_settings/selling_settings.txt @@ -2,7 +2,7 @@ { "creation": "2013-06-25 10:25:16", "docstatus": 0, - "modified": "2013-07-18 12:03:39", + "modified": "2013-08-02 12:09:20", "modified_by": "Administrator", "owner": "Administrator" }, @@ -94,6 +94,12 @@ "fieldtype": "Check", "label": "Maintain Same Rate Throughout Sales Cycle" }, + { + "doctype": "DocField", + "fieldname": "editable_price_list_rate", + "fieldtype": "Check", + "label": "Allow user to edit Price List Rate in transactions" + }, { "doctype": "DocPerm" } From e5c69133a84f07a0568be5b6ea84bdb0fba110bc Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 2 Aug 2013 12:45:00 +0530 Subject: [PATCH 02/33] [minor] moved delivered items to be billed to accounts module --- .../delivered_items_to_be_billed.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.txt b/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.txt index 05983b072d0..a42bcbd74f6 100644 --- a/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.txt +++ b/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.txt @@ -2,7 +2,7 @@ { "creation": "2013-07-30 17:28:49", "docstatus": 0, - "modified": "2013-07-30 18:41:28", + "modified": "2013-08-02 18:41:28", "modified_by": "Administrator", "owner": "Administrator" }, @@ -10,7 +10,7 @@ "doctype": "Report", "is_standard": "Yes", "name": "__common__", - "query": "select\n `tabDelivery Note`.`name` as \"Delivery Note:Link/Delivery Note:120\",\n\t`tabDelivery Note`.`customer` as \"Customer:Link/Customer:120\",\n\t`tabDelivery Note`.`posting_date` as \"Date:Date\",\n\t`tabDelivery Note`.`project_name` as \"Project\",\n\t`tabDelivery Note Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabDelivery Note Item`.`qty` - ifnull((select sum(qty) from `tabSales Invoice Item` \n\t where `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n\t `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\n\t\tas \"Qty:Float:110\",\n\t(`tabDelivery Note Item`.`amount` - ifnull((select sum(amount) from `tabSales Invoice Item` \n where `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\n\t\tas \"Amount:Currency:110\",\n\t`tabDelivery Note Item`.`item_name` as \"Item Name::150\",\n\t`tabDelivery Note Item`.`description` as \"Description::200\"\nfrom `tabDelivery Note`, `tabDelivery Note Item`\nwhere\n `tabDelivery Note`.docstatus = 1 and\n\t`tabDelivery Note`.status != \"Stopped\" and\n `tabDelivery Note`.name = `tabDelivery Note Item`.parent and\n (`tabDelivery Note Item`.qty > ifnull((select sum(qty) from `tabSales Invoice Item` \n where `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\norder by `tabDelivery Note`.`name` desc", + "query": "select\n `tabDelivery Note`.`name` as \"Delivery Note:Link/Delivery Note:120\",\n\t`tabDelivery Note`.`customer` as \"Customer:Link/Customer:120\",\n\t`tabDelivery Note`.`posting_date` as \"Date:Date\",\n\t`tabDelivery Note`.`project_name` as \"Project\",\n\t`tabDelivery Note Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabDelivery Note Item`.`qty` - ifnull((select sum(qty) from `tabSales Invoice Item` \n\t where `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n\t `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\n\t\tas \"Qty:Float:110\",\n\t(`tabDelivery Note Item`.`amount` - ifnull((select sum(amount) from `tabSales Invoice Item` \n where `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\n\t\tas \"Amount:Currency:110\",\n\t`tabDelivery Note Item`.`item_name` as \"Item Name::150\",\n\t`tabDelivery Note Item`.`description` as \"Description::200\"\nfrom `tabDelivery Note`, `tabDelivery Note Item`\nwhere\n `tabDelivery Note`.docstatus = 1 and\n\t`tabDelivery Note`.`status` != \"Stopped\" and\n `tabDelivery Note`.name = `tabDelivery Note Item`.parent and\n (`tabDelivery Note Item`.qty > ifnull((select sum(qty) from `tabSales Invoice Item` \n where `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\norder by `tabDelivery Note`.`name` desc", "ref_doctype": "Sales Invoice", "report_name": "Delivered Items To Be Billed", "report_type": "Query Report" From 79a0534fc035c041e367052cc14e79e0d17f7614 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 2 Aug 2013 12:47:05 +0530 Subject: [PATCH 03/33] [data import tool] [feature] Added ability to import / export documents with child records --- docs/docs.user.setup.masters.md | 11 +++++++++++ docs/docs.user.setup.price_list.md | 5 +++++ docs/docs.user.stock.valuation.md | 27 +++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 docs/docs.user.setup.masters.md create mode 100644 docs/docs.user.setup.price_list.md create mode 100644 docs/docs.user.stock.valuation.md diff --git a/docs/docs.user.setup.masters.md b/docs/docs.user.setup.masters.md new file mode 100644 index 00000000000..ccbc32d8250 --- /dev/null +++ b/docs/docs.user.setup.masters.md @@ -0,0 +1,11 @@ +--- +{ + "_label": "Setting Up Masters", + "_toc": [ + "docs.user.stock.item", + "docs.user.selling.customer", + "docs.user.buying.supplier" + ] +} +--- +First step is setting up your master data. \ No newline at end of file diff --git a/docs/docs.user.setup.price_list.md b/docs/docs.user.setup.price_list.md new file mode 100644 index 00000000000..c746ee7ccf0 --- /dev/null +++ b/docs/docs.user.setup.price_list.md @@ -0,0 +1,5 @@ +--- +{ + "_label": "Price Lists" +} +--- \ No newline at end of file diff --git a/docs/docs.user.stock.valuation.md b/docs/docs.user.stock.valuation.md new file mode 100644 index 00000000000..8ecf8fd7eb0 --- /dev/null +++ b/docs/docs.user.stock.valuation.md @@ -0,0 +1,27 @@ +--- +{ + "_label": "Item Valuation: FIFO and Moving Average" +} +--- +### How are Items Valued? + +One of the major features of any inventory system is that you can find out the value of any item based on its historic or average price. You can also find the value of all your items for your balance sheet. Why is valuation important? + +- The buying price fluctuates. +- The value changes because of some process (value add). +- The value changes because of decay, loss etc. + +You may encounter these terms, so lets clarify: + +- Rate: Rate at which the transaction takes place. +- Valuation Rate: Rate at which the items value is set for your valuation. + +There are two major ways in which ERPNext values your items. + +- **FIFO (First In First Out):** In this system, ERPNext assumes that you will consume / sell those Items first that you bought first. For example, if you buy an Item at price X and then after a few days at price Y. Thus when you sell your Item, ERPNext will reduce the quantity of the Item priced at X first and then Y. + +![FIFO](img/fifo.png) + +- **Moving Average:** In this method, ERPNext assumes that the value of the item at any point is the average price of the units of that Item in stock. For example, if the value of an Item is X in a Warehouse with quantity Y and another quantity Y1 is added to the Warehouse at cost X1, the new value X2 would be: + +> New Value X2 = (X * Y + X1 * Y1) / (Y + Y1) \ No newline at end of file From 6affb78e1fc2587d21fb8288d5ee9f4df7b38c2c Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 2 Aug 2013 12:50:08 +0530 Subject: [PATCH 04/33] [minor] moved delivered items to be billed to accounts module --- .../delivered_items_to_be_billed.txt | 2 +- .../delivered_items_to_be_billed/__init__.py | 0 .../delivered_items_to_be_billed.txt | 22 ------------------- 3 files changed, 1 insertion(+), 23 deletions(-) delete mode 100644 stock/report/delivered_items_to_be_billed/__init__.py delete mode 100644 stock/report/delivered_items_to_be_billed/delivered_items_to_be_billed.txt diff --git a/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.txt b/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.txt index a42bcbd74f6..9bcfe700d73 100644 --- a/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.txt +++ b/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.txt @@ -2,7 +2,7 @@ { "creation": "2013-07-30 17:28:49", "docstatus": 0, - "modified": "2013-08-02 18:41:28", + "modified": "2013-08-02 12:41:28", "modified_by": "Administrator", "owner": "Administrator" }, diff --git a/stock/report/delivered_items_to_be_billed/__init__.py b/stock/report/delivered_items_to_be_billed/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/stock/report/delivered_items_to_be_billed/delivered_items_to_be_billed.txt b/stock/report/delivered_items_to_be_billed/delivered_items_to_be_billed.txt deleted file mode 100644 index 920d00d192a..00000000000 --- a/stock/report/delivered_items_to_be_billed/delivered_items_to_be_billed.txt +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "creation": "2013-07-30 17:28:49", - "docstatus": 0, - "modified": "2013-07-31 11:46:34", - "modified_by": "Administrator", - "owner": "Administrator" - }, - { - "doctype": "Report", - "is_standard": "Yes", - "name": "__common__", - "query": "select\n `tabDelivery Note`.`name` as \"Delivery Note:Link/Delivery Note:120\",\n\t`tabDelivery Note`.`customer` as \"Customer:Link/Customer:120\",\n\t`tabDelivery Note`.`posting_date` as \"Date:Date\",\n\t`tabDelivery Note`.`project_name` as \"Project\",\n\t`tabDelivery Note Item`.`item_code` as \"Item:Link/Item:120\",\n\t(`tabDelivery Note Item`.`qty` - ifnull((select sum(qty) from `tabSales Invoice Item` \n\t where `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n\t `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\n\t\tas \"Qty:Float:110\",\n\t(`tabDelivery Note Item`.`amount` - ifnull((select sum(amount) from `tabSales Invoice Item` \n where `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\n\t\tas \"Amount:Currency:110\",\n\t`tabDelivery Note Item`.`item_name` as \"Item Name::150\",\n\t`tabDelivery Note Item`.`description` as \"Description::200\"\nfrom `tabDelivery Note`, `tabDelivery Note Item`\nwhere\n `tabDelivery Note`.docstatus = 1 and\n\t`tabDelivery Note`.`status` != \"Stopped\" and\n `tabDelivery Note`.name = `tabDelivery Note Item`.parent and\n (`tabDelivery Note Item`.qty > ifnull((select sum(qty) from `tabSales Invoice Item` \n where `tabSales Invoice Item`.delivery_note = `tabDelivery Note`.name and\n `tabSales Invoice Item`.dn_detail = `tabDelivery Note Item`.name), 0))\norder by `tabDelivery Note`.`name` desc", - "ref_doctype": "Delivery Note", - "report_name": "Delivered Items To Be Billed", - "report_type": "Query Report" - }, - { - "doctype": "Report", - "name": "Delivered Items To Be Billed" - } -] \ No newline at end of file From 2b76a5e82a9f496315ae1558984b3005c16fc8bc Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 2 Aug 2013 15:16:59 +0530 Subject: [PATCH 05/33] [minor] fixes to data import tool, docs and lead --- docs/docs.user.setup.data_import.md | 69 ++++++++++++++++++++++------- utilities/demo_docs/Lead.csv | 6 +-- utilities/make_demo.py | 4 ++ 3 files changed, 59 insertions(+), 20 deletions(-) diff --git a/docs/docs.user.setup.data_import.md b/docs/docs.user.setup.data_import.md index ae2ee4bcae2..713275f50e6 100644 --- a/docs/docs.user.setup.data_import.md +++ b/docs/docs.user.setup.data_import.md @@ -5,35 +5,70 @@ --- The Data Import Tool is a great way to upload (or edit) bulk data, specially master data, into the system. To start the tool go to: -> Setup > Data > Data Import Tool +To Open the data import tool, you either go to Setup or go to the Transaction you want to Import. If Data Import is allowed, you will see an Import Button: + +![Start Import](img/import-1.png) The tool has two sections, one to download a template and the second to upload the data. -To upload any type of information, select a type from the drop-down. When you select, the system will give you one or more list of templates you can download. So why multiple templates? +(Note: Only those DocTypes are allowed for Import whose Document Type is "Master" or Allow Import property is set.) -In ERPNext, each master or transaction is defined by a “main table” and “child tables”. These child tables are there because some master tables could have multiple value of certain properties. For example, select Item. Here you will see a number of “child” tables linked to the item table. This is because an Item can have multiple prices, taxes and so on! You must import each table separately. In the child table, you must mention the parent of the row in the “parent” column so that ERPNext knows which Item’s price or tax you are trying to set. +### 1. Downloading The Template -### The Template +Data in ERPNext is stored in tables, much like a spreadsheet with columns and rows of data. Each entity in ERPNext can have multiple child tables associated with it too. The child tables are linked to the parent tables and are implemented where are multiple values for any property. For example an Item can have multiple prices, An Invoice has multiple Items and so on. -Here are a few tips to fill your template: +You can import each table separately, or all at a time. In the child table, you must mention the parent of the row in the “parent” column so that ERPNext knows which Item’s price or tax you are trying to set if you are importing separately. -- Don’t change any cells before the row “----Start entering data below this line----”. -- Leave the first column blank. -- Read the explanations of the columns. -- Some columns are mandatory (the 5th row will tell you which ones those are). -- Columns of type “Link” and “Select” will only accept values from a certain set. -- For “Link” type columns, the value must be present in the table it links to. -- For “Select” the options are given on the 6th row. The value must be one of those. -- Dates: A number of standard date formats are accepted. Please make sure, your dates are added in one of those formats. +![Download The Template](img/import-2.png) -### Overwriting +- Click on the table you want to download or "All Tables" +- For bulk editing, you can click on "Download With Data" -ERPNext also allows you to overwrite all / certain columns. If you want to update certain columns, you can download the template with data.Remember to check on the “Overwrite” box before uploading. +### 2. Fill in the Template + +After downloading the template, open it in a spreadsheet application and fill in the data below the column headings. + +![Spreadsheet](img/import-3.png) + +Then export your template or save it as a **Comma Separated Values** (CSV) file. + +![Spreadsheet](img/import-4.png) + +### 3. Upload the .csv File + +Finally attach the .csv file in the section section click on the "Attach" button. + +![Attach and Upload](img/import-5.png) + +Notes: + +- Make sure that if your application allows, use encoding as UTF-8. +- Keep the ID column blank for new records. +- Make sure you keep the modified column as it is for "All Tables". +- "Parent" column is mandatory for child type tables. + +### 4. Uploading All Tables (Main + Child) + +If you select all tables, you will get columns belonging to all the tables in one row separated by `-` columns. + +If you have multiple child rows then you must start a new main item on a new row. See the example: + + Main Table - Child Table + Column 1 Column 2 Column 3 - Column 1 Column 2 Column 3 + v11 v12 v13 c11 c12 c13 + c14 c15 c17 + v21 v22 v23 c21 c22 c23 + +> To see how its done, enter a few records manually using forms and export "All Tables" with "Download with Data" + +### 5. Overwriting + +ERPNext also allows you to overwrite all / certain columns. If you want to update certain columns, you can download the template with data. Remember to check on the “Overwrite” box before uploading. > Note: For child records, if you select Overwrite, it will delete all the child records of that parent. -### Upload Limitations +### 6. Upload Limitations -ERPNext restricts the amount of data you can upload in one file. Though the number may vary based on the type of data. It is usually safe to upload 100-200 rows of a table at one go. If the system will not accept, then you will see an error. +ERPNext restricts the amount of data you can upload in one file. Though the number may vary based on the type of data. It is usually safe to upload around 1000 rows of a table at one go. If the system will not accept, then you will see an error. Why is this? Uploading a lot of data can cause your system to crash, specially if there are other users doing things in parallel. Hence ERPNext restricts the number of “writes” you can process in one request. diff --git a/utilities/demo_docs/Lead.csv b/utilities/demo_docs/Lead.csv index 9471b215f53..c00ab441625 100644 --- a/utilities/demo_docs/Lead.csv +++ b/utilities/demo_docs/Lead.csv @@ -29,8 +29,8 @@ Start entering data below this line,,,,,,,,,,,,,,,,,,,,,,,,,,, ,,Leo Mikulić,Passive,,Listen Up,LeoMikulic@gustr.com,,,,,,,,,,,,,,,,,,,,, ,,Denisa Jarošová,Passive,,I. Magnin,DenisaJarosova@teleworm.us,,,,,,,,,,,,,,,,,,,,, ,,Janek Rutkowski,Passive,,First Rate Choice,JanekRutkowski@dayrep.com,,,,,,,,,,,,,,,,,,,,, -,,美月 宇藤,Passive,,Multi Tech Development,@gustr.com,,,,,,,,,,,,,,,,,,,,, -,,Даниил Афанасьев,Passive,,National Auto Parts,@einrot.com,,,,,,,,,,,,,,,,,,,,, +,,美月 宇藤,Passive,,Multi Tech Development,mm@gustr.com,,,,,,,,,,,,,,,,,,,,, +,,Даниил Афанасьев,Passive,,National Auto Parts,dd@einrot.com,,,,,,,,,,,,,,,,,,,,, ,,Zorislav Petković,Passive,,Integra Investment Plan,ZorislavPetkovic@cuvox.de,,,,,,,,,,,,,,,,,,,,, ,,Nanao Niwa,Passive,,The Lawn Guru,NanaoNiwa@superrito.com,,,,,,,,,,,,,,,,,,,,, ,,Hreiðar Jörundsson,Passive,,Buena Vista Realty Service,HreiarJorundsson@armyspy.com,,,,,,,,,,,,,,,,,,,,, @@ -60,7 +60,7 @@ Start entering data below this line,,,,,,,,,,,,,,,,,,,,,,,,,,, ,,Mekirinzukushitakufu ,Passive,,Choices,Mekirinzukushitakufu@teleworm.us,,,,,,,,,,,,,,,,,,,,, ,,Mukharbek Sultanovich,Passive,,Megatronic,MukharbekSultanovich@cuvox.de,,,,,,,,,,,,,,,,,,,,, ,,Osman Amanuel,Passive,,Handy Dan,OsmanAmanuel@dayrep.com,,,,,,,,,,,,,,,,,,,,, -,,幸子 阪部,Passive,,Channel Home Centers,@armyspy.com,,,,,,,,,,,,,,,,,,,,, +,,幸子 阪部,Passive,,Channel Home Centers,dd@armyspy.com,,,,,,,,,,,,,,,,,,,,, ,,Masakazu Kamitani,Passive,,Honest Air Group,MasakazuKamitani@superrito.com,,,,,,,,,,,,,,,,,,,,, ,,Omran Sabbagh,Passive,,Pleasures and Pasttimes,OmranNuhaidSabbagh@einrot.com,,,,,,,,,,,,,,,,,,,,, ,,Rikako Matsumura,Passive,,Lazysize,RikakoMatsumura@einrot.com,,,,,,,,,,,,,,,,,,,,, diff --git a/utilities/make_demo.py b/utilities/make_demo.py index 8328853a7c9..a55dc800092 100644 --- a/utilities/make_demo.py +++ b/utilities/make_demo.py @@ -4,6 +4,7 @@ from core.page.data_import_tool.data_import_tool import upload def make(): webnotes.connect() + webnotes.print_messages = True webnotes.mute_emails = True install() complete_setup() @@ -37,6 +38,9 @@ def make_items(): print "Importing Items..." webnotes.uploaded_file = os.path.join(os.path.dirname(__file__), "demo_docs", "Item.csv") upload() + print "Importing Item Prices..." + webnotes.uploaded_file = os.path.join(os.path.dirname(__file__), "demo_docs", "Item_Price.csv") + upload() def make_customers_suppliers_contacts(): print "Importing Customers..." From 3362e1978a143dc21047d14118a3ff42b39c15e5 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 2 Aug 2013 15:24:44 +0530 Subject: [PATCH 06/33] [minor] fixes to data import tool, docs and lead --- docs/docs.user.setup.data_import.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs.user.setup.data_import.md b/docs/docs.user.setup.data_import.md index 713275f50e6..b88b705c1db 100644 --- a/docs/docs.user.setup.data_import.md +++ b/docs/docs.user.setup.data_import.md @@ -36,7 +36,7 @@ Then export your template or save it as a **Comma Separated Values** (CSV) file. ### 3. Upload the .csv File -Finally attach the .csv file in the section section click on the "Attach" button. +Finally attach the .csv file in the section section click on the "Upload and Import" button. ![Attach and Upload](img/import-5.png) From 0b6e59076691f1850ae485cc44feebf3e50b79de Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 2 Aug 2013 16:08:04 +0530 Subject: [PATCH 07/33] [fix] [minor] get supplier details in purchase invoice --- accounts/doctype/purchase_invoice/purchase_invoice.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 141811d0f9c..9e220fd30c0 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -91,19 +91,9 @@ class DocType(BuyingController): return ret def set_supplier_defaults(self): - self.doc.fields.update(self.get_supplier()) self.doc.fields.update(self.get_credit_to()) super(DocType, self).set_supplier_defaults() - def get_supplier(self): - ret = {} - if self.doc.credit_to: - acc = webnotes.conn.get_value('Account',self.doc.credit_to,['master_name', 'credit_days']) - ret['supplier'] = acc[0] - ret['due_date'] = add_days(cstr(self.doc.posting_date), acc and cint(acc[1]) or 0) - - return ret - def get_advances(self): super(DocType, self).get_advances(self.doc.credit_to, "Purchase Invoice Advance", "advance_allocation_details", "debit") From c12553fba1567c517716fe9089298b232d5ea0cc Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 2 Aug 2013 18:20:10 +0530 Subject: [PATCH 08/33] [journal voucher] [minor] added Reference section break in Journal Voucher Detail --- .../journal_voucher_detail/journal_voucher_detail.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/accounts/doctype/journal_voucher_detail/journal_voucher_detail.txt b/accounts/doctype/journal_voucher_detail/journal_voucher_detail.txt index 750449b5242..aea5d1256d8 100644 --- a/accounts/doctype/journal_voucher_detail/journal_voucher_detail.txt +++ b/accounts/doctype/journal_voucher_detail/journal_voucher_detail.txt @@ -2,7 +2,7 @@ { "creation": "2013-02-22 01:27:39", "docstatus": 0, - "modified": "2013-07-10 14:56:33", + "modified": "2013-08-02 18:15:56", "modified_by": "Administrator", "owner": "Administrator" }, @@ -88,6 +88,12 @@ "options": "Company:company:default_currency", "read_only": 1 }, + { + "doctype": "DocField", + "fieldname": "reference", + "fieldtype": "Section Break", + "label": "Reference" + }, { "doctype": "DocField", "fieldname": "against_voucher", From e79d57ca19998ca0fce1617ea6e22335f4c42a46 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 2 Aug 2013 19:31:41 +0530 Subject: [PATCH 09/33] [salary slip] total no. of working days calculation [issue] webnotes/erpnext#285 --- controllers/accounts_controller.py | 5 +- .../deduction_type/test_deduction_type.py | 10 +++ hr/doctype/earning_type/test_earning_type.py | 12 +++ hr/doctype/holiday_list/test_holiday_list.py | 3 +- hr/doctype/hr_settings/__init__.py | 0 hr/doctype/hr_settings/hr_settings.py | 8 ++ hr/doctype/hr_settings/hr_settings.txt | 59 +++++++++++++ .../test_leave_application.py | 10 +++ hr/doctype/leave_type/test_leave_type.py | 5 ++ hr/doctype/salary_manager/salary_manager.py | 30 +++---- hr/doctype/salary_slip/salary_slip.py | 44 +++++++--- hr/doctype/salary_slip/salary_slip.txt | 6 +- hr/doctype/salary_slip/test_salary_slip.py | 85 +++++++++++++++++++ hr/page/hr_home/hr_home.js | 12 +++ patches/august_2013/__init__.py | 0 patches/august_2013/p01_hr_settings.py | 16 ++++ patches/patch_list.py | 1 + .../global_defaults/global_defaults.txt | 11 +-- 18 files changed, 271 insertions(+), 46 deletions(-) create mode 100644 hr/doctype/deduction_type/test_deduction_type.py create mode 100644 hr/doctype/earning_type/test_earning_type.py create mode 100644 hr/doctype/hr_settings/__init__.py create mode 100644 hr/doctype/hr_settings/hr_settings.py create mode 100644 hr/doctype/hr_settings/hr_settings.txt create mode 100644 hr/doctype/salary_slip/test_salary_slip.py create mode 100644 patches/august_2013/__init__.py create mode 100644 patches/august_2013/p01_hr_settings.py diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index e3e5d5eaf38..0a2a20be4f1 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -141,8 +141,9 @@ class AccountsController(TransactionBase): def calculate_taxes_and_totals(self): # validate conversion rate - if not self.doc.currency: - self.doc.currency = get_company_currency(self.doc.company) + company_currency = get_company_currency(self.doc.company) + if not self.doc.currency or self.doc.currency == company_currency: + self.doc.currency = company_currency self.doc.conversion_rate = 1.0 else: validate_conversion_rate(self.doc.currency, self.doc.conversion_rate, diff --git a/hr/doctype/deduction_type/test_deduction_type.py b/hr/doctype/deduction_type/test_deduction_type.py new file mode 100644 index 00000000000..5960aace2d1 --- /dev/null +++ b/hr/doctype/deduction_type/test_deduction_type.py @@ -0,0 +1,10 @@ +test_records = [ + [{ + "doctype": "Deduction Type", + "deduction_name": "_Test Professional Tax" + }], + [{ + "doctype": "Deduction Type", + "deduction_name": "_Test TDS" + }] +] \ No newline at end of file diff --git a/hr/doctype/earning_type/test_earning_type.py b/hr/doctype/earning_type/test_earning_type.py new file mode 100644 index 00000000000..ea245a2e0a3 --- /dev/null +++ b/hr/doctype/earning_type/test_earning_type.py @@ -0,0 +1,12 @@ +test_records = [ + [{ + "doctype": "Earning Type", + "earning_name": "_Test Basic Salary", + "taxable": "Yes" + }], + [{ + "doctype": "Earning Type", + "earning_name": "_Test Allowance", + "taxable": "Yes" + }] +] \ No newline at end of file diff --git a/hr/doctype/holiday_list/test_holiday_list.py b/hr/doctype/holiday_list/test_holiday_list.py index e3a2d829807..07b7fe57710 100644 --- a/hr/doctype/holiday_list/test_holiday_list.py +++ b/hr/doctype/holiday_list/test_holiday_list.py @@ -1,7 +1,8 @@ test_records = [[{ "doctype": "Holiday List", "holiday_list_name": "_Test Holiday List", - "fiscal_year": "_Test Fiscal Year 2013" + "fiscal_year": "_Test Fiscal Year 2013", + "is_default": 1 }, { "doctype": "Holiday", "parent": "_Test Holiday List", diff --git a/hr/doctype/hr_settings/__init__.py b/hr/doctype/hr_settings/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/hr/doctype/hr_settings/hr_settings.py b/hr/doctype/hr_settings/hr_settings.py new file mode 100644 index 00000000000..928aa9ff9f2 --- /dev/null +++ b/hr/doctype/hr_settings/hr_settings.py @@ -0,0 +1,8 @@ +# For license information, please see license.txt + +from __future__ import unicode_literals +import webnotes + +class DocType: + def __init__(self, d, dl): + self.doc, self.doclist = d, dl \ No newline at end of file diff --git a/hr/doctype/hr_settings/hr_settings.txt b/hr/doctype/hr_settings/hr_settings.txt new file mode 100644 index 00000000000..e3694d05727 --- /dev/null +++ b/hr/doctype/hr_settings/hr_settings.txt @@ -0,0 +1,59 @@ +[ + { + "creation": "2013-08-02 13:45:23", + "docstatus": 0, + "modified": "2013-08-02 14:22:26", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "doctype": "DocType", + "document_type": "Other", + "icon": "icon-cog", + "issingle": 1, + "module": "HR", + "name": "__common__" + }, + { + "doctype": "DocField", + "name": "__common__", + "parent": "HR Settings", + "parentfield": "fields", + "parenttype": "DocType", + "permlevel": 0 + }, + { + "create": 1, + "doctype": "DocPerm", + "name": "__common__", + "parent": "HR Settings", + "parentfield": "permissions", + "parenttype": "DocType", + "permlevel": 0, + "read": 1, + "role": "System Manager", + "write": 1 + }, + { + "doctype": "DocType", + "name": "HR Settings" + }, + { + "description": "Employee record is created using selected field. ", + "doctype": "DocField", + "fieldname": "emp_created_by", + "fieldtype": "Select", + "label": "Employee Records to be created by", + "options": "Naming Series\nEmployee Number" + }, + { + "description": "If checked, Total no. of Working Days will include holidays, and this will reduce the value of Salary Per Day", + "doctype": "DocField", + "fieldname": "include_holidays_in_total_working_days", + "fieldtype": "Check", + "label": "Include holidays in Total no. of Working Days" + }, + { + "doctype": "DocPerm" + } +] \ No newline at end of file diff --git a/hr/doctype/leave_application/test_leave_application.py b/hr/doctype/leave_application/test_leave_application.py index 338225c45e7..4acabda263d 100644 --- a/hr/doctype/leave_application/test_leave_application.py +++ b/hr/doctype/leave_application/test_leave_application.py @@ -236,5 +236,15 @@ test_records = [ "fiscal_year": "_Test Fiscal Year 2013", "employee": "_T-Employee-0002", "company": "_Test Company" + }], + [{ + "doctype": "Leave Application", + "leave_type": "_Test Leave Type LWP", + "from_date": "2013-01-02", + "to_date": "2013-01-02", + "posting_date": "2013-01-02", + "fiscal_year": "_Test Fiscal Year 2013", + "employee": "_T-Employee-0001", + "company": "_Test Company", }] ] diff --git a/hr/doctype/leave_type/test_leave_type.py b/hr/doctype/leave_type/test_leave_type.py index 4d789758a47..9b3b240174e 100644 --- a/hr/doctype/leave_type/test_leave_type.py +++ b/hr/doctype/leave_type/test_leave_type.py @@ -2,5 +2,10 @@ test_records = [ [{ "leave_type_name": "_Test Leave Type", "doctype": "Leave Type" + }], + [{ + "leave_type_name": "_Test Leave Type LWP", + "doctype": "Leave Type", + "is_lwp": 1 }] ] \ No newline at end of file diff --git a/hr/doctype/salary_manager/salary_manager.py b/hr/doctype/salary_manager/salary_manager.py index e9b3dd719ea..7a8f1da6afe 100644 --- a/hr/doctype/salary_manager/salary_manager.py +++ b/hr/doctype/salary_manager/salary_manager.py @@ -112,26 +112,16 @@ class DocType: if not sql("""select name from `tabSalary Slip` where docstatus!= 2 and employee = %s and month = %s and fiscal_year = %s and company = %s """, (emp[0], self.doc.month, self.doc.fiscal_year, self.doc.company)): - ss = Document('Salary Slip') - ss.fiscal_year = self.doc.fiscal_year - ss.employee = emp[0] - ss.month = self.doc.month - ss.email_check = self.doc.send_email - ss.company = self.doc.company - ss.save(1) - - ss_obj = get_obj('Salary Slip', ss.name, with_children=1) - ss_obj.get_emp_and_leave_details() - ss_obj.calculate_net_pay() - ss_obj.validate() - ss_obj.doc.save() - - for d in getlist(ss_obj.doclist, 'earning_details'): - d.save() - for d in getlist(ss_obj.doclist, 'deduction_details'): - d.save() - - ss_list.append(ss.name) + ss = webnotes.bean({ + "doctype": "Salary Slip", + "fiscal_year": self.doc.fiscal_year, + "employee": emp[0], + "month": self.doc.month, + "email_check": self.doc.send_email, + "company": self.doc.company, + }) + ss.insert() + ss_list.append(ss.doc.name) return self.create_log(ss_list) diff --git a/hr/doctype/salary_slip/salary_slip.py b/hr/doctype/salary_slip/salary_slip.py index 09bd602da1b..3e943bc94f6 100644 --- a/hr/doctype/salary_slip/salary_slip.py +++ b/hr/doctype/salary_slip/salary_slip.py @@ -61,7 +61,7 @@ class DocType(TransactionBase): ["bank_name", "bank_ac_no", "esic_card_no", "pf_number"], as_dict=1) if emp: self.doc.bank_name = emp.bank_name - self.doc.bank_ac_no = emp.bank_ac_no + self.doc.bank_account_no = emp.bank_ac_no self.doc.esic_no = emp.esic_card_no self.doc.pf_no = emp.pf_number @@ -72,9 +72,17 @@ class DocType(TransactionBase): self.doc.month = "%02d" % getdate(nowdate()).month m = get_obj('Salary Manager').get_month_details(self.doc.fiscal_year, self.doc.month) + holidays = self.get_holidays_for_employee(m) + if not cint(webnotes.conn.get_value("HR Settings", "HR Settings", + "include_holidays_in_total_working_days")): + m["month_days"] -= len(holidays) + if m["month_days"] < 0: + msgprint(_("Bummer! There are more holidays than working days this month."), + raise_exception=True) + if not lwp: - lwp = self.calculate_lwp(m) + lwp = self.calculate_lwp(holidays, m) self.doc.total_days_in_month = m['month_days'] self.doc.leave_without_pay = lwp payment_days = flt(self.get_payment_days(m)) - flt(lwp) @@ -103,11 +111,8 @@ class DocType(TransactionBase): payment_days = 0 return payment_days - - - - - def calculate_lwp(self, m): + + def get_holidays_for_employee(self, m): holidays = sql("""select t1.holiday_date from `tabHoliday` t1, tabEmployee t2 where t1.parent = t2.holiday_list and t2.name = %s @@ -117,8 +122,13 @@ class DocType(TransactionBase): holidays = sql("""select t1.holiday_date from `tabHoliday` t1, `tabHoliday List` t2 where t1.parent = t2.name and ifnull(t2.is_default, 0) = 1 - and t2.fiscal_year = %s""", self.doc.fiscal_year) + and t2.fiscal_year = %s + and t1.holiday_date between %s and %s""", (self.doc.fiscal_year, + m['month_start_date'], m['month_end_date'])) holidays = [cstr(i[0]) for i in holidays] + return holidays + + def calculate_lwp(self, holidays, m): lwp = 0 for d in range(m['month_days']): dt = add_days(cstr(m['month_start_date']), d) @@ -133,7 +143,7 @@ class DocType(TransactionBase): and %s between from_date and to_date """, (self.doc.employee, dt)) if leave: - lwp = cint(leave[0][1]) and lwp + 0.5 or lwp + 1 + lwp = cint(leave[0][1]) and (lwp + 0.5) or (lwp + 1) return lwp def check_existing(self): @@ -150,17 +160,29 @@ class DocType(TransactionBase): def validate(self): from webnotes.utils import money_in_words self.check_existing() + + if not (len(self.doclist.get({"parentfield": "earning_details"})) or + len(self.doclist.get({"parentfield": "deduction_details"}))): + self.get_emp_and_leave_details() + else: + self.get_leave_details(self.doc.leave_without_pay) + + if not self.doc.net_pay: + self.calculate_net_pay() + company_currency = get_company_currency(self.doc.company) self.doc.total_in_words = money_in_words(self.doc.rounded_total, company_currency) def calculate_earning_total(self): self.doc.gross_pay = flt(self.doc.arrear_amount) + flt(self.doc.leave_encashment_amount) - for d in getlist(self.doclist, 'earning_details'): + for d in self.doclist.get({"parentfield": "earning_details"}): if cint(d.e_depends_on_lwp) == 1: d.e_modified_amount = round(flt(d.e_amount) * flt(self.doc.payment_days) / cint(self.doc.total_days_in_month), 2) elif not self.doc.payment_days: d.e_modified_amount = 0 + else: + d.e_modified_amount = d.e_amount self.doc.gross_pay += flt(d.e_modified_amount) def calculate_ded_total(self): @@ -171,6 +193,8 @@ class DocType(TransactionBase): / cint(self.doc.total_days_in_month), 2) elif not self.doc.payment_days: d.d_modified_amount = 0 + else: + d.d_modified_amount = d.d_amount self.doc.total_deduction += flt(d.d_modified_amount) diff --git a/hr/doctype/salary_slip/salary_slip.txt b/hr/doctype/salary_slip/salary_slip.txt index 871c6b850b2..641adae9461 100644 --- a/hr/doctype/salary_slip/salary_slip.txt +++ b/hr/doctype/salary_slip/salary_slip.txt @@ -2,7 +2,7 @@ { "creation": "2013-01-10 16:34:15", "docstatus": 0, - "modified": "2013-07-05 14:53:44", + "modified": "2013-08-02 19:23:13", "modified_by": "Administrator", "owner": "Administrator" }, @@ -190,7 +190,7 @@ "doctype": "DocField", "fieldname": "total_days_in_month", "fieldtype": "Data", - "label": "Total days in month", + "label": "Total Working Days In The Month", "oldfieldname": "total_days_in_month", "oldfieldtype": "Int", "read_only": 1, @@ -208,7 +208,7 @@ "doctype": "DocField", "fieldname": "payment_days", "fieldtype": "Float", - "label": "Payment days", + "label": "Payment Days", "oldfieldname": "payment_days", "oldfieldtype": "Float", "read_only": 1, diff --git a/hr/doctype/salary_slip/test_salary_slip.py b/hr/doctype/salary_slip/test_salary_slip.py new file mode 100644 index 00000000000..e48bf6216f2 --- /dev/null +++ b/hr/doctype/salary_slip/test_salary_slip.py @@ -0,0 +1,85 @@ +import webnotes +import unittest + +class TestSalarySlip(unittest.TestCase): + def setUp(self): + webnotes.conn.sql("""delete from `tabLeave Application`""") + webnotes.conn.sql("""delete from `tabSalary Slip`""") + from hr.doctype.leave_application.test_leave_application import test_records as leave_applications + la = webnotes.bean(copy=leave_applications[4]) + la.insert() + la.doc.status = "Approved" + la.submit() + + def tearDown(self): + webnotes.conn.set_value("HR Settings", "HR Settings", "include_holidays_in_total_working_days", 0) + + def test_salary_slip_with_holidays_included(self): + webnotes.conn.set_value("HR Settings", "HR Settings", "include_holidays_in_total_working_days", 1) + ss = webnotes.bean(copy=test_records[0]) + ss.insert() + self.assertEquals(ss.doc.total_days_in_month, 31) + self.assertEquals(ss.doc.payment_days, 30) + self.assertEquals(ss.doclist[1].e_modified_amount, 14516.13) + self.assertEquals(ss.doclist[2].e_modified_amount, 500) + self.assertEquals(ss.doclist[3].d_modified_amount, 100) + self.assertEquals(ss.doclist[4].d_modified_amount, 48.39) + self.assertEquals(ss.doc.gross_pay, 15016.13) + self.assertEquals(ss.doc.net_pay, 14867.74) + + def test_salary_slip_with_holidays_excluded(self): + ss = webnotes.bean(copy=test_records[0]) + ss.insert() + self.assertEquals(ss.doc.total_days_in_month, 30) + self.assertEquals(ss.doc.payment_days, 29) + self.assertEquals(ss.doclist[1].e_modified_amount, 14500) + self.assertEquals(ss.doclist[2].e_modified_amount, 500) + self.assertEquals(ss.doclist[3].d_modified_amount, 100) + self.assertEquals(ss.doclist[4].d_modified_amount, 48.33) + self.assertEquals(ss.doc.gross_pay, 15000) + self.assertEquals(ss.doc.net_pay, 14851.67) + +test_dependencies = ["Leave Application"] + +test_records = [ + [ + { + "doctype": "Salary Slip", + "employee": "_T-Employee-0001", + "employee_name": "_Test Employee", + "company": "_Test Company", + "fiscal_year": "_Test Fiscal Year 2013", + "month": "01", + "total_days_in_month": 31, + "payment_days": 31 + }, + { + "doctype": "Salary Slip Earning", + "parentfield": "earning_details", + "e_type": "_Test Basic Salary", + "e_amount": 15000, + "e_depends_on_lwp": 1 + }, + { + "doctype": "Salary Slip Earning", + "parentfield": "earning_details", + "e_type": "_Test Allowance", + "e_amount": 500, + "e_depends_on_lwp": 0 + }, + { + "doctype": "Salary Slip Deduction", + "parentfield": "deduction_details", + "d_type": "_Test Professional Tax", + "d_amount": 100, + "d_depends_on_lwp": 0 + }, + { + "doctype": "Salary Slip Deduction", + "parentfield": "deduction_details", + "d_type": "_Test TDS", + "d_amount": 50, + "d_depends_on_lwp": 1 + }, + ] +] \ No newline at end of file diff --git a/hr/page/hr_home/hr_home.js b/hr/page/hr_home/hr_home.js index 21ec1e1fe98..54c3d6685f0 100644 --- a/hr/page/hr_home/hr_home.js +++ b/hr/page/hr_home/hr_home.js @@ -161,6 +161,18 @@ wn.module_page["HR"] = [ }, ] }, + { + title: wn._("Setup"), + icon: "icon-cog", + items: [ + { + "label": wn._("HR Settings"), + "route": "Form/HR Settings", + "doctype":"HR Settings", + "description": "Settings for HR Module" + } + ] + }, { title: wn._("Reports"), right: true, diff --git a/patches/august_2013/__init__.py b/patches/august_2013/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/patches/august_2013/p01_hr_settings.py b/patches/august_2013/p01_hr_settings.py new file mode 100644 index 00000000000..408f1e4357d --- /dev/null +++ b/patches/august_2013/p01_hr_settings.py @@ -0,0 +1,16 @@ +import webnotes + +def execute(): + webnotes.reload_doc("hr", "doctype", "hr_settings") + webnotes.reload_doc("setup", "doctype", "global_defaults") + + hr = webnotes.bean("HR Settings", "HR Settings") + hr.doc.emp_created_by = webnotes.conn.get_value("Global Defaults", "Global Defaults", "emp_created_by") + + if webnotes.conn.sql("""select name from `tabSalary Slip` where docstatus=1 limit 1"""): + hr.doc.include_holidays_in_total_working_days = 1 + + hr.save() + + webnotes.conn.sql("""delete from `tabSingles` where doctype = 'Global Defaults' + and field = 'emp_created_by'""") \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 1426539bbe4..c4c4a8324af 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -264,4 +264,5 @@ patch_list = [ "patches.july_2013.p10_change_partner_user_to_website_user", "patches.july_2013.p11_update_price_list_currency", "execute:webnotes.bean('Selling Settings').save() #2013-07-29", + "patches.august_2013.p01_hr_settings", ] \ No newline at end of file diff --git a/setup/doctype/global_defaults/global_defaults.txt b/setup/doctype/global_defaults/global_defaults.txt index b59ca94c258..8f5b940fb19 100644 --- a/setup/doctype/global_defaults/global_defaults.txt +++ b/setup/doctype/global_defaults/global_defaults.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-02 17:53:24", "docstatus": 0, - "modified": "2013-07-15 15:03:01", + "modified": "2013-08-02 13:45:12", "modified_by": "Administrator", "owner": "Administrator" }, @@ -181,15 +181,6 @@ "label": "HR", "read_only": 0 }, - { - "description": "Employee record is created using selected field. ", - "doctype": "DocField", - "fieldname": "emp_created_by", - "fieldtype": "Select", - "label": "Employee Records to be created by ", - "options": "Naming Series\nEmployee Number", - "read_only": 0 - }, { "doctype": "DocPerm" } From edfba96ce1e9a9c1b27cfd3a74675ae2a93bd5ec Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 5 Aug 2013 11:56:54 +0530 Subject: [PATCH 10/33] [fix] [minor] show company currency fields if included_in_print_rate is checked --- selling/doctype/sales_common/sales_common.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/selling/doctype/sales_common/sales_common.js b/selling/doctype/sales_common/sales_common.js index b3ae0fe17af..964a9847494 100644 --- a/selling/doctype/sales_common/sales_common.js +++ b/selling/doctype/sales_common/sales_common.js @@ -605,7 +605,10 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ // toggle columns var item_grid = this.frm.fields_dict[this.fname].grid; - var show = this.frm.doc.currency != company_currency; + var show = (this.frm.doc.currency != company_currency) || + (wn.model.get_doclist(cur_frm.doctype, cur_frm.docname, + {parentfield: "other_charges", included_in_print_rate: 1}).length); + $.each(["basic_rate", "base_ref_rate", "amount"], function(i, fname) { if(wn.meta.get_docfield(item_grid.doctype, fname)) item_grid.set_column_disp(fname, show); From 5013dcb12cc18ba38d69813602ae1af49db1b745 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 5 Aug 2013 12:16:04 +0530 Subject: [PATCH 11/33] [fix] [minor] change_grid_labels --- public/js/transaction.js | 1 + selling/doctype/sales_common/sales_common.js | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/public/js/transaction.js b/public/js/transaction.js index 4a647adc1cf..6348e5a30e6 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -195,6 +195,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ var company_currency = this.get_company_currency(); this.change_form_labels(company_currency); this.change_grid_labels(company_currency); + this.frm.refresh_fields(); }, recalculate: function() { diff --git a/selling/doctype/sales_common/sales_common.js b/selling/doctype/sales_common/sales_common.js index 964a9847494..20d3a2323c9 100644 --- a/selling/doctype/sales_common/sales_common.js +++ b/selling/doctype/sales_common/sales_common.js @@ -617,7 +617,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ // set labels var $wrapper = $(this.frm.wrapper); $.each(field_label_map, function(fname, label) { - $wrapper.find('[data-grid-fieldname="'+fname+'"]').text(label); + fname = fname.split("-"); + var df = wn.meta.get_docfield(fname[0], fname[1], me.frm.doc.name); + if(df) df.label = label; }); }, From 7895d34d4166650c15f7c3ecf838ad8d80f14e66 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 5 Aug 2013 12:44:10 +0530 Subject: [PATCH 12/33] [fix] [minor] SO/DN required validation and get_single_value deprecated --- accounts/doctype/purchase_invoice/purchase_invoice.py | 4 ++-- accounts/doctype/sales_invoice/sales_invoice.py | 4 ++-- stock/doctype/delivery_note/delivery_note.py | 2 +- stock/doctype/purchase_receipt/purchase_receipt.py | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 9e220fd30c0..693ed844f6a 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -252,14 +252,14 @@ class DocType(BuyingController): self.doc.against_expense_account = ",".join(against_accounts) def po_required(self): - if webnotes.conn.get_single_value("Buying Settings", "po_required") == 'Yes': + if webnotes.conn.get_value("Buying Settings", None, "po_required") == 'Yes': for d in getlist(self.doclist,'entries'): if not d.purchase_order: msgprint("Purchse Order No. required against item %s"%d.item_code) raise Exception def pr_required(self): - if webnotes.conn.get_single_value("Buying Settings", "pr_required") == 'Yes': + if webnotes.conn.get_value("Buying Settings", None, "pr_required") == 'Yes': for d in getlist(self.doclist,'entries'): if not d.purchase_receipt: msgprint("Purchase Receipt No. required against item %s"%d.item_code) diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index 09df5f65121..bf5e201f6b3 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -430,8 +430,8 @@ class DocType(SellingController): def so_dn_required(self): """check in manage account if sales order / delivery note required or not.""" dic = {'Sales Order':'so_required','Delivery Note':'dn_required'} - for i in dic: - if webnotes.conn.get_single_value('Selling Settings', dic[i]) == 'Yes': + for i in dic: + if webnotes.conn.get_value('Selling Settings', None, dic[i]) == 'Yes': for d in getlist(self.doclist,'entries'): if webnotes.conn.get_value('Item', d.item_code, 'is_stock_item') == 'Yes' \ and not d.fields[i.lower().replace(' ','_')]: diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index 25a70b6c662..5df531ea10a 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -85,7 +85,7 @@ class DocType(SellingController): def so_required(self): """check in manage account if sales order required or not""" - if webnotes.conn.get_single_value("Selling Settings", 'so_required') == 'Yes': + if webnotes.conn.get_value("Selling Settings", None, 'so_required') == 'Yes': for d in getlist(self.doclist,'delivery_note_details'): if not d.prevdoc_docname: msgprint("Sales Order No. required against item %s"%d.item_code) diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index 703929ce81a..9daff8faafa 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -118,7 +118,7 @@ class DocType(BuyingController): def po_required(self): - if webnotes.conn.get_single_value("Buying Settings", "po_required") == 'Yes': + if webnotes.conn.get_value("Buying Settings", None, "po_required") == 'Yes': for d in getlist(self.doclist,'purchase_receipt_details'): if not d.prevdoc_docname: msgprint("Purchse Order No. required against item %s"%d.item_code) From 7e405e26b62fadc2447d8c99290b3ddd5ed65b42 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 5 Aug 2013 13:00:20 +0530 Subject: [PATCH 13/33] [fix] [minor] expense head get_query fixed in purchase invoice --- .../doctype/purchase_invoice/purchase_invoice.js | 15 ++++++--------- .../doctype/purchase_invoice/purchase_invoice.py | 16 +++++++++++++++- accounts/doctype/sales_invoice/sales_invoice.py | 1 + 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.js b/accounts/doctype/purchase_invoice/purchase_invoice.js index e71a40815f1..b00cfeadc1a 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -172,16 +172,13 @@ return{ } } -cur_frm.fields_dict['entries'].grid.get_field("expense_head").get_query = function(doc) { +cur_frm.set_query("expense_head", "entries", function(doc) { return{ - filters:{ - 'debit_or_credit':'Debit', - 'account_type': 'Expense Account', - 'group_or_ledger': 'Ledger', - 'company': doc.company - } - } -} + query: "accounts.doctype.purchase_invoice.purchase_invoice.get_expense_account", + filters: {'company': doc.company} + } +}); + cur_frm.cscript.expense_head = function(doc, cdt, cdn){ var d = locals[cdt][cdn]; if(d.idx == 1 && d.expense_head){ diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 693ed844f6a..3f94de31884 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -457,4 +457,18 @@ class DocType(BuyingController): "UOM Conversion Detail", {"parent": d.item_code, "uom": d.uom}, "conversion_factor")) or 1 - d.rm_supp_cost = rm_cost * flt(d.qty) * flt(d.conversion_factor) \ No newline at end of file + d.rm_supp_cost = rm_cost * flt(d.qty) * flt(d.conversion_factor) + +@webnotes.whitelist() +def get_expense_account(doctype, txt, searchfield, start, page_len, filters): + from controllers.queries import get_match_cond + + return webnotes.conn.sql("""select tabAccount.name from `tabAccount` + where (tabAccount.debit_or_credit="Debit" + or tabAccount.account_type = "Expense Account") + and tabAccount.group_or_ledger="Ledger" + and tabAccount.docstatus!=2 + and tabAccount.company = '%(company)s' + and tabAccount.%(key)s LIKE '%(txt)s' + %(mcond)s""" % {'company': filters['company'], 'key': searchfield, + 'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype, searchfield)}) \ No newline at end of file diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index bf5e201f6b3..adadcc81d17 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -979,6 +979,7 @@ def get_bank_cash_account(mode_of_payment): "cash_bank_account": val } +@webnotes.whitelist() def get_income_account(doctype, txt, searchfield, start, page_len, filters): from controllers.queries import get_match_cond From aa71b5b6ea634ac5140917d463269f68b7899767 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 5 Aug 2013 13:00:53 +0530 Subject: [PATCH 14/33] [fix] [minor] show item-wise taxes --- public/js/transaction.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/public/js/transaction.js b/public/js/transaction.js index 6348e5a30e6..34d3cb04298 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -315,15 +315,15 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ var tax_rate = tax_data[0] == null ? "" : (flt(tax_data[0], tax_rate_precision) + "%"), tax_amount = format_currency(flt(tax_data[1], tax_amount_precision), company_currency); - item_tax[item_code][tax.account_head] = [tax_rate, tax_amount]; + item_tax[item_code][tax.name] = [tax_rate, tax_amount]; } else { - item_tax[item_code][tax.account_head] = [flt(tax_data, tax_rate_precision) + "%", ""]; + item_tax[item_code][tax.name] = [flt(tax_data, tax_rate_precision) + "%", ""]; } }); - tax_accounts.push(tax.account_head); + tax_accounts.push([tax.name, tax.account_head]); }); - var headings = $.map([wn._("Item Name")].concat(tax_accounts), + var headings = $.map([wn._("Item Name")].concat($.map(tax_accounts, function(head) { return head[1]; })), function(head) { return '' + (head || "") + "" }).join("\n"); var rows = $.map(this.get_item_doclist(), function(item) { @@ -332,8 +332,8 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ return repl("%(item_name)s%(taxes)s", { item_name: item.item_name, taxes: $.map(tax_accounts, function(head) { - return item_tax_record[head] ? - "(" + item_tax_record[head][0] + ") " + item_tax_record[head][1] + "" : + return item_tax_record[head[0]] ? + "(" + item_tax_record[head[0]][0] + ") " + item_tax_record[head[0]][1] + "" : ""; }).join("\n") }); From 7ee90ab4e68a674949fadd82798a6aeb566dded0 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 5 Aug 2013 13:45:41 +0530 Subject: [PATCH 15/33] [minor] [translation] Fixed German translations file webnotes/erpnext#509 --- translations/de.csv | 1293 ++++++++++++++++++---------------- utilities/demo_docs/Item.csv | 34 +- 2 files changed, 684 insertions(+), 643 deletions(-) diff --git a/translations/de.csv b/translations/de.csv index 106ccd34bb9..c3e9a76505c 100644 --- a/translations/de.csv +++ b/translations/de.csv @@ -1,28 +1,32 @@ (Half Day),(Halber Tag) + against sales order,gegen Kundenauftrag against same operation,gegen dieselbe Operation - already marked,شهدت بالفعل + already marked,bereits markierten and year: ,und Jahr: at warehouse: ,im Warenlager: - by Role ,von Rolle + by Role ,von Role + can not be made.,nicht vorgenommen werden. cannot be 0,nicht 0 sein kann - cannot be deleted.,لا يمكن حذف. - does not belong to the company,لا تنتمي إلى الشركة + cannot be deleted.,kann nicht gelöscht werden. + does not belong to the company,nicht dem Unternehmen gehören has already been submitted.,wurde bereits eingereicht. + has been freezed. ,wurde eingefroren. has been freezed. \ Only Accounts Manager can do transaction against this account,Wurde eingefroren. \ Nur Accounts Manager kann Transaktion gegen dieses Konto zu tun " is less than equals to zero in the system, \ valuation rate is mandatory for this item",weniger als gleich im System Null ist \ Wertansatz für diesen Artikel zwingend is mandatory,zwingend is mandatory for GL Entry,ist für GL Eintrag zwingend is not a ledger,ist nicht ein Ledger is not active,nicht aktiv - is not set,لم يتم تعيين + is not set,nicht gesetzt is now the default Fiscal Year. \ Please refresh your browser for the change to take effect.,"Ist nun der Standard Geschäftsjahr. \ Bitte Ihren Browser aktualisieren, damit die Änderungen wirksam werden." - is present in one or many Active BOMs,موجود في BOMs واحد أو العديد من بالموقع - not active or does not exists in the system,غير نشطة أو لا موجود في نظام + is present in one or many Active BOMs,ist in einer oder mehreren Active BOMs + not active or does not exists in the system,nicht aktiv oder existiert nicht im System not submitted,nicht vorgelegt or the BOM is cancelled or inactive,oder das BOM wird abgebrochen oder inaktiv should be 'Yes'. As Item: ,sollte "Ja". Als Item: should be same as that in ,sollte dieselbe wie die in was on leave on ,war im Urlaub aus + will be ,wird will be over-billed against mentioned ,wird gegen erwähnt überrepräsentiert in Rechnung gestellt werden will become ,werden """Company History""",Firmengeschichte @@ -30,26 +34,26 @@ % Delivered,% Lieferung % Amount Billed,% Rechnungsbetrag % Billed,% Billed -% Completed,٪ مكتمل +% Completed,% Abgeschlossen % Installed,% Installierte % Received,% Erhaltene % of materials billed against this Purchase Order.,% Der Materialien gegen diese Bestellung in Rechnung gestellt. % of materials billed against this Sales Order,% Der Materialien gegen diesen Kundenauftrag abgerechnet % of materials delivered against this Delivery Note,% Der Materialien gegen diese Lieferschein % of materials delivered against this Sales Order,% Der Materialien gegen diesen Kundenauftrag geliefert -% of materials ordered against this Material Request,٪ من المواد المطلوبة ضد هذه المادة طلب +% of materials ordered against this Material Request,% Der bestellten Materialien gegen diesen Werkstoff anfordern % of materials received against this Purchase Order,% Der Materialien erhalten gegen diese Bestellung -"' can not be managed using Stock Reconciliation.\ You can add/delete Serial No directly, \ to modify stock of this item.",'لا يمكن إدارتها باستخدام المصالحة المالية. \ يمكنك إضافة / حذف رقم المسلسل مباشرة، \ لتعديل الأوراق المالية من هذا البند. +"' can not be managed using Stock Reconciliation.\ You can add/delete Serial No directly, \ to modify stock of this item.",'Kann nicht verwaltet mit Lager Versöhnung werden. \ Sie können hinzufügen / löschen Seriennummer direkt \ to stock dieses Artikels ändern. ' in Company: ,'In Unternehmen: -'To Case No.' cannot be less than 'From Case No.','بالقضية رقم' لا يمكن أن يكون أقل من 'من القضية رقم' +'To Case No.' cannot be less than 'From Case No.','To Fall Nr.' kann nicht kleiner sein als "Von Fall Nr. ' * Will be calculated in the transaction.,* Wird in der Transaktion berechnet werden. "**Budget Distribution** helps you distribute your budget across months if you have seasonality in your business.To distribute a budget using this distribution, set this **Budget Distribution** in the **Cost Center**","** Budget Verteilung ** hilft Ihnen verteilen Sie Ihr Budget über Monate, wenn Sie Saisonalität in Ihrem business.To vertreiben ein Budget Verwendung dieser Verteilung, setzen Sie diesen ** Budget Verteilung ** in der ** Cost Center ** haben" **Currency** Master,** Währung ** Meister **Fiscal Year** represents a Financial Year. All accounting entries and other major transactions are tracked against **Fiscal Year**.,** Geschäftsjahr ** ein Geschäftsjahr. Alle Buchungen und anderen wichtigen Transaktionen gegen ** Geschäftsjahr ** verfolgt. -. Outstanding cannot be less than zero. \ Please match exact outstanding.,. المعلقة لا يمكن أن يكون أقل من الصفر. \ الرجاء تطابق تام المعلقة. -. Please set status of the employee as 'Left',. يرجى تغيير الحالة للموظف ب "الزمن" -. You can not mark his attendance as 'Present',. لا يمكنك وضع علامة حضوره ك 'هدية' -"000 is black, fff is white",000 سوداء، بيضاء FFF +. Outstanding cannot be less than zero. \ Please match exact outstanding.,. Herausragende kann nicht kleiner als Null ist. \ Bitte Exakte hervorragend. +. Please set status of the employee as 'Left',. Bitte setzen Sie den Status des Mitarbeiters als "links" +. You can not mark his attendance as 'Present',. Sie können nicht markieren seine Teilnahme als "Gegenwart" +"000 is black, fff is white","000 ist schwarz, weiß fff" 1 Currency = [?] FractionFor e.g. 1 USD = 100 Cent,1 Währung = [?] FractionFor beispielsweise 1 USD = 100 Cent 1. To maintain the customer wise item code and to make them searchable based on their code use this option,Ein. Um den Kunden kluge Artikel Code zu pflegen und um sie durchsuchbar basierend auf ihren Code um diese Option 12px,12px @@ -64,10 +68,10 @@ "To manage Customer Groups, click here"," Kundengruppen zu verwalten, klicken Sie hier " "Manage Item Groups"," Artikel Gruppen verwalten " "To manage Territory, click here"," Um Territory zu verwalten, klicken Sie hier " -"Manage Customer Groups","إدارة مجموعات العملاء" +"Manage Customer Groups","Verwalten von Kunden-Gruppen" "To manage Territory, click here"," Um Territory zu verwalten, klicken Sie hier " -"Manage Item Groups","إدارة مجموعات السلعة" -"Territory","إقليم" +"Manage Item Groups","Artikel verwalten Gruppen" +"Territory","Bereich" "To manage Territory, click here"," Um Territory zu verwalten, klicken Sie hier " "\
  • field:[fieldname] - By Field\
  • naming_series: - By Naming Series (field called naming_series must be present\
  • eval:[expression] - Evaluate an expression in python (self is doc)\
  • Prompt - Prompt user for a name\
  • [series] - Series by prefix (separated by a dot); for example PRE.#####\')"">Naming Options"," \
  • Feld: [Feldname] - Durch Feld \
  • naming_series: - durch die Benennung Series (Feld namens naming_series muss vorhanden sein \
  • eval: [Ausdruck] - Bewerten Sie einen Ausdruck in python (Selbst ist doc) \
  • Prompt - Benutzer nach einem Namen \
  • [Serie] - Series by Prefix (getrennt durch einen Punkt);. zum Beispiel PRE # # # # # \ ') ""> Naming Optionen " Cancel allows you change Submitted documents by cancelling them and amending them., Abbrechen können Sie ändern eingereichten Unterlagen durch Vernichtung von ihnen und zur Änderung ihnen. @@ -76,7 +80,7 @@ A Customer exists with same name,Ein Kunde gibt mit dem gleichen Namen A Lead with this email id should exist,Ein Lead mit dieser E-Mail-ID sollte vorhanden sein "A Product or a Service that is bought, sold or kept in stock.","Ein Produkt oder eine Dienstleistung, die gekauft, verkauft oder gehalten auf Lager." A Supplier exists with same name,Ein Lieferant existiert mit dem gleichen Namen -A condition for a Shipping Rule,وهناك شرط للشحن قاعدة +A condition for a Shipping Rule,Eine Bedingung für einen Versand Rule A logical Warehouse against which stock entries are made.,Eine logische Warehouse gegen die Lager-Einträge vorgenommen werden. A new popup will open that will ask you to select further conditions.,"Ein neues Pop-up öffnet das wird Sie bitten, weitere Bedingungen zu wählen." A symbol for this currency. For e.g. $,Ein Symbol für diese Währung. Für z.B. $ @@ -105,18 +109,19 @@ Account Head,Konto Leiter Account Id,Konto-ID Account Name,Account Name Account Type,Kontotyp -Accounting,المحاسبة -Accounting Year.,السنة المحاسبية. -"Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",قيد محاسبي المجمدة تصل إلى هذا التاريخ، لا أحد يمكن أن تفعل / تعديل إدخال باستثناء دور المحددة أدناه. +Account for this ,Konto für diese +Accounting,Buchhaltung +Accounting Year.,Rechnungsjahres. +"Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.","Buchhaltungseingaben bis zu diesem Zeitpunkt eingefroren, kann niemand / nicht ändern Eintrag außer Rolle unten angegebenen." Accounting journal entries.,Accounting Journaleinträge. Accounts,Konten Accounts Frozen Upto,Konten Bis gefroren Accounts Payable,Kreditorenbuchhaltung Accounts Receivable,Debitorenbuchhaltung -Accounts Settings,إعدادات الحسابات +Accounts Settings,Konten-Einstellungen Action,Aktion Active,Aktiv -Active: Will extract emails from ,Aktiv: Werden E-Mails extrahieren +Active: Will extract emails from ,Aktive: Wird E-Mails zu extrahieren Activity,Aktivität Activity Log,Activity Log Activity Type,Art der Tätigkeit @@ -125,8 +130,8 @@ Actual Budget,Tatsächliche Budget Actual Completion Date,Tatsächliche Datum der Fertigstellung Actual Date,Aktuelles Datum Actual End Date,Actual End Datum -Actual Invoice Date,الفعلي تاريخ الفاتورة -Actual Posting Date,تاريخ النشر الفعلي +Actual Invoice Date,Tag der Rechnungslegung +Actual Posting Date,Tatsächliche Buchungsdatum Actual Qty,Tatsächliche Menge Actual Qty (at source/target),Tatsächliche Menge (an der Quelle / Ziel) Actual Qty After Transaction,Tatsächliche Menge Nach Transaction @@ -140,28 +145,28 @@ Add Attachments,Anhänge hinzufügen Add Bookmark,Lesezeichen hinzufügen Add CSS,Fügen Sie CSS Add Column,Spalte hinzufügen -Add Comment,إضافة تعليق -Add Google Analytics ID: eg. UA-89XXX57-1. Please search help on Google Analytics for more information.,إضافة خدمة Google Analytics ID: على سبيل المثال. UA-89XXX57-1. الرجاء بحث المساعدة على تحليلات جوجل لمزيد من المعلومات. +Add Comment,Kommentar hinzufügen +Add Google Analytics ID: eg. UA-89XXX57-1. Please search help on Google Analytics for more information.,In Google Analytics ID: zB. UA-89XXX57-1. Bitte suchen Sie Hilfe zu Google Analytics für weitere Informationen. Add Message,Nachricht hinzufügen Add New Permission Rule,Add New Permission Rule Add Reply,Fügen Sie Antworten -Add Terms and Conditions for the Material Request. You can also prepare a Terms and Conditions Master and use the Template,إضافة بنود وشروط لطلب المواد. يمكنك أيضا إعداد الشروط والأحكام الماجستير واستخدام القالب +Add Terms and Conditions for the Material Request. You can also prepare a Terms and Conditions Master and use the Template,In Allgemeinen Geschäftsbedingungen für das Material-Request. Sie können auch ein Master-AGB und verwenden Sie die Vorlage Add Terms and Conditions for the Purchase Receipt. You can also prepare a Terms and Conditions Master and use the Template.,Hinzufügen Geschäftsbedingungen für den Kaufbeleg. Sie können auch eine AGB-Master und verwenden Sie die Vorlage. "Add Terms and Conditions for the Quotation like Payment Terms, Validity of Offer etc. You can also prepare a Terms and Conditions Master and use the Template","Fügen AGB für das Angebot wie Zahlungsbedingungen, Gültigkeit des Angebots etc. Sie können auch ein AGB-Master und verwenden Sie die Vorlage" -Add Total Row,إضافة صف الإجمالي -Add a banner to the site. (small banners are usually good),إضافة لافتة إلى الموقع. (لافتات صغيرة عادة ما تكون جيدة) -Add attachment,إضافة المرفقات +Add Total Row,In insgesamt Row +Add a banner to the site. (small banners are usually good),Hinzufügen einen Banner auf der Website. (Kleine Banner sind in der Regel gut) +Add attachment,Anhang hinzufügen Add code as <script>,Fügen Sie Code wie